Verilog 同时使用case语句和if-else?

Verilog 同时使用case语句和if-else?,verilog,hdl,Verilog,Hdl,我正在尝试编写下面状态图中指定的机器的Verilog HDL行为描述 我在case语句中使用if-else语句,这会导致这些行的语法错误。你知道问题出在哪里吗 我的代码附在下面: module foo(y_out, state, x_in, clk, reset); input x_in, clk, reset; output reg y_out; parameter s0 = 3'b000, s1 = 3'b001, s2 = 3'b010, s3 = 3'b011

我正在尝试编写下面状态图中指定的机器的Verilog HDL行为描述

我在
case
语句中使用
if-else
语句,这会导致这些行的语法错误。你知道问题出在哪里吗

我的代码附在下面:

module foo(y_out, state, x_in, clk, reset);

    input x_in, clk, reset;
    output reg y_out;
    parameter s0 = 3'b000, s1 = 3'b001, s2 = 3'b010, s3 = 3'b011, s4 = 3'b100;
    output reg[2:0] state;
    reg[2:0] next_state;

    always @(posedge clk) begin
        if(reset == 1'b0) state <= s0;
        else state <= next_state;
    end
    always @(state, x_in) begin
        y_out = 0;
        next_state = s0;
        case(state, x_in)
        s0:
            if (!x_in) begin
                next_state = s3;
                y_out = 1'b0;
            end
            else begin
                next_state = s4;
                y_out =1'b1;
            end
        s1:
            if (!x_in) begin
                next_state = s1;
                y_out = 1'b0;
            end
            else begin
                next_state = s4;
                y_out =1'b1;
            end
        s2: if (!x_in) begin
                next_state = s2;
                y_out = 1'b0;
            end
            else begin
                next_state = s0;
                y_out =1'b1;
            end
        s3: if (!x_in) begin
                next_state = s1;
                y_out = 1'b0;
            end
            else begin
                next_state = s2;
                y_out =1'b1;
            end
        s4: if (!x_in) begin
                next_state = s2;
                y_out = 1'b0;
            end
            else begin
                next_state = s3;
                y_out =1'b0;
            end
        default begin
            next_state = s0;
            y_out = 1'b0;
        end
        endcase
    end
endmodule

module t_foo;

    wire t_y_out, t_state;
    reg t_x_in, t_clock, t_reset;

    foo M1(t_y_out, t_state, t_x_in, t_clock, t_reset);

    initial #200 $finish;
    initial begin
        t_reset = 0;
        t_clock = 0;
        #5 t_reset = 1;
      repeat (16)
        #5 t_clock = ~t_clock;
    end

    initial begin
        t_x_in = 0;
        #15 t_x_in = 1;
      repeat (8)
        #10 t_x_in = ~t_x_in;
    end
    initial begin
       $monitor("ABC: %d, x_in: %d, Clock: %d, Reset: %d", state, t_x_in, t_clock, t_reset);
       $dumpfile("5_41_wv.vcd");
       $dumpvars;
    end
endmodule
模块foo(y_out,state,x_in,clk,reset);
输入x_in,时钟,复位;
输出寄存器y_out;
参数s0=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100;
输出reg[2:0]状态;
reg[2:0]下一个州;
始终@(posedge clk)开始
如果(重置==1'b0)状态改变:

case(state, x_in)
致:

这为我修复了一个编译错误。代码中的case项仅取决于状态参数,而不取决于
中的
x\u

我还发现testbench模块中存在编译错误。要修复它,请更改:

   $monitor("ABC: %d, x_in: %d, Clock: %d, Reset: %d", state, t_x_in, t_clock, t_reset);
致:

并通过更改以下内容来修复警告:

wire t_y_out, t_state;
致:


case
语句期望单个项如果这是基于多个wire/reg,则需要使用
{}
连接它们

我会避免使用像
always@(state,x_in)begin
这样的东西,而只写
always@*begin
。@*将处理敏感度列表

使用串联运算符可以删除if语句:

 always @* begin
   y_out = 0;
   next_state = s0;
   case({state, x_in}) //Added {}
    {s0, 1'b0}: 
      begin
        next_state = s3;
        y_out      = 1'b0;
      end
    {s0, 1'b1}:
      begin 
        next_state = s4;
        y_out      = 1'b1;
      end
    {s1, 1'b0}: 
      begin
        next_state = s1;
        y_out      = 1'b0;
      end
    {s1, 1'b1}:
      begin
        next_state = s4;
        y_out      = 1'b1;
      end
使用
casez
将允许您将不关心添加到下一个状态逻辑:

 always @* begin
   y_out = 0;
   next_state = s0;
   casez({state, x_in}) //Added {}
    {s0, 1'bx}: //Do not care about the state of x_in
      begin
        next_state = s3;
        y_out      = 1'b0;
      end
    {s1, 1'b0}: 
      begin
        next_state = s1;
        y_out      = 1'b0;
      end
    {s1, 1'b1}:
      begin
        next_state = s4;
        y_out      = 1'b1;
      end

case表达式中的使用状态和if条件中的xin正常工作。请查找以下工作代码

module fsm_state(

   input clk,
   input rst_n,
   input xin,
   output reg yout
    );
    
    reg [2:0] state;
    reg [2:0] next_state;
    
    parameter s0 = 3'b000,
              s1 = 3'b001,
              s2 = 3'b010,
              s3 = 3'b011,
              s4 = 3'b100;
              
    always @ (posedge clk) begin
       if (!rst_n)
          state = s0;
       else
          state = next_state;
    end
    
    always @*
    begin
       yout = 1'b0; 
       case (state)
          s0: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s4;
             end
             else 
                next_state = s3;              
          end
          s1: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s4;
             end
             else 
                next_state = s1;  
          end
          s2: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s0;
             end
             else 
                next_state = s2;
          end
          s3: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s2;
             end
             else 
                next_state = s1;
          end
          s4: begin
             if (xin) 
                next_state = s3;
             else 
                next_state = s2;
          end
         
       endcase
    end
    
endmodule

谢谢

@ScottAronBloom该问题被标记为Verilog而非SystemVerilog,因此总是ff,总是comb将不可用<代码>始终@*
分配
是创建组合逻辑的主要方式。使用手动灵敏度是造成synth与simulation不匹配的最常见方法之一,这就是为什么在语言中添加通配符来避免这种情况;使用NBA,如问题中所述。
 always @* begin
   y_out = 0;
   next_state = s0;
   case({state, x_in}) //Added {}
    {s0, 1'b0}: 
      begin
        next_state = s3;
        y_out      = 1'b0;
      end
    {s0, 1'b1}:
      begin 
        next_state = s4;
        y_out      = 1'b1;
      end
    {s1, 1'b0}: 
      begin
        next_state = s1;
        y_out      = 1'b0;
      end
    {s1, 1'b1}:
      begin
        next_state = s4;
        y_out      = 1'b1;
      end
 always @* begin
   y_out = 0;
   next_state = s0;
   casez({state, x_in}) //Added {}
    {s0, 1'bx}: //Do not care about the state of x_in
      begin
        next_state = s3;
        y_out      = 1'b0;
      end
    {s1, 1'b0}: 
      begin
        next_state = s1;
        y_out      = 1'b0;
      end
    {s1, 1'b1}:
      begin
        next_state = s4;
        y_out      = 1'b1;
      end
module fsm_state(

   input clk,
   input rst_n,
   input xin,
   output reg yout
    );
    
    reg [2:0] state;
    reg [2:0] next_state;
    
    parameter s0 = 3'b000,
              s1 = 3'b001,
              s2 = 3'b010,
              s3 = 3'b011,
              s4 = 3'b100;
              
    always @ (posedge clk) begin
       if (!rst_n)
          state = s0;
       else
          state = next_state;
    end
    
    always @*
    begin
       yout = 1'b0; 
       case (state)
          s0: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s4;
             end
             else 
                next_state = s3;              
          end
          s1: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s4;
             end
             else 
                next_state = s1;  
          end
          s2: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s0;
             end
             else 
                next_state = s2;
          end
          s3: begin
             if (xin) begin
                yout = 1'b1;
                next_state = s2;
             end
             else 
                next_state = s1;
          end
          s4: begin
             if (xin) 
                next_state = s3;
             else 
                next_state = s2;
          end
         
       endcase
    end
    
endmodule