使用 Verilog 的 FSM 建模显示 X

Modelling of a FSM using Verilog shows 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.

相同

造成 X 的原因有多种。

在设计中,您将 S0S1 声明为 reg,但您从未为它们赋值。 Verilog reg 被初始化为 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