如何解决Verilog case 语句中匹配的多个项目
我有一个状态机,其中有几个非常相似的状态。我可以为每个状态编写它,如下例所示:
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 members 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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。