Multiple items matching in Verilog case statement - case

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.

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.

Related

Creating a buffer in Nusmv

I'm attempting to write code for a buffer in NuSMV. The buffer has 6 wires. 4 input wires (reset, clock, read_enable, and write_enable) and 2 output wires(full and empty). Wires are modeled as boolean true|false (true being high voltage). The first
wire is an asynchronous (instant) reset. If there is a high voltage, the buffer
goes instantly to the empty configuration. Other wires are operated in the
synchronous mode triggered by a rising edge on the clock wire. The buffer is of Size 3. There are specific behaviors.
I created the following code but I cannot think of what the Main Module could be.
MODULE buffer (reset, clock, read_enable, write_enable, full, empty)
-- inputs
-- reset : boolean; -- asynchronous (instant) reset
-- clock : boolean; -- clock
-- read_enable : boolean; -- data read request = enqueue
-- write_enable : boolean; -- data write request = dequeue
-- outputs
-- full : boolean; -- is the buffer full?
-- empty : boolean; -- is the buffer empty?
-- use SIZE for the maximal buffer size
-- TODO ....
VAR
reset: {False, True};
clock: {False, True};
read_enable: {False, True};
write_enable: {False, True};
full: {False, True};
empty: {False, True};
ASSIGN
SIZE := 0;
init (reset) := True;
next (reset) := case
reset = True : empty = True;
esac;
next (clock) := case
write_enable = True : clock = True & empty = False;
esac;
next (write_enable):= case
write_enable = True : SIZE + 1 & SIZE <=3;
esac;
next (read_enable) := case
write_enable = True & read_enable = True : SIZE != SIZE +1;
esac;
next (full) := case
full = True & SIZE = 3 & write_enable = True : reset = True;
esac;
MODULE main
VAR
reset: boolean;
turn: boolean;
pro0: process buffer(reset, 0, clock, read_enable, write_enable);
pro1: process buffer(reset, 1, clock, read_enable, write_enable);
ASSIGN
init(turn) := 0;
FAIRNESS !(reset = True)
FAIRNESS !(reset = False)
MODULE prc(reset, turn, pro0, pro1)
ASSIGN
init(reset) := 0;
next (reset) := case
(reset = 0) : {0,1};
(reset = 1) : {0};
1 : reset;
esac;
Please assist
I've tried following basic NuSMV guides on how to write the code but I have no experience in this language.

How to preserve a value in a case statement in verilog

When designing finite state machines in verilog, I find myself writing code like this a lot to preserve a value in a particular state.
always#(state, a, b) begin
case(state) begin
S1: a = b;
S2: a = a; // preserve a;
endcase
end
This is necessary because if I don’t specify a value for each register in the sensitivity list, the compiler will infer a latch. To me this feels like a code smell, but I’m not experienced enough to know for sure. Is this the best way to preserve a value in verilog?
Preserve state means to create a latch, which is a device that do exactly that.
a=a is a null statement and you should not use it at all.
Do not use sensetivity lists in the always block, they are error prone, use #* instead.
And, for latches, you should use non-blocking assignments.
Your latch case statement should look like the following:
always#(*) begin
case(state) begin
S1: a <= b;
S2: // do nothing about 'a', a will not change.
endcase
end
in general the FSM scheme use in industry uses clocks and looks like the following:
always#(posedge clk) begin
case(state) begin
S1: begin
next_state <= S2;
a <= b;
end
S2: // do nothing about 'a', a will not change.
....
endcase
end
assign state = next_state;

Is an asynchronous counter made in Verilog synthesizable?

the question in it itself is simple. Is it possible to synthesize an Asynchronous counter in Verilog?
More explanation:
So for example, if I have something like the following code, is it possible to synthesize it?
always #(posedge clk) begin
//rst
if(!rst)begin
enable <=0;
end else begin
enable <= 1;
end
end
//action loop
always #(state) begin
case (state)
0:begin
cnt <= cnt
end
1: begin
cnt <= cnt + 1;
next_state <= 1;
end
default: begin
cnt <= cnt;
end
endcase
end
//state loop
always #(next_state, control, enable) begin
if(enable)begin
if(!control) begin
state <= next_state;
end else begin
state <= 0;
end
end
end
Here the general idea is that the counter will go asynchronously while the input control flag is 0, if it is 1 then the counter will be stopped until the input control flag becomes 0 again.
Note: I know I could try and synthesize the code and see what happens. But before that, I would like to know more and see if people have tried it.
Thanks for reading!!
Your action loop can't be properly synthesized.
What it is doing when state == 1?
Your state loop is synthesizable except but you will produce a latch (to store the value when enable == 0). This block is something that could be done using combinational logic '=' instead of non-blocking assignment '<='.

