What does a simple state machine look like in Verilog?

I am trying to convert a block diagram of a simple state machine into Verilog code. But I was somehow stuck in the following, and since I have almost no knowledge in Verilog, I probably missed something.

Statemachine detects an input stream of 0 and 1 if counter 1 can be divided by 3 (or simply: if there were 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 need to define inputs + outputs as reg or wire ? Or input and output ! enough?

  • Should I provide a vector size for reg state, nextstate ? If so, how do you know which measurement to choose?

  • Can I write statements at the end like state0 & input1 ? Or should I use state = state0 & input1 = ?? - yes, what?

+4
source share
3 answers

Do I need to define inputs + outputs as reg or wire? Or entry and exit! enough?

Inputs are always wires, although this does not really matter, since you do not assign them. Outputs are the default wires, although you can also declare output reg if you want to register instead.

Should I provide a vector dimension for reg, nextstate state? If so, how do you know which measurement to choose?

Yes, you must declare a measurement, otherwise your design will disastrously fail when verilog silently truncates all your states to 0 or 1 . The width of the states should be the same width of the local parameters that you use to define state names, or, more generally, should be log2(number of input states) .

Can I write statements at the end like state0 and input1?

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

 output = (state == state0) && input1; 
+2
source
 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 
+2
source

Although its too late, but I ended up in Verilog training wagon and decided to take a picture in your request. I wrote a design module, and also created a stand for it. It works according to your expectations.

 `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 
+1
source

All Articles