Verilog case 语句中的多项匹配

Multiple items matching in Verilog case statement

我有一个状态机,其中有几个非常相似的状态。我可以为每个州编写它,如下例所示:

module CHECK_FSM (
GO,
DONE,
CLK, RESETN );

input       GO;
output reg  DONE;
input       CLK,RESETN;

reg[7:0]    state;

reg[7:0]    next_state; 

    //the actual registers
    always @(posedge CLK or negedge RESETN)
        if (!RESETN)    state <= 8'd0;
        else            state <= next_state;

    //next state logic
    always @(*)
        begin
        //defaults
        next_state = state;
        DONE = 1'b0; //low by default

        case(state)
            0: //S_INIT
                if(GO==1'b1)
                    next_state = 8'd1;
                else
                    next_state = 8'd0;
            1: //S_WAIT_1:
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
            2: //S_WAIT_2:
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
            3: //S_WAIT_3:
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
            //...
            127: //S_FINISH
                begin
                DONE = 1'b1;
                next_state = state; //stay put
                end

            default: next_state= 8'd0;
            endcase
        end

endmodule

我想知道是否有办法为多个状态指定 case 语句。类似于:

        case(state)
            0: //S_INIT
                if(GO==1'b1)
                    next_state = 8'd1;
                else
                    next_state = 8'd0;
            [1-->126]:
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
            127: //S_FINISH
                begin
                DONE = 1'b1;
                next_state = state; //stay put
                end

            default: next_state= 8'd0;
            endcase

我想避免重复声明(都是一样的)以便更清楚并且避免错误,如果我需要修改它(我的实际 FSM 比这更复杂......)。有什么想法吗?

PS:代码是用来合成的。就我而言,综合工具不支持 SystemVerilog 语句,所以我希望有一个 Verilog 解决方案。

case 语句语法允许指定多个用逗号分隔的 case 项值:

1, 2, 3, 4,
5, 6, 7, 8: begin
    // your code
end

对于 126 个值,这将非常麻烦。

在您的例子中,由于您只使用 0 到 127 之间的值,因此状态变量不需要 8 位。您可以将它们更改为 7 位 ([6:0]),然后您的 case 将被填满。然后,您可以将 default 用于状态 1-126,而无需用逗号分隔的长列表。

case (state)
    0       : //...
    127     : //...
    default : //1-126 ...
endcase

为了支持 SystemVerilog 语法的工具的好处, IEEE Std 1800-2017,第 12.5.4 节 Set membership case statement 描述了 case inside 构造:

case (state) inside
    0       : //...
    [1:126] : //...
    default : //...
endcase

您的综合工具可能支持也可能不支持,但值得一试。

SystemVerilog 中的 case inside 语句可以完全满足您的要求。但是由于您将自己限制在 Verilog 中,对于给定的示例

,使用 if/else 链可能比使用 case 语句更实用
if (state==0) begin : S_INIT
                if(GO==1'b1)
                    next_state = 8'd1;
                else
                    next_state = 8'd0;
              end
 else if (state >0 && state < 127) begin
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
            end
else if (state == 127) begin : S_FINISH
                DONE = 1'b1;
                next_state = state; //stay put
                end
else begin : S_DEFUALT
            default: next_state= 8'd0;
end

或者您仍然可以使用这种形式的 case 语句

case(1)
  state==0: //S_INIT
                if(GO==1'b1)
                    next_state = 8'd1;
                else
                    next_state = 8'd0;
  (state>0&&state<127):
                if(GO==1'b1)
                    next_state = state+1; //continue
                else
                    next_state = 8'd0; //go back to S_INIT
  state==127: //S_FINISH
                begin
                DONE = 1'b1;
                next_state = state; //stay put
                end
  default: next_state= 8'd0;
endcase