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
我有一个状态机,其中有几个非常相似的状态。我可以为每个州编写它,如下例所示:
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