有限状态机--纠正版

前面写的博客《有限状态机--售报机》有错。

如上图,我们可以发现,本来在30ns时,news_out就应该输出1,但直到下一个上升沿到来时,news_ou才输出1。这种能编译并仿真出来,但没有达到预期效果的,肯定就是逻辑错误啦。下面这个图是教材中,正确的仿真图:



下面,我们来说说上面这个程序的问题所在,就在pres_state=s2这条分支上:

原来写的是:如左图                                                                                        改正后:如右图

                                 

本来s2代表目前已经投入了一块钱,那么当再投入5毛或者1一块钱的时候,就已经完成投入一块五,售报机应该售报了,即rnews_out=1,且next_state应该立马变为初始状态s0;但上面左图写的时,next_state=s3,rnews_out=0;那么在s2状态下,投入一块或五毛达到总币大于等于一块五后,只能等下一个上升沿到来时,才能检测pres_state=s3,并给rnews_out赋值为1;因此,原程序的仿真图总延迟了一个时钟。

修改后仿真图如下:



(1)、建模代码如下:

module fsm5(clock,reset,coin,news_out);
  input clock,reset;
  input [1:0]coin;
  output news_out;
  
  reg [1:0]pres_state;
  reg news_out;
  
  
  parameter s0=2'd0;
  parameter s1=2'd1;
  parameter s2=2'd2;
  parameter s3=2'd3;
  
  
  
  always @(posedge clock)
  begin
    if(!reset)
      pres_state<=s0;
    else
    case(pres_state) 
      s0 :
        case(coin)
          2'd0 : 
          begin
            pres_state<=s0;
            news_out<=0;
          end
          2'd1 : 
          begin
            pres_state<=s1;
            news_out<=0;
          end
          2'd2 : 
          begin
            pres_state<=s2;
            news_out<=0;
          end
        endcase
    
      s1 :
        case(coin)
          2'd0 :
          begin
            pres_state<=s1;
            news_out<=0;
          end
          2'd1 :
          begin
            pres_state<=s2;
            news_out<=0;
          end
          2'd2 : 
          begin
            pres_state<=s0;
            news_out<=1;
          end
        endcase
    
      s2 :
        case(coin)
          2'd0 :
          begin
            pres_state<=s2;
            news_out<=0;
          end
          2'd1 : 
          begin
            pres_state<=s0;
            news_out<=1;
          end
          2'd2 : 
          begin
            pres_state<=s0;
            news_out=1;
          end
        endcase
      s3 :
        begin
          news_out=1;
          pres_state<=s0;
        end
    endcase
  end
 
 
endmodule
      

(2)、仿真代码:

`include "fsm5.v"
module fsm5_stimulus;
  reg CLK,Rst;
  reg [1:0]coin;
  
  wire newspaper;
  
  fsm5 f(CLK,Rst,coin,newspaper);
  
  initial
  begin
    CLK=1'b1;
    Rst=0;
    coin=2'd0;
    #5 Rst=1;
    #200 Rst=0;
    #215 Rst=1;
    //#500 $stop;
  end
  
  always #5 CLK=~CLK;
  
  always @(posedge CLK)
  #20 coin={$random}%3;

  //这块将coin设置成随机数,更好
  
endmodule
  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章