-1

I have been working on a FSM which is implemented using Verilog HDL. In the case determining the next state outputs, I have two outputs that need to be assigned. So I tried to use begin and end to put two assignments into a single case. But it still doesn't work. I am not sure if there is some syntax errors which I can't write the code in this way.

module Vending_FSM(
input [2:0] INPUT,
input CLK,
output REL,
output [3:0] AMT
);

// Declaring state and next_state variable
reg[2:0]    state, next_state;

// Declaring 6 state parameters
parameter
    S0 = 3'b000,    // WAIT
    S1 = 3'b001,    // $5
    S2 = 3'b010,    // $10
    S3 = 3'b011,    // $15
    S4 = 3'b100,    // $20
    S5 = 3'b101;    // $25

// Determning next state transition
always @(posedge CLK)
    begin
    state <= next_state;    // Positive-edge triggering 
    end

// Determing next state input
always @(INPUT or state)
    begin
    case (state)
        S0: case (INPUT)    // WAIT
            3'b000: next_state = S1;    // $5
            3'b001: next_state = S2;    // $10
            3'b010: next_state = S4;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S0;    // $100
            3'b101: next_state = S0;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
        S1: case (INPUT)    // $5
            3'b000: next_state = S2;    // $5
            3'b001: next_state = S3;    // $10
            3'b010: next_state = S5;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S1;    // $100
            3'b101: next_state = S1;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
        S2: case (INPUT)    // $10
            3'b000: next_state = S3;    // $5
            3'b001: next_state = S4;    // $10
            3'b010: next_state = S5;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S2;    // $100
            3'b101: next_state = S2;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
        S3: case (INPUT)    // $15
            3'b000: next_state = S4;    // $5
            3'b001: next_state = S5;    // $10
            3'b010: next_state = S5;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S3;    // $100
            3'b101: next_state = S3;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
        S4: case (INPUT)    // $20
            3'b000: next_state = S5;    // $5
            3'b001: next_state = S5;    // $10
            3'b010: next_state = S5;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S4;    // $100
            3'b101: next_state = S4;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
        S5: case (INPUT)    // $25
            3'b000: next_state = S5;    // $5
            3'b001: next_state = S5;    // $10
            3'b010: next_state = S5;    // $20
            3'b011: next_state = S5;    // $50
            3'b100: next_state = S5;    // $100
            3'b101: next_state = S0;    // PUR
            3'b110: next_state = S0;    // REF
        endcase
    endcase
    end

// Determing next state output
always @(INPUT or state)
    begin
    case (state)
        S0: case (INPUT)    // WAIT
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0000;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0000;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0000;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b0101;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b0;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0000;
                    end
        endcase
        S1: case (INPUT)    // $5
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0000;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0000;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0000;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b0110;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b0;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0001;
                    end
        endcase
        S2: case (INPUT)    // $10
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0000;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0000;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0001;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b0111;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b0;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0010;
                    end
        endcase
        S3: case (INPUT)    // $15
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0000;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0000;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0010;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b1000;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b0;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0011;
                    end
        endcase
        S4: case (INPUT)    // $20
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0000;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0001;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0011;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b1001;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b0;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0100;
                    end
        endcase
        S5: case (INPUT)    // $25
            3'b000: begin
                    REL = 1'b0;     // $5
                    AMT = 4'b0001;
                    end
            3'b001: begin
                    REL = 1'b0;     // $10
                    AMT = 4'b0010;
                    end
            3'b010: begin
                    REL = 1'b0;     // $20
                    AMT = 4'b0100;
                    end
            3'b011: begin
                    REL = 1'b0;     // $50
                    AMT = 4'b1010;
                    end
            3'b100: begin
                    REL = 1'b0;     // $100
                    AMT = 4'b1011;
                    end
            3'b101: begin
                    REL = 1'b1;     // PUR
                    AMT = 4'b0000;
                    end
            3'b110: begin
                    REL = 1'b0;     // REF
                    AMT = 4'b0101;
                    end
        endcase
    endcase
    end

endmodule

Thank you in advance.

  • are your states getting transitioned?can you add the error you are seeing or any waveform from your initial debug?In this code you haven't assigned anything for next state. Are you trying your FSM in 2 always block style – Rama Krishna Meda Apr 25 '20 at 04:13
  • The syntax you have used is valid and it works normally. – Rama Krishna Meda Apr 25 '20 at 04:39
  • I have uploaded the full code. The compiler error says that "ERROR:HDLCompiler:806 - "/home/ise/Xilinx_Share_Folder/Assignment2_Verilog/Vending_FSM.v" Line 121: Syntax error near "="." And it happends in multiple lines. – Karol Warvic Apr 25 '20 at 04:49
  • 1
    I just glanced at your code and noticed that AMT and REL should be `reg` type. As for style: normally capitals are used for parameters or macros and not for standard variables. (At least what is good is that your variables are not named X,Y or Z :-) – Oldfart Apr 25 '20 at 05:15
  • For stack overflow, you should put the syntax error in the original question, I'm getting requests from SO to help you. The above comment is correct though - and generally you want the outputs to be registered, not asynchronous, otherwise you will run into timing issues. – Joe Apr 25 '20 at 19:15

2 Answers2

0
module Vending_FSM(
   input      [2:0] INPUT
  ,input            CLK
  ,output reg       REL
  ,output reg [3:0] AMT
);

// Declaring state and next_state variable
reg[2:0]    state, next_state;
reg         n_AMT,n_REL;

