一直想从一段式状态机切换到三段式状态机,从书上和网上不断搜寻三段式案例及方法,感觉很简单,就想拿之前做过的实验把一段式改成三段式,可是写起来并非那么简单,很棘手,改完后也没有成功,尤其状态机里面的计数器,查了一些资料,就一句话带过,把计数器提出来,但怎么提、怎么来保证同步、怎么不让生成latch,并没有仔细的讲清楚。也许自己比较笨吧,一时半会改不出来,当时就想,是不是起步太高了,应该在找一个简单的例程改写,循序渐进。这时就重新阅读黑金的"Verilog那些事儿"教程,看里面哪个例程比较简单,容易改的,结果找到建模篇的实验五例程进行改写,改完后发现三段式写还是比较简单的,思路也比较清晰。当然我跟书上的思路有点不一样,我是这样做的:

产生SOS信号,就是短音(100ms)、间隔(50ms)、长音(300ms),三种音之间的一个组合,可以得到下面波形,这是SOS信号吗?好吧,就是利用三段式产生如下一个波形。

由于不像占空比为50%波形那么有简单,中间要产生不同的占空比高低电平,那么就把它定义成18个状态,加上空闲状态,共19个状态,每个状态,输出高或低就行。

代码实现:

sos.v

 module sos(
//input
sys_clk,
rst_n,
start_cnt, //output
sig_out
);
/*************************************************************/
input sys_clk;
input rst_n;
input start_cnt; output sig_out;
/*************************************************************/
parameter T1MS = 'd49_999;
/*************************************************************/
reg [ : ] cnt;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n)
cnt <= 'd0;
else if(!start_cnt || cnt == T1MS)
cnt <= 'd0;
else if(start_cnt)
cnt <= cnt + 'b1;
else
cnt <= 'd0;
/*************************************************************/
reg [ : ] cnt_ms;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n)
cnt_ms <= 'd0;
else if(start_cnt && cnt == T1MS)
cnt_ms <= cnt_ms + 'b1;
else if(!start_cnt || cnt_ms == 'd1950)
cnt_ms <= 'd0;
/*************************************************************/
parameter IDLE = 'd0 ;
parameter SHORT_1 = 'd1 ;
parameter DLY_1 = 'd2 ;
parameter SHORT_2 = 'd3 ;
parameter DLY_2 = 'd4 ;
parameter SHORT_3 = 'd5 ;
parameter DLY_3 = 'd6 ;
parameter LONG_1 = 'd7 ;
parameter DLY_4 = 'd8 ;
parameter LONG_2 = 'd9 ;
parameter DLY_5 = 'd10 ;
parameter LONG_3 = 'd11 ;
parameter DLY_6 = 'd12 ;
parameter SHORT_4 = 'd13 ;
parameter DLY_7 = 'd14 ;
parameter SHORT_5 = 'd15 ;
parameter DLY_8 = 'd16 ;
parameter SHORT_6 = 'd17 ;
parameter DLY_9 = 'd18 ;
/*************************************************************/
reg [ : ] state_crt,state_nxt;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n)
state_crt <= IDLE;
else
state_crt <= state_nxt;
/*************************************************************/
always @( * )
case(state_crt)
IDLE : state_nxt = SHORT_1;
SHORT_1 : if(cnt_ms == 'd100 ) state_nxt = DLY_1;
else state_nxt = SHORT_1;
DLY_1 : if(cnt_ms == 'd150 ) state_nxt = SHORT_2;
else state_nxt = DLY_1;
SHORT_2 : if(cnt_ms == 'd250 ) state_nxt = DLY_2;
else state_nxt = SHORT_2;
DLY_2 : if(cnt_ms == 'd300 ) state_nxt = SHORT_3;
else state_nxt = DLY_2;
SHORT_3 : if(cnt_ms == 'd400 ) state_nxt = DLY_3;
else state_nxt = SHORT_3;
DLY_3 : if(cnt_ms == 'd450 ) state_nxt = LONG_1;
else state_nxt = DLY_3;
LONG_1 : if(cnt_ms == 'd750 ) state_nxt = DLY_4;
else state_nxt = LONG_1;
DLY_4 : if(cnt_ms == 'd800 ) state_nxt = LONG_2;
else state_nxt = DLY_4;
LONG_2 : if(cnt_ms == 'd1100) state_nxt = DLY_5;
else state_nxt = LONG_2;
DLY_5 : if(cnt_ms == 'd1150) state_nxt = LONG_3;
else state_nxt = DLY_5;
LONG_3 : if(cnt_ms == 'd1450) state_nxt = DLY_6;
else state_nxt = LONG_3;
DLY_6 : if(cnt_ms == 'd1500) state_nxt = SHORT_4;
else state_nxt = DLY_6;
SHORT_4 : if(cnt_ms == 'd1600) state_nxt = DLY_7;
else state_nxt = SHORT_4;
DLY_7 : if(cnt_ms == 'd1650) state_nxt = SHORT_5;
else state_nxt = DLY_7;
SHORT_5 : if(cnt_ms == 'd1750) state_nxt = DLY_8;
else state_nxt = SHORT_5;
DLY_8 : if(cnt_ms == 'd1800) state_nxt = SHORT_6;
else state_nxt = DLY_8;
SHORT_6 : if(cnt_ms == 'd1900) state_nxt = DLY_9;
else state_nxt = SHORT_6;
DLY_9 : if(cnt_ms == 'd1950) state_nxt = IDLE;
else state_nxt = DLY_9;
default : state_nxt = IDLE;
endcase
/*************************************************************/
reg sig_out_temp;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n)
sig_out_temp <= 'b0;
else begin
case(state_nxt)
IDLE : sig_out_temp <= 'b0;
SHORT_1 : sig_out_temp <= 'b1;
DLY_1 : sig_out_temp <= 'b0;
SHORT_2 : sig_out_temp <= 'b1;
DLY_2 : sig_out_temp <= 'b0;
SHORT_3 : sig_out_temp <= 'b1;
DLY_3 : sig_out_temp <= 'b0;
LONG_1 : sig_out_temp <= 'b1;
DLY_4 : sig_out_temp <= 'b0;
LONG_2 : sig_out_temp <= 'b1;
DLY_5 : sig_out_temp <= 'b0;
LONG_3 : sig_out_temp <= 'b1;
DLY_6 : sig_out_temp <= 'b0;
SHORT_4 : sig_out_temp <= 'b1;
DLY_7 : sig_out_temp <= 'b0;
SHORT_5 : sig_out_temp <= 'b1;
DLY_8 : sig_out_temp <= 'b0;
SHORT_6 : sig_out_temp <= 'b1;
DLY_9 : sig_out_temp <= 'b0;
default : sig_out_temp <= 'b0;
endcase
end
/*************************************************************/
assign sig_out = start_cnt ? (~sig_out_temp) : 'b0;
/*************************************************************/
endmodule

sos_top.v

 `timescale 1ns/10ps
module sos_top;
/*************************************************************/
reg sys_clk;
reg rst_n;
wire start_cnt;
/*************************************************************/
initial begin
sys_clk = 'b0;
rst_n = 'b0;
#;
rst_n = 'b1;
end
/*************************************************************/
always # sys_clk = ~sys_clk;
/*************************************************************/
reg [:] cnt;
always @(posedge sys_clk or negedge rst_n)
if(!rst_n)
cnt <= 'd0;
else
cnt <= cnt + 'b1; assign start_cnt = 'b1;//~cnt[27];
/*************************************************************/
sos u1_sos(
//input
.sys_clk(sys_clk),
.rst_n(rst_n),
.start_cnt(start_cnt), //output
.sig_out(sig_out)
);
/*************************************************************/
endmodule

仿真波形:

最后输出进行反向,那是因为书上是驱动蜂鸣器的,而蜂鸣器工作是低电平有效,故输出取反。此实验没有下载到板子上验证,就是做了一个仿真,从仿真波形来看,与设计思想是对的。从上面的波形来看,感觉state_crt和state_nxt貌似基本上在同一时刻变换,其实不是的,state_nxt会比state_crt早一拍,把波形状态切换时刻放大就可以明显看到,如下波形:

简单三段式状态机实验1-SOS的更多相关文章

  1. 简单三段式状态机实验2-LCD12864

    此实验是在“基于I2C EPPRPM(AT24C02B) + LCD12864实验”基础上,把LCD模块里的一段式状态机改成三段式,I2C EPPROM模块暂时未改出来,一步一步来吧,改完后代码下载到 ...

  2. 简单三段式状态机实验3-Sequence Detect(序列检测)

    1.序列检测器的逻辑功能描述:序列检测指的就是将一个指定的序列从数字码流中识别出来.本例中,我们将设计一个"10010”序列的检测器.设x_in为数字码流输入,z_out为检出标记输出,高电 ...

  3. Verilog笔记.三段式状态机

    之前都是用的一段式状态机,逻辑与输出混在一起,复杂点的就比较吃力了. 所以就开始着手三段式状态机. 组合逻辑与时序逻辑分开,这样就能简单许多了. 但是两者在思考方式上也有着很大的区别. 三段式,分作: ...

  4. FPGA三段式状态机的思维陷阱

    用三段式描述状态机的好处,国内外各位大牛都已经说的很多了,大致可归为以下三点: 1.将组合逻辑和时序逻辑分开,利于综合器分析优化和程序维护; 2.更符合设计的思维习惯; 3.代码少,比一段式状态机更简 ...

  5. 10010序列检测器的三段式状态机实现(verilog)

    序列检测器是时序数字电路设计中经典的教学范例,夏宇闻的<verilog数字系统设计教程>一书中有这个例子,用verilog设计一个“10010”序列的检测器.看完后我觉得F和G两个状态多余 ...

  6. 基于FPGA的三段式状态机

    状态机分类: 通常, 状态机的状态数量有限, 称为有限状态机(FSM) .由于状态机所有触发器的时钟由同一脉冲边沿触发, 故也称之为同步状态机. 根据状态机的输出信号是否与电路的输入有关分为 Meal ...

  7. (原创)Verilog三段式状态机

    下面以上图一个简单的FSM说明三段式Verilog状态机范式: `timescale 1ns / 1ps module FSM( clk,rst_n, in1,in2, out1,out2, CS,N ...

  8. Verilog三段式状态机描述

    时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息. 状态机采用VerilogHDL语言编码,建议分为三个always段完成. 三段式建模 ...

  9. verilog 三段式状态机的技巧

    三段式代码多,但是有时钟同步,延时少,组合逻辑跟时序逻辑分开并行出错少. (1)同步状态转移 (2)当前状态判断接下来的状态 (3)动作输出 如果程序复杂可以不止三个always   .always ...

随机推荐

  1. hdu_5677_ztr loves substring(回文+二维多重背包)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5677 题意:给你N个串,问能否选出小于K个回文字符串使得选出的字符串的长度之和为L. 题解:很容易想到 ...

  2. PHP:preg_replace

    关于preg_match: http://www.cnblogs.com/helww/p/3466720.html 关于preg_match_all:暂时没有完整的 preg_replace_call ...

  3. File类与FileInfo类区别

    ile类是静态的,FileInfo不是静态的也没有静态的方法,仅可用于实例化的对象.FileInfo方法基本类似于File.关于二者,作何选择. ● 如果仅进行单一方法调用,则可以使用静态File类上 ...

  4. 最大独立集 HDU 1068

    题目大意:有n个人,两个人之间有相互的关系,问最大的关系数目. 思路:n-(最大匹配数/2).因为这里给出的是n个人之间的两两关系 //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心 ...

  5. curl continue

    http://www.cyberciti.biz/faq/curl-command-resume-broken-download/

  6. 笨方法学python--简介

    该章提到编程新手所需的三种最重要的技术:读和写,注重细节,发现不同. 读 和 写 即熟悉代码中的各种字符. 注 重 细 节 将例子一字不差地打出来,通过实践训练自己 发 现 不 同 这个是通过长年累月 ...

  7. 图解如何 将Excel里的数据导入到sql server数据库中

    项目中,经常会碰到如何将Excel里的数据导入到sql server中的问题. 下面,图解如何实现导入Excel中的数据到sql server 2008 R2: Excel截图如下: 查询pub数据库 ...

  8. 转 Problem: AnyConnect was not able to establish a connection to the specified secu

    不多说直接上问题,在点击连接时,也是能正常连接上输入密码,在输出用户名密码后 连接后,会出现: problem:anyconnect was net able to establish a conne ...

  9. WPF(ContentControl和ItemsControl)

    WPF(ContentControl和ItemsControl) 2013-04-01 16:25 2188人阅读 评论(0) 收藏 举报  分类: .Net(C#)(31)  WPF(25)  版权 ...

  10. HDU 1495 非常可乐 BFS

    题目大意:中文题不说了. 题目思路:我有同学用GCD数论写出来的代码很简洁,但是很抱歉,数论蒟蒻,我觉得比赛的时候我没办法推出.如果用BFS的话思路很简单的,就是6方向广搜,只不过稍微麻烦点.具体看代 ...