Using Case Statement and If-Else at the Same Time?

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;
      end

Using 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
    
endmodule

Thanks

1

Your Answer

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.

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest