有限状态机--自动售报机

来源:互联网 发布:vmp脱壳软件 编辑:程序博客网 时间:2024/06/05 02:48

设计一个有限状态机,不论什么功能,关键点在于:

(1)、状态循环中,有哪些状态,即画出状态转换图;

(2)、改变这些有限状态,有哪些条件;

(3)、最终的输出,即在何种状态下会有输出。

下面就是我的设计啦:


1、设计模块:

module finite_state_module(clock,reset,coin,news_out);
  input clock,reset;
  input [1:0]coin;
  output news_out;
  
  reg [1:0]pres_state,next_state;
  reg rnews_out;
  
  
  parameter s0=2'd0;
  parameter s1=2'd1;
  parameter s2=2'd2;
  parameter s3=2'd3;
  

//下面部分参数定义本想用于表示“不投入钱用x0表示,投入5毛,用x1表示,投入一块,用x2表示,然后在case分支结构中,判断coin=x?”好吧,脑抽了,x?是4位的,coin设置的是2位,两个就不能匹配,只是很神奇的编译时没有报错
  /*parameter x0=4'd0;
  parameter x1=4'd5;
  parameter x2=4'd10;*/
  
  
  always @(posedge clock,negedge reset)
  begin
    if(!reset)
     begin
        pres_state=s0;
        //rnews_out=0;
     end
    else
      pres_state=next_state;
  end
   

//在上面这个always@()中,我真心蠢的想哭,rnews_out是表输出的寄存器,我怎么在reset=0时,可以直接初始化成了0,难怪导致了下图结果,不论,输入如何变化,输出始终为0:


 

 always @(posedge clock,negedge reset)
  begin
    case(pres_state) 
      s0 :
        case(coin)
          2'd0 : 
          begin
            next_state=s0;
            rnews_out=0;
          end
          2'd1 : 
          begin
            next_state=s1;
            rnews_out=0;
          end
          2'd2 : 
          begin
            next_state=s2;
            rnews_out=0;
          end
        endcase
    
      s1 :
        case(coin)
          2'd0 :
          begin
            next_state=s1;
            rnews_out=0;
          end
          2'd1 :
          begin
            next_state=s2;
            rnews_out=0;
          end
          2'd2 : 
          begin
            next_state=s3;
            rnews_out=0;
          end
        endcase
    
      s2 :
        case(coin)
          2'd0 :
          begin
            next_state=s2;
            rnews_out=0;
          end
          2'd1 : 
          begin
            next_state=s3;
            rnews_out=0;
          end
          2'd2 : 
          begin
            next_state=s3;
            rnews_out=0;
          end
        endcase
      s3 :
        begin
          rnews_out=1;
          next_state=s0;
        end
    endcase
  end
    
  assign news_out=rnews_out;
    
endmodule
      
//另外,我在编写代码时,常犯的一个错误就是经常忘了在过程块中使用begin-end语句,特别是在always中(这个错误前几天也犯了好几次)。


2、仿真模块:

`include "finite_state_module.v"
module finite_state_stimulus;
  reg CLK,Rst;
  reg [1:0]coin;
  
  wire newspaper;
  
  finite_state_module fsm(CLK,Rst,coin,newspaper);
  
  initial
  begin
    CLK=1'b1;
    forever #5 CLK=~CLK;
  end
  
  initial
  begin
    Rst=0;
    coin=2'd0;
    #5 Rst=1;
  
    #5 coin=2'd1;
    #10 coin=2'd0;
    #10 coin=2'd1;
    #10 coin=2'd1;
    
    #10 coin=2'd0;
    
    #40 coin=2'd2;
    #10 coin=2'd0;
    #10 coin=2'd2;
    
    #10 coin=2'd1;
    #10 coin=2'd0;
    #40 coin=2'd1;
    #10 coin=2'd1;
    
    #10 coin=2'd0;
    #10 coin=2'd1;
    
    #50 coin=2'd0;
  end
endmodule
  
  //说到仿真,又是蠢的要哭的节奏,今天直接把这句“ finite_state_module fsm(CLK,Rst,coin,newspaper);”给忘写了,不调用实例,那要给谁仿真呢。另外,clock的初始化,我写成:

 initial
  begin
    CLK=1'b1;
    forever  CLK=~CLK;
  end

好吧,clk的翻转忘了给延时,结局就是,我开始仿真,点击“run”按钮后,软件就卡壳了,处于“死机”状态。并出现下面这个警告:

(关于.wlf问题的链接,可以看这个http://blog.csdn.net/jbb0523/article/details/7749660)


//另外,在第二个initial过程块中,我开始写成了

initial
  begin
    Rst=0;
    
    #5 Rst=1;

    coin=2'd0;

出现了下图结果,原因就是我是在仿真#5时刻才给coin初始化为0,在仿真0时刻coin为xx,因此输出news_out一直为x(不确定值)。所以,各个输入变量一定要在仿真时刻初始化好。



3、给个正确的仿真图吧:


//00表示没有投入钱,01表示投入五毛,10表示投入一块,当投入的硬币大于或等于一块五时,等待下一个上升沿到来时,售报机就可以卖出报纸,即news_out=1;之后,news_out又置为0,一切重新开始。


4、教材中写的例子是设计个函数,再在模块中调用函数设计的,具体代码如下:

module vend(clock,reset,coin,news_out);
  input clock,reset;
  input [1:0]coin;
  output news_out;
  wire news_out;
  
  wire [1:0]next_state;
  reg  [1:0]pres_state;
  
  parameter s0=2'd0;
  parameter s1=2'd1;
  parameter s2=2'd2;
  parameter s3=2'd3;
  
  
  function [2:0]fsm;
    input [1:0]fsm_coin;
    input [1:0]fsm_pres_state;
    
    reg fsm_newspaper;
    reg [1:0]fsm_next_state;
    
    begin
      case(fsm_pres_state)
        s0:
        begin
          if(fsm_coin==2'd2)
            begin
              fsm_next_state=s2;
              fsm_newspaper=1'b0;
            end
          else if(fsm_coin==2'd1)
            begin
              fsm_next_state=s1;
              fsm_newspaper=1'b0;
            end
          else
            begin
              fsm_next_state=s0;
              fsm_newspaper=1'b0;
            end
        end
        
        s1:
        begin
          if(fsm_coin==2'd2)
            begin
              fsm_next_state=s3;
              fsm_newspaper=1'b0;
            end
          else if(fsm_coin==2'd1)
            begin
              fsm_next_state=s2;
              fsm_newspaper=1'b0;
            end
          else
            begin
              fsm_next_state=s1;
              fsm_newspaper=1'b0;
            end
        end
        
        s2:
        begin
          if(fsm_coin==2'd2)
            begin
              fsm_next_state=s3;
              fsm_newspaper=1'b0;
            end
          else if(fsm_coin==2'd1)
            begin
              fsm_next_state=s3;
              fsm_newspaper=1'b0;
            end
          else
            begin
              fsm_next_state=s2;
              fsm_newspaper=1'b0;
            end
        end
        
        s3:
        begin
          fsm_next_state=s0;
          fsm_newspaper=1'b1;
        end
      endcase
      fsm={fsm_newspaper,fsm_next_state};
    end
  endfunction
  
  assign {news_out,next_state}=fsm(coin,pres_state);


  
  always @(posedge clock)
  begin
    if(reset==1'b0)
      pres_state<=s0;
    else
      pres_state<=next_state;
  end
endmodule
    
  
  


0 0