// Declaring 6 state parameters
parameter
    S0 = 3'b000,    // WAIT
    S1 = 3'b001,    // $5
    S2 = 3'b010,    // $10
    S3 = 3'b011,    // $15
    S4 = 3'b100,    // $20
    S5 = 3'b101;    // $25

always@(posedge clk)
    state <= next_state;

// Determing next state input
always@*
    casez (state)
        S0: casez (INPUT)    // WAIT
            3'b000: next_state = S1;    // $5
            3'b001: next_state = S2;    // $10
            3'b010: next_state = S4;    // $20
            3'b011: next_state = S5;    // $50
            3'b10?,
            3'b110: next_state = S0;    // $100// PUR// REF
        endcase
        S1: casez (INPUT)    // $5
            3'b000: next_state = S2;    // $5
            3'b001: next_state = S3;    // $10
            3'b01?: next_state = S5;    // $20// $50
            3'b10?: next_state = S1;    // $100// PUR
            3'b110: next_state = S0;    // REF
        endcase
        S2: casez (INPUT)    // $10
            3'b000: next_state = S3;    // $5
            3'b001: next_state = S4;    // $10
            3'b01?: next_state = S5;    // $20// $50
            3'b10?: next_state = S2;    // $100// PUR
            3'b110: next_state = S0;    // REF
        endcase
        S3: casez (INPUT)    // $15
            3'b000: next_state = S4;    // $5
            3'b001,                     // $10
            3'b01?: next_state = S5;    // $20// $50
            3'b10?: next_state = S3;    // $100// PUR
            3'b110: next_state = S0;    // REF
        endcase
        S4: casez (INPUT)    // $20
            3'b0??: next_state = S5;    // $5// $10// $20 // $50
            3'b10?: next_state = S4;    // $100// PUR
            3'b110: next_state = S0;    // REF
        endcase
        S5: casez (INPUT)    // $25
            3'b0??,    // $5// $10// $20// $50
            3'b100: next_state = S5;    // $100
            3'b10?: next_state = S0;    // PUR// REF
          endcase
        default:    next_state = 'x;
    endcase


always @* begin
            n_REL = 1'b0;
            n_AMT = 4'b0;
    case (state)
        S0:        if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b011) n_AMT = 4'b0101;

        S1:        if(INPUT == 3'b011) n_AMT = 4'b0110;
              else if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b110) n_AMT = 4'b0001;

        S2:        if(INPUT == 3'b010) n_AMT = 4'b0001;
              else if(INPUT == 3'b011) n_AMT = 4'b0111;
              else if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b110) n_AMT = 4'b0010;

        S3:        if(INPUT == 3'b010) n_AMT = 4'b0010;
              else if(INPUT == 3'b011) n_AMT = 4'b1000;
              else if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b110) n_AMT = 4'b0011;

        S4:        if(INPUT == 3'b001) n_AMT = 4'b0001;
              else if(INPUT == 3'b010) n_AMT = 4'b0011;
              else if(INPUT == 3'b011) n_AMT = 4'b1001;
              else if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b110) n_AMT = 4'b0100;

        S5:        if(INPUT == 3'b000) n_AMT = 4'b0001;
              else if(INPUT == 3'b001) n_AMT = 4'b0010;
              else if(INPUT == 3'b010) n_AMT = 4'b0100;
              else if(INPUT == 3'b011) n_AMT = 4'b1010;
              else if(INPUT == 3'b100) n_AMT = 4'b1011;
              else if(INPUT == 3'b101) n_REL = 1'b1;
              else if(INPUT == 3'b110) n_AMT = 4'b0101;

    endcase
end

always @(posedge clk) begin
    REL <= #1 n_REL;
    AMT <= #1 n_AMT;
end

endmodule
0

REL and AMT need to be reg type. As they were inferred wire types which cannot be assigned in always blocks.

module Vending_FSM(
input [2:0] INPUT,
input CLK,
output reg REL,
output reg [3:0] AMT
);

also next_state, REL, and AMT are an inferred latches because it is not explcetly assigned when INPUT equal to 3'b111 and state outside of S0-S5. You can either define all cases in the case statement or/and have a default assignment above the case to a constant of flop. Example:

always @* begin
  // default assignment
  next_state = state;
  // update
  case(state)
    S0: case (INPUT)    // WAIT
        //... your existing code, maybe added 3'b111/default case
    endcase
    // S1..S5: ... your existing code, maybe added case 3'b111/default for INPUT
  default : next_state = S0; // in case state not inside S0..S5
  endcase
end
always @* begin
  // default assignment
  REL = 1'b0;
  ATM = 4'b0000;
  // update
  case(state)
    //... your existing code
  endcase
end

Other notes:

always @(INPUT or state) is technically okay, but is no longer recommenced. Use always @* or always @(*) for auto sensitivity. Specifying the signals for the sensitivity list was required for Verilog-1995. Verilog-2001 added auto sensitivity which reduces the risk of an incomplete sensitivity lists; plus reduces typing.

For cleaner output signals and easier timing analysis, I recommend flopping the outputs. Example:

always @* begin
  // default assignment
  next_REL = 1'b0;
  next_AMT = 4'b0000;
  // update
  case(state)
    //... your existing code but REL and AMT prefixed with next_
  endcase
end
always @(posedge clk) begin
  state <= next_state;
  REL <= next_REL;
  AMT <= next_AMT;
end
Greg
  • 18,111
  • 5
  • 46
  • 68