Multiple items matching in Verilog case statement

I have a state machine with several states that are very similar. I could write it for each state, like in the following example:

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

I am wondering if there is a way to specify the case statement for multiple states. Something like:

 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

I want to avoid repeating the statements (that are all the same) to be more clear and to avoid errors if I need to modify it afterwards (my actual FSM is more complicated than this...). Any ideas ?

PS: The code is meant to be synthesized. In my case, the synthesis tool does not support SystemVerilog statements, so I am hoping for a Verilog solution.

2 Answers

The case inside statement in SystemVerilog would do exactly what you want. But since you have constrained yourself to Verilog,it might be more practical to use an if/else chain than a case statement for the example given

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

or you can still use a case statement in this form

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

case statement syntax allows for specifying multiple case item values separated by commas:

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

That will be quite cumbersome for 126 values.

In your case, since you are only using values 0 to 127, you don't need 8 bits for your state variables. You could change them to be 7-bit ([6:0]), and then your case would be full. Then, you could use the default for your states 1-126 without having the long comma-separated list.

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

For the benefit of tools which do support SystemVerilog syntax, IEEE Std 1800-2017, section 12.5.4 Set membership case statement describes the case inside construct:

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

Your synthesis tool may or may not support it, but it is worth a quick try.

0

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like