How should I go about resetting my reset signal in Verilog?

I have 2 always blocks, one that counts the number of clock cycles that have passed capable of asynchronous reset and another that triggers the reset signal on the negedge of some input signal.
always#(posedge clock or posedge reset)
begin: ClockCounter
if(reset == 1)
begin
clock_cnt = 1;
end
else
begin
clock_cnt = clock_cnt + 1;
end
end
always#(negedge pulse_in)
begin: Receiver
negedge_cnt = negedge_cnt + 1;
reset = 1;
.......Code goes on
end
end module
What I want to do is set the reset signal to 0 once the clock_cnt has been reset to 1 so it can continue counting in the following clock cycle. If I try to insert a reset = 0; after clock_cnt = 1; I get an issue with multiple drivers to the same signal. Does anybody have any idea how to do this?
Unless there is a really important reason to do so, and you have guaranteed glitchless combinational logic, you should not use asynchronous resets to clear registers. The typical approach would be to use a synchronous clear signal rather than use the asynchronous reset.
Heres what the code would look like:
always #(posedge clk or posedge reset) begin
if (reset) begin // Note that you need to separate the asynchronous reset and synchronous clear logic (ie, dont do 'if (reset | clr)')
counter <= 1; // Use non-blocking assignment for clocked blocks
end
else begin
if (clr) begin
counter <= 1;
end
else begin
counter <= counter + 1;
end
end
end
always #(posedge clk) begin // You need to synchronize your input pulse, Im assuming its synchronous to your clock, otherwise youll need a synchronizer
if (prev_pulse_in & ~pulse_in) begin
negedge_cnt <= negedge_cnt + 1;
clr <= 1;
end
else begin
clr <= 0;
end
prev_pulse_in <= pulse_in;
end
My solution was
always#(posedge clock or posedge reset)
begin: ClockCounter
if(reset == 1)
begin
clock_cnt = 1;
reset_flag = 1;
end
else
begin
clock_cnt = clock_cnt + 1;
reset_flag = 0;
end
end
always#(negedge pulse_in or posedge reset_flag)
begin
reset = 1;
if(reset_flag == 1)
reset = 0;
end

Cases throwing unexpected when

I'm making a statemachine in VHDL. My case is throwing an unexpected when error
case state IS
--state 1 A
WHEN s0=>
--Half step
if(FULL = '0' AND RIGHT = '1') then
state <= s1;
else if (RIGHT = '0') then
state <= s7;
end if;
--Full step
if (FULL = '1' AND RIGHT = '1') then
state <= s2;
else if (RIGHT = '0') then
state <= s6;
end if;
--State 2 A&B
WHEN s1=>
if(RIGHT = '0') then
state <= s0;
else if (RIGHT = '1') then
state <= s2;
end if;
However, when running a syntax check with xilinx ISE I'm greeted with a
ERROR:HDLParsers:164 Line 72. parse error, unexpected WHEN, expecting END
This happens 8 times in total. What am I doing wrong?
The if and end if are not balanced, so you will have to close the if with some more end if, or use elsif instead of else if.
You write:
if ... then
...
else if ... then
...
end if;
Even through your indentation shows this like balanced, it is not, since the right indentation would be:
if ... then
...
else
if ... then
...
end if;
Then it is clear that the if and end if are not balance.
If you use elsif you can write it as:
if ... then
...
elsif ... then
...
end if;
Once you have done the correction suggested by #MortenZdk, you need to also consider your logic. In the following, you will never go to state s7 because the assignments done for full step will always over write it.
WHEN s0=>
--Half step
if(FULL = '0' AND RIGHT = '1') then
state <= s1;
elsif (RIGHT = '0') then
state <= s7;
end if;
--Full step
if (FULL = '1' AND RIGHT = '1') then
state <= s2;
elsif (RIGHT = '0') then
state <= s6;
end if;
For this example, I would recommend rewriting it as a nested if then else. It is also a good practice to avoid the final elsif.
WHEN s0=>
if (FULL = '1') then -- Full Step
if (RIGHT = '1') then
state <= s2;
else
state <= s6;
end if;
else --Half step
if (RIGHT = '1') then
state <= s1;
else
state <= s7;
end if;
end if;
I like the active high checks since with VHDL-2008 once your synthesis tool supports it, you will be able to leave off the "= '1'". Ie:
if FULL then -- Full Step
if RIGHT then
Alternately you could concatenate them into a variable and and use a case statement. My suggestion is to always code for readability.

Resources