tag 标签: 两段式状态机

相关博文
  • 热度 17
    2016-2-5 14:49
    3337 次阅读|
    0 个评论
    两段式状态机 实验目的: 用两段式状态机描述法设计如图 1 所示的状态图转换图。 图 1 状态转换图 由图 1 可知,状态的跳转和输出信号的控制不仅与复位信号 Reset 有关,还与输入信号 A 有关,同时,输出有 K1 、 K2 两个信号,如果采用一段式状态机描述它则会杂乱无章,甚至会出现漏写语句的情况,故为了描述的状态机条理清晰、缜密,我们决定采用两段式状态机描述该状态转换图,第一段用一个 always 语句块描述状态的跳转,第二段用一个或多个 always 语句块描述输出信号与输入信号或当前状态的关系。需注意:( 1 ) always 的个数不是状态机的段数;( 2 ) always 的个数由输出信号的个数决定,一个 always 块中尽量只对一个输出变量进行赋值(或控制)。代码截图如下: Testbench 代码截图如下: QUARTUS 综合得到的状态转换图如图 2 所示: 图 2 QUARTUS 综合得到的状态转换图 Modelsim 仿真结果如图 3 所示: 图 3 Modelsim 仿真结果截图 由图 3 可知, A 从第 210 ns 开始变为高电平,然后依次产生 101001100110 的序列(以一个时钟周期为基本单位),在 A 的作用下,状态机的状态依次经由 IDLE 、 START 、 CLEAR 向 STOP 跳转,最后由回到 IDLE 状态。在第 290 ns 以前,状态每隔一个时钟周期跳转一次;而在第 290 ns 以后,因为 A 的电平状态变化减慢,故状态每隔两个时钟周期才跳转一次, K1 、 K2 的高电平保持时间也随之增长。 综上所述,采用两段式状态机描述上述状态转换图调理清晰、思维缜密,验证了状态转换的正确性。
  • 热度 26
    2011-4-22 13:39
    5462 次阅读|
    11 个评论
      最近折腾状态机,发现一个小任务对于两段式状态机写法是不可能完成的。这个小任务很简单,先看用一段式状态机实现的代码: module test(             clk,rst_n,             din,dout         );   input clk; input rst_n;    input din; output dout;     parameter IDLE  = 3'd0; parameter STA1  = 3'd1;   //一段式写法 reg cstate; reg cnt;   always @(posedge clk or negedge rst_n)     if(!rst_n) cstate = IDLE;     else begin         case(cstate)             IDLE: begin                     cnt = 4'd0;                     if(din) cstate = STA1;                     else cstate = IDLE;                        end             STA1: begin                     cnt = cnt+1'b1;                     if(cnt == 4'd10) cstate = IDLE;                     else cstate = STA1;                 end             default: cstate = IDLE;         endcase     end   assign dout = cnt;   endmodule   同样的,用三段式状态机也能够实现这个功能: //三段式写法 reg cstate,nstate; reg cnt;   always @(posedge clk or negedge rst_n)     if(!rst_n) cstate = IDLE;     else cstate = nstate;   always @(cstate or din or cnt) begin     case(cstate)         IDLE:   if(din) nstate = STA1;                 else nstate = IDLE;             STA1:   if(cnt == 4'd10) nstate = IDLE;                 else nstate = STA1;         default: nstate = IDLE;     endcase end   always @(posedge clk or negedge rst_n)     if(!rst_n) cnt = 4'd0;     else begin         case(nstate)             IDLE:   cnt = 4'd0;             STA1:   cnt = cnt+1'b1;             default: ;         endcase     end   严格来看,上面的三段式状态机相比于一段式会滞后一个时钟周期。但是我们的重点不在这里,大家大可以不必钻这个牛角尖。另外,这个实例实现的功能本身也没有什么意义,当然也是可以用别的更简单(不需要状态机)的方式实现,但是你可以想象成这是实际应用中状态机各种复杂输出的一部分。     而如果大家希望用两段式状态机实现这个功能,或许会这么写: //两段式写法 reg cstate,nstate; reg cnt;   always @(posedge clk or negedge rst_n)     if(!rst_n) cstate = IDLE;     else cstate = nstate;   always @(cstate or din or cnt) begin     case(cstate)         IDLE: begin                 cnt = 4'd0;                 if(din) nstate = STA1;                 else nstate = IDLE;                 end         STA1: begin                 cnt = cnt+1'b1;                 if(cnt == 4'd10) nstate = IDLE;                 else nstate = STA1;             end         default: nstate = IDLE;     endcase end   如果大家有兴趣对三中代码方式都做一下仿真,会发现一些有意思的问题,尤其两段式状态机最终根本无法退出STA1,计数器cnt也会死在那里。究其根本原因,可大有学问。在编译工程后,出现了数条类似下面的warning: Warning: Found combinational loop of 2 nodes     Warning: Node "Add0~2"     Warning: Node "cnt~9"     何为combinational loop?让handbook来解释吧,看不懂英文的可别怪我~_~ Combinational loops are among the most common causes of instability and unreliability in digital designs. They should be avoided whenever possible. In a synchronous design, feedback loops should include registers. Combinational loops generally violate synchronous design principles by establishing a direct feedback loop that contains no registers. For example, a combinational loop occurs when the left-hand side of an arithmetic expression also appears on the right-hand side in HDL code. A combinational loop also occurs when you feed back the output of a register to an asynchronous pin of the same register through combinational logic, as shown in Figure 5–1.     没有寄存器打一拍的这种combinational loop(组合环)是一种不推荐的设计方式,就如两段式状态机所实现的效果,甚至最终无法实现功能要求。同样的功能,一段式和三段式状态机之所以能够解决这个问题,就是避免了在纯组合逻辑中涉及这个反馈逻辑。在初学verilog时,我们常提的latch(锁存器),其实也是combinational loop的一个特例。