有限狀態機--糾正版

前面寫的博客《有限狀態機--售報機》有錯。

如上圖,我們可以發現,本來在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
  



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