【问题标题】:Using case statement and if-else at the same time?同时使用case语句和if-else?
【发布时间】:2020-11-12 00:41:58
【问题描述】:

我正在尝试编写下面状态图中指定的机器的 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

【问题讨论】:

    标签: verilog hdl


    【解决方案1】:

    case 语句需要单个项目,如果这是基于多个线/注册,那么它们需要使用 {} 连接。

    我会避免使用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 将允许您将不关心添加到 next_state 逻辑:

     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
    

    【讨论】:

    • @ScottAronBloom 该问题被标记为 Verilog 而不是 SystemVerilog,因此 always_ff,always_comb 将不可用。 always @*assign 是创建组合逻辑的主要方式。使用手动灵敏度是创建合成器与模拟不匹配的最常见方法之一,这就是为什么在语言中添加了通配符以避免这种情况。
    【解决方案2】:

    变化:

    case(state, x_in)
    

    到:

    case(state)
    

    这为我修复了一个编译错误。您代码中的案例项目仅取决于您的状态参数,而不是x_in

    我还在您的测试平台模块中遇到编译错误。要修复它,请更改:

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

    到:

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

    并通过更改来修复警告:

    wire t_y_out, t_state;
    

    到:

    wire t_y_out;
    wire [2:0] t_state;
    

    【讨论】:

      【解决方案3】:

      在 case 表达式中使用 state 并在 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
      

      谢谢

      【讨论】:

      • 你不应该对顺序逻辑使用阻塞赋值;使用 NBA,如问题中所示。
      猜你喜欢
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多