首页 > 解决方案 > 使用 Verilog 对 FSM 进行建模显示 X

问题描述

给定以下 FSM:

在此处输入图像描述

我正在尝试使用 Verilog 对其进行建模,这是我的试用版:

module fsm (u,d,clr,clk,inc,dec,c);
  
input  u,d, clr,clk;
output reg inc,dec,c ;
// the state variables
reg y,Y; // y is the present state and Y is the next state
reg S0,S1;  

  // next state and output specifications 
 
  always @ (y,u,d) begin 
    
    case (y)
      S0 : if (u==1) begin
        Y= S1;
        inc=1;
        dec=0;
        c=1;
      end
      else if (u==0) begin
        c=0;
      end
      S1 :  if (d==1) begin
         Y= S0;
         inc=0;
         dec=1;
         c=0;
      end
      else if (d==0) begin
            c=1;
      end
   endcase 
  end 
  // state update
    always @(posedge clk,clr) begin
      if (clr) 
        y=S0;
      else 
        y=Y;
    end
    endmodule

如果我的代码正确描述了这个 FSM,请告诉我,如果代码中有任何增强,请告诉我。

这是一个初始测试台代码:

module tb();
 reg u,d, clr,clk;
reg inc,dec,c,y ;
  
  fsm ttb (.u(u),.d(d),.clk(clk),.clr(clr),.inc(inc),.dec(dec),.c(c));
  
     initial begin 
    $dumpfile("dump.vcd");
    $dumpvars;
  end 
  
  initial begin //{
   clk=0 ; clr=0; #10
    clk=1; u=0 ; clr=0 ; d=0; #10
    clk = 0;#10
    u=1; clk=1; #10
   
    
    
    
    
    $finish;
    
    
    
    
  end //}
  
endmodule

测试台代码显示有问题。当前状态变量y显示未定义的值“X”。我不知道为什么。输出变量incdec.

在此处输入图像描述

标签: verilogstate-machine

解决方案


X's有几个原因。

在设计中,您将S0and声明S1reg,但您从未为它们赋值。Verilogreg被初始化为X. FSM 通常使用常parameter数值进行编码。例如,更改:

reg S0,S1;  

至:

parameter S0=0, S1=1;  

Y在所有情况下,您的下一个状态逻辑都需要分配值(请参阅<---):

  always @ (y,u,d) begin 
    case (y)
      S0 : if (u==1) begin
        Y= S1;
        inc=1;
        dec=0;
        c=1;
      end
      else if (u==0) begin
        c=0;
        Y= S0; // <-----
      end
      S1 :  if (d==1) begin
         Y= S0;
         inc=0;
         dec=1;
         c=0;
      end
      else if (d==0) begin
            c=1;
            Y= S1; // <-----
      end
   endcase 
  end 

在您的测试台中,您需要断言重置(clr=1):

  initial begin
    u=0; d=0;
    clk=0 ; clr=1; #10
    clk=1; u=0 ; d=0; #10
    clk = 0;#10
    u=1; clk=1; clr=0; #10
    $finish; 
  end

解决关于异步清除问题的评论,您应该更改:

always @(posedge clk,clr) begin

至:

always @(posedge clk, posegde clr) begin

推荐阅读