I am trying to write Verilog HDL behavioral description of the machine specified in the state diagram below.
I am using if-else statements inside a case statement, and this gives me syntax errors regarding those lines. Do you see what the problem is?
My code is attached below:
module foo(y_out, state, x_in, clk, reset); input x_in, clk, reset; output reg y_out; parameter s0 = 3'b000, s1 = 3'b001, s2 = 3'b010, s3 = 3'b011, s4 = 3'b100; output reg[2:0] state; reg[2:0] next_state; always @(posedge clk) begin if(reset == 1'b0) state <= s0; else state <= next_state; end always @(state, x_in) begin y_out = 0; next_state = s0; case(state, x_in) s0: if (!x_in) begin next_state = s3; y_out = 1'b0; end else begin next_state = s4; y_out =1'b1; end s1: if (!x_in) begin next_state = s1; y_out = 1'b0; end else begin next_state = s4; y_out =1'b1; end s2: if (!x_in) begin next_state = s2; y_out = 1'b0; end else begin next_state = s0; y_out =1'b1; end s3: if (!x_in) begin next_state = s1; y_out = 1'b0; end else begin next_state = s2; y_out =1'b1; end s4: if (!x_in) begin next_state = s2; y_out = 1'b0; end else begin next_state = s3; y_out =1'b0; end default begin next_state = s0; y_out = 1'b0; end endcase end
endmodule
module t_foo; wire t_y_out, t_state; reg t_x_in, t_clock, t_reset; foo M1(t_y_out, t_state, t_x_in, t_clock, t_reset); initial #200 $finish; initial begin t_reset = 0; t_clock = 0; #5 t_reset = 1; repeat (16) #5 t_clock = ~t_clock; end initial begin t_x_in = 0; #15 t_x_in = 1; repeat (8) #10 t_x_in = ~t_x_in; end initial begin $monitor("ABC: %d, x_in: %d, Clock: %d, Reset: %d", state, t_x_in, t_clock, t_reset); $dumpfile("5_41_wv.vcd"); $dumpvars; end
endmodule 0 3 Answers
case statements expect a single item if this is to be based on multiple wire/regs then they need to be concatenated using {}.
I would avoid using things like always @(state, x_in) begin and just write always @* begin. The @* will take care of the sensitivity list.
Using the concatenation operator would allow you to remove the if statements:
always @* begin y_out = 0; next_state = s0; case({state, x_in}) //Added {} {s0, 1'b0}: begin next_state = s3; y_out = 1'b0; end {s0, 1'b1}: begin next_state = s4; y_out = 1'b1; end {s1, 1'b0}: begin next_state = s1; y_out = 1'b0; end {s1, 1'b1}: begin next_state = s4; y_out = 1'b1; endUsing a casez would allow you to add do not cares to the next_state logic:
always @* begin y_out = 0; next_state = s0; casez({state, x_in}) //Added {} {s0, 1'bx}: //Do not care about the state of x_in begin next_state = s3; y_out = 1'b0; end {s1, 1'b0}: begin next_state = s1; y_out = 1'b0; end {s1, 1'b1}: begin next_state = s4; y_out = 1'b1; end 1 Change:
case(state, x_in)to:
case(state)That fixes a compile error for me. The case items in your code only depend on your state parameters, not x_in.
I also get a compile error in your testbench module. To fix it, change:
$monitor("ABC: %d, x_in: %d, Clock: %d, Reset: %d", state, t_x_in, t_clock, t_reset);to:
$monitor("ABC: %d, x_in: %d, Clock: %d, Reset: %d", t_state, t_x_in, t_clock, t_reset);And fix a warning by changing:
wire t_y_out, t_state;to:
wire t_y_out;
wire [2:0] t_state; Using state in case expression and xin in if condition is working fine. Please find below working code.
module fsm_state( input clk, input rst_n, input xin, output reg yout ); reg [2:0] state; reg [2:0] next_state; parameter s0 = 3'b000, s1 = 3'b001, s2 = 3'b010, s3 = 3'b011, s4 = 3'b100; always @ (posedge clk) begin if (!rst_n) state = s0; else state = next_state; end always @* begin yout = 1'b0; case (state) s0: begin if (xin) begin yout = 1'b1; next_state = s4; end else next_state = s3; end s1: begin if (xin) begin yout = 1'b1; next_state = s4; end else next_state = s1; end s2: begin if (xin) begin yout = 1'b1; next_state = s0; end else next_state = s2; end s3: begin if (xin) begin yout = 1'b1; next_state = s2; end else next_state = s1; end s4: begin if (xin) next_state = s3; else next_state = s2; end endcase end
endmoduleThanks
1