5

I'm trying to convert a flow chart simple state machine into Verilog code. But I'm somehow stuck with the following, and as I have hardly any knowledge in Verilog I'm probably missing something.

The statemachine detects for an input stream of 0 and 1, if the count of 1s can be divided by 3 (or simply: if there have been 3 times number 1).

enter image description here

module example (
  input clk,
  input rst,
  input input1,
  output output
);

reg state;
reg nextstate;

localparam state2 = 3'd0;
localparam state1 = 3'd1;
localparam state0 = 3'd2;

always @(posedge clk or posedge rst) begin
  if (rst)
    state <= state0;
  else
    state <= nextstate;
end

always @* begin
  case(state)
    state0: begin
      if(input1)
        nextstate = state1;
      end
    state2: begin
      if(input1)
        nextstate = state0;
      end
    state1: begin
      if(input1)
        nextstate = state2;
      end
    default: nextstate = state0;
  endcase
end

always @* begin
  output1 = state0 & input1;
end

endmodule

I'm not sure:

  • do I have to define the inputs + outputs as reg or wire? Or is input and output! sufficient?

  • must I provide a vector dimension for the reg state, nextstate? If yes, how to I know which dimension to pick?

  • can I write these kind of assertions at the end like state0 & input1? Or should I use state = state0 & input1 = ?? - yes, what?

3 Answers 3

2

do I have to define the inputs + outputs as reg or wire? Or is input and output! sufficient?

Inputs are always wires, though it doesn't really matter as you don't assign to them. Outputs are wires by default, though you can also declare output reg if you want a register instead.

must I provide a vector dimension for the reg state, nextstate? If yes, how to I know which dimension to pick?

Yes you must declare a dimension, or else your design will catastrophically fail when verilog silently truncates all your states to 0 or 1. The width of the states should be the same width of the localparams that you use to define the state names, or more generically the width should be log2(number of input states).

can I write these kind of assertions at the end like state0 & input1?

I don't think this is what you want. State0 is just a constant number. If you want to know if the state machine is in state0, then you need to compare the current state with the constant state0. Also you likely don't want a bitwise AND here, so use the regular and &&. Should be:

output = (state == state0) && input1;
Sign up to request clarification or add additional context in comments.

6 Comments

What do you mean exactly by number of input states? Would this be 3 in my case (input1, clock, reset), and thus the dimension vector would be [1:0]? Further: if I assume my states are always either high or low (1 or 0), can I then neglect the vector dimension for the localparams?
Yes, I just meant the total number of states in your state machine (sorry should have worded that better). You can make the vector as large as you want, but you just have to make sure that if you have a state definition that is N bits wide, that you don't cram it into a field smaller than N bits, or else the top bits will be dropped.
No, you need a demension for the localparams as well. I think you might be not understanding something, 'states' are not high or low. A state machine has one register which holds the 'current state', and all of the 'states' are just numbers, where each state gets its own unique number. You know what state you're in by comparing the value of the state register to the definition of the parameters. @membersound
Yes as I already wrote I have some understanding problems with this. But your comments help a lot, thanks! Just to make sure, as you said "Yes, I just meant the total number of states in your state machine", again you do not mean total number of inputs + outputs, but only total number of inputs, thus any signal that write "input X,", correct?
No, I meant the number of states in the machine (S0, S1, S2), the number of bubbles in your diagram. Your state machine has three states, therefore you need three separate state numbers. Three unique numbers can only be represented in at least 2 bits (00, 01, 10), so your 'state' reg needs to have 2 bits, to hold these values. The number of states doesn't have anything to do with the number of module inputs or outputs.
|
2
always @* begin
  case(state)
    state0: begin
      if(input1)begin
        nextstate = state1;
         output1 = 0;
      end end
       else begin
        nextstate = state0;
         output1 = 1;
      end
    state2: begin
      if(input1)begin
        nextstate = state0;
        output1   = 1 ;
      end end
      begin
        nextstate = state2;
         output1 = 0;
      end
    state1: begin
      if(input1)begin
        nextstate = state2;
        output1   = 0;
      end end
     else begin
        nextstate = state1;
         output1 = 0;
      end
    default: nextstate = state0;
  endcase
end

1 Comment

Since the output shpuld make transition from 0 to 1 while the state2 changes to state 0 , I feel its better to assign the outputs along with change in states.
2

Although its too late but i got on the band wagon of learning Verilog and decided to take a shot at your inquiry. I wrote the design module and also created a test bench for it. This works according to your expectation.

`timescale 1ns/1ns
`define WIDTH 4
module FSM_Detect_Stream_Top();

    reg in_clk;
    reg in_rst_n;
    reg [`WIDTH-1:0] in_input;

    wire out_ouput;

    FSM Test (.i_clk(in_clk), .i_rst_n(in_rst_n), .i_input(in_input), .o_output(out_output));

    initial
        begin
            in_clk = 1'b0; // clk at t=0
            #1 in_rst_n = 1'b1;
            #2 in_rst_n = 1'b0;
            #5 in_rst_n = 1'b1;
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b01;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b00;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_rst_n = 1'b0;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            @ (negedge in_clk)
                in_input = 2'b00; in_rst_n = 1'b1;
            @ (posedge in_clk)  
                $display("output:%b ", out_output);
            $finish;
        end


    // Generating a 20ns width clock pulse with 50% duty cycle
    always
        #10 in_clk = ~in_clk;

endmodule // FSM_Detect_Stream_Top

//*********************************************************************************************
module FSM(input i_clk, input i_rst_n, input [`WIDTH-1:0] i_input, output reg o_output);
//*********************************************************************************************

    parameter S0 = 2'b00;   //FIRST STATE or DEFAULT
    parameter S1 = 2'b01;   //SECOND STATE
    parameter S2 = 2'b10;   //THIRD STATE
    parameter S3 = 2'b11;   //FOURTH STATE

    reg [`WIDTH-3:0] curr_state;
    reg [`WIDTH-3:0] next_state;

    //Sequential Logic for Storing Current State
    always @ (posedge i_clk or negedge i_rst_n) begin
        if(~i_rst_n)
            curr_state <= S0;
        else
            curr_state <= next_state;
        end

    //Combinational Logic for Next State
    always @ (curr_state or i_input)    begin
        case(curr_state)
            S0: begin
                if (i_input == 2'b01)
                    next_state <= S1;
                else
                    next_state <= S0;
            end
            S1: begin
                if (i_input == 2'b01)
                    next_state <= S2;
                else
                    next_state <= S1;
            end
            S2: begin
                if (i_input == 2'b01)
                    next_state <= S3;
                else
                    next_state <= S2;
            end
            S3: begin
                if (i_input == 2'b01)
                    next_state <= S0;
                else
                    next_state <= S3;
            end 
            default: next_state <= S0;
        endcase // curr_state
    end

    // Output Logic
    always @(posedge i_clk) begin
        if (~i_rst_n)
            o_output <= 1'b0;
        else begin
            case(curr_state)    
                S0: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else
                        o_output <= 1'b1;
                    end
                S1: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else
                        o_output <= 1'b0;
                    end
                S2: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else 
                        o_output <= 1'b0;
                    end
                S3: begin
                    if (i_input == 2'b01)
                        o_output <= 1'b1;
                    else 
                        o_output <= 1'b0;
                    end
                default: o_output <= 1'b0;
            endcase
        end
    end 

endmodule

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.