6.3 Verilog State Machine
Category Verilog Tutorial
Keywords: State Machine, Vending Machine
Finite-State Machine (FSM), abbreviated as state machine, is a mathematical model representing a finite number of states and the transitions and actions between these states. State machines are not only a description tool for circuits but also a methodological approach, widely used at both system and RTL levels in circuit design.
Types of State Machines
In Verilog, state machines are primarily used for the design of synchronous sequential logic, enabling transitions between a finite number of states according to specific requirements and rules. The direction of state transitions depends not only on the input values but also on the current state. State machines can be categorized into two types: Moore state machines and Mealy state machines.
Moore State Machine
The output of a Moore state machine is solely dependent on the current state and independent of the current input.
The output remains stable for a complete clock cycle, and even if the input signal changes, the output does not change. The effect of the input on the output is reflected only in the next clock cycle. This is a significant characteristic of Moore state machines: inputs and outputs are isolated.
Mealy State Machine
The output of a Mealy state machine depends on both the current state and the current input signal.
The output of a Mealy state machine changes immediately after the input signal changes, and input changes can occur at any state within the clock cycle. Therefore, under the same logic, the Mealy state machine's output responds to inputs one clock cycle earlier than the Moore state machine.
State Machine Design Process
Draw the state transition diagram based on the design requirements, determine the type of state machine to be used, and label various input and output signals, which helps in programming. The most commonly used is the Mealy-type three-segment state machine. Below is an example of designing a state machine for an automatic vending machine.
Vending Machine
Function Description of the Vending Machine:
The price of a drink is 2 yuan, and the vending machine accepts only 0.5 yuan and 1 yuan coins. Consider change and dispensing. Both the coin insertion and dispensing processes are done one by one, without multiple coins being inserted at once or multiple drinks being dispensed at once. Each round of the vending machine, after completing the coin acceptance, dispensing, and change, enters a new vending state.
The state transition diagram of the vending machine is shown below, including input and output signal states.
Here, coin = 1 represents the insertion of a 0.5 yuan coin, and coin = 2 represents the insertion of a 1 yuan coin.
State Machine Design: Three-Segment (Recommended)
State Machine Design:
- (0) First, determine the state machine encoding based on the number of states. Assign values to the state register using encoding for better code readability.
- (1) The first segment of the state machine, sequential logic, uses non-blocking assignments to transfer the state of the register.
- (2) The second segment of the state machine, combinational logic, uses blocking assignments to determine the next state of the state machine based on the current state and current input.
- (3) The third segment of the state machine, sequential logic, uses non-blocking assignments. Since it is a Mealy-type state machine, the output signal is determined based on the current state and current input.
Example
// vending-machine
// 2 yuan for a bottle of drink
// only 2 coins supported: 5 jiao and 1 yuan
// finish the function of selling and changing
module vending_machine_p3 (
input clk,
input rstn,
input [1:0] coin, //01 for 0.5 jiao, 10 for 1 yuan
output [1:0] change,
output sell //output the drink
);
//machine state decode
parameter IDLE = 3'd0;
parameter GET05 = 3'd1;
parameter GET10 = 3'd2;
parameter GET15 = 3'd3;
//machine variable
reg [2:0] st_next;
reg [2:0] st_cur;
//(1) state transfer
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
st_cur <= 'b0;
end
else begin
st_cur <= st_next;
end
end
//(2) state switch, using block assignment for combination-logic
//all case items need to be displayed completely
always @(*) begin
//st_next = st_cur ;//如果条件选项考虑不全,可以赋初值消除latch
case(st_cur)
IDLE:
case (coin)
2'b01: st_next = GET05;
2'b10: st_next = GET10;
default: st_next = IDLE;
endcase
GET05:
case (coin)
2'b01: st_next = GET10;
2'b10: st_next = GET15;
default: st_next = GET05;
endcase
GET10:
case (coin)
2'b01: st_next = GET15;
2'b10: st_next = IDLE;
default: st_next = GET10;
endcase
GET15:
case (coin)
2'b01,2'b10:
st_next = IDLE;
default: st_next = GET15;
endcase
default: st_next = IDLE;
endcase
end
//(3) output logic, using non-block assignment
reg [1:0] change_r;
reg sell_r;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
change_r <= 2'b0;
sell_r <= 1'b0;
end
else if ((st_cur == GET15 && coin ==2'h1)
|| (st_cur == GET10 && coin ==2'd2)) begin
change_r <= 2'b0;
sell_r <= 1'b1;
end
else if (st_cur == GET15 && coin == 2'h2) begin
change_r <= 2'b1;
sell_r <= 1'b1;
end
else begin
change_r <= 2'b0;
sell_r <= 1'b0;
end
end
assign sell = sell_r;
assign change = change_r;
endmodule
Testbench Design is as follows. Four scenarios are simulated:
case1 corresponds to the continuous input of four 5 jiao coins; case2 corresponds to the sequence of 1 yuan - 5 jiao - 1 yuan; case3 corresponds to the sequence of 5 jiao - 1 yuan - 5 jiao; case4 corresponds to the continuous input of three 5 jiao coins followed by one 1 yuan coin.
Example
`timescale 1ns/1ps
module test;
reg clk;
reg rstn;
reg [1:0] coin;
wire [1:0] change;
wire sell;
//clock generating
parameter CYCLE_200MHz = 10; //
always begin
clk = 0; #(CYCLE_200MHz/2);
clk = 1; #(CYCLE_200MHz/2);
end
//motivation generating
reg [9:0] buy_oper; //store state of the buy operation
initial begin
buy_oper = 'h0;
coin = 2'h0;
rstn = 1'b0;
#8 rstn = 1'b1;
@(negedge clk);
//case(1) 0.5 -> 0.5 -> 0.5 -> 0.5
#16;
buy_oper = 10'b00_0101_0101;
repeat(5) begin
@(negedge clk);
coin = buy_oper[1:0];
buy_oper = buy_oper >> 2;
end
//case(2) 1 -> 0.5 -> 1, taking change
#16;
buy_oper = 10'b00_0010_0110;
repeat(5) begin
@(negedge clk);
// Simulation results are as follows:
As shown in the figure, the signal representing the dispensing action, sell, is able to be pulled high normally after the coins are inserted. The signal representing the change action, change, also outputs the correct change signal according to the input coin scenario.
[ ](https://www.tutorialpro.org/wp-content/uploads/2020/09/ymJcSH14aenfZbDR.png)
### State Machine Modification: 2-Stage
**Merging the 2nd and 3rd stages of the 3-stage state machine, while keeping other parts unchanged, transforms the state machine into a 2-stage description.**
The modification is as follows:
## Example
//(2) State switch, and output logic // All using block assignment for combination-logic reg [1:0] change_r ; reg sell_r ; always @(*) begin // All case items need to be displayed completely case(st_cur) IDLE: begin change_r = 2'b0 ; sell_r = 1'b0 ; case (coin) 2'b01: st_next = GET05 ; 2'b10: st_next = GET10 ; default: st_next = IDLE ; endcase // case (coin) end GET05: begin change_r = 2'b0 ; sell_r = 1'b0 ; case (coin) 2'b01: st_next = GET10 ; 2'b10: st_next = GET15 ; default: st_next = GET05 ; endcase // case (coin) end
GET10:
case (coin)
2'b01: begin
st_next = GET15 ;
change_r = 2'b0 ;
sell_r = 1'b0 ;
end
2'b10: begin
st_next = IDLE ;
change_r = 2'b0 ;
sell_r = 1'b1 ;
end
default: begin
st_next = GET10 ;
change_r = 2'b0 ;
sell_r = 1'b0 ;
end
endcase // case (coin)
GET15:
case (coin)
2'b01: begin
st_next = IDLE ;
change_r = 2'b0 ;
sell_r = 1'b1 ;
end
2'b10: begin
st_next = IDLE ;
change_r = 2'b1 ;
sell_r = 1'b1 ;
end
default: begin
st_next = GET15 ;
change_r = 2'b0 ;
sell_r = 1'b0 ;
end
endcase
default: begin
st_next = IDLE ;
change_r = 2'b0 ;
sell_r = 1'b0 ;
end
endcase
end
**Instantiating the modified new module into the 3-stage testbench for simulation, the results are as follows:**
As shown in the figure, the dispensing signal sell and the change signal change are advanced by one clock cycle compared to the 3-stage state machine output, due to the blocking assignment of the output signals.
As indicated by the red circles in the figure, interference pulses appear in the output signals, because the input signals are asynchronous and the output signals are combinational logic outputs without clock drive.
In practice, if the input signals are synchronized with the clock, such interference pulses will not appear. If the input signals are asynchronous, the signals should first be synchronized.
[ ](https://www.tutorialpro.org/wp-content/uploads/2020/09/mLTvRsiPSEgpti4Y.png)
### State Machine Modification: 1-Stage (Use with Caution)
**Merging the 1st, 2nd, and 3rd stages of the 3-stage state machine, the state machine becomes a 1-stage description.**
The modification is as follows:
## Example
//(1) Using one state-variable to describe reg [1:0] change_r ; reg sell_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin st_cur <= 'b0 ; change_r <= 2'b0 ; sell_r <= 1'b0 ; end else begin case(st_cur)
IDLE: begin
change_r <= 2'b0 ;
sell_r <= 1'b0 ;
case (coin)
2'b01: st_cur <= GET05 ;
2'b10: st_cur <= GET10 ;
endcase
end
GET05: begin
case (coin)
2'b01: st_cur <= GET10 ;
2'b10: st_cur <= GET15 ;
endcase
end
GET10:
case (coin)
2'b01: st_cur <= GET15 ;
2'b10: begin
st_cur <= IDLE ;
sell_r <= 1'b1 ;
end
endcase
GET15:
case (coin)
2'b01: begin
st_cur <= IDLE ;
sell_r <= 1'b1 ;
end
2'b10: begin
st_cur <= IDLE ;
change_r <= 2'b1 ;
sell_r <= 1'b1 ; end endcase
default: begin st_cur <= IDLE ; end
endcase // case (st_cur) end // else: !if(!rstn) end
**Instantiate the modified new module into a 3-segment testbench for simulation, and the results are as follows:**
As shown in the figure, the output signal is identical to the 3-segment state machine.
The drawback of the 1-segment state machine is that many logics are mixed together, making it difficult for later maintenance. When the state machine and output signals are few, this description method can be tried.
[](https://www.tutorialpro.org/wp-content/uploads/2020/09/DCvzwVT7h58iH0aN.png)
### State Machine Modification: Moore Type
If the vending machine's workflow is described using a Moore-type state machine, then two more state encodings need to be added to describe the input signals and state machine states when the Mealy state machine outputs.
The Verilog code for the automatic vending machine described by the 3-segment Moore-type state machine is as follows:
## Example
module vending_machine_moore ( input clk, input rstn, input [1:0] coin, //01 for 0.5 jiao, 10 for 1 yuan
output [1:0] change, output sell //output the drink );
//machine state decode parameter IDLE = 3'd0 ; parameter GET05 = 3'd1 ; parameter GET10 = 3'd2 ; parameter GET15 = 3'd3 ; // new state for moore state-machine parameter GET20 = 3'd4 ; parameter GET25 = 3'd5 ;
//machine variable reg [2:0] st_next ; reg [2:0] st_cur ;
//(1) state transfer always @(posedge clk or negedge rstn) begin if (!rstn) begin st_cur <= 'b0 ; end else begin st_cur <= st_next ; end end
//(2) state switch, using block assignment for combination-logic always @(*) begin //all case items need to be displayed completely case(st_cur) IDLE: case (coin) 2'b01: st_next = GET05 ; 2'b10: st_next = GET10 ; default: st_next = IDLE ; endcase GET05: case (coin) 2'b01: st_next = GET10 ; 2'b10: st_next = GET15 ; default: st_next = GET05 ; endcase
GET10: case (coin) 2'b01: st_next = GET15 ; 2'b10: st_next = GET20 ; default: st_next = GET10 ; endcase GET15: case (coin) 2'b01: st_next = GET20 ; 2'b10: st_next = GET25 ; default: st_next = GET15 ; endcase GET20: st_next = IDLE ; GET25: st_next = IDLE ; default: st_next = IDLE ; endcase // case (st_cur) end // always @ (*)
// (3) output logic, // one cycle delayed when using non-block assignment reg [1:0] change_r ; reg sell_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin change_r <= 2'b0 ; sell_r <= 1'b0 ; end else if (st_cur == GET20 ) begin sell_r <= 1'b1 ; end else if (st_cur == GET25) begin change_r <= 2'b1 ; sell_r <= 1'b1 ; end else begin change_r <= 2'b0 ; sell_r <= 1'b0 ; end end assign sell = sell_r ; assign change = change_r ;
endmodule
**Instantiate the modified Moore state machine into a 3-segment testbench for simulation, and the results are as follows:**
As shown in the figure, the output signal is delayed by one clock cycle compared to the Mealy-type 3-segment state machine, because it takes one clock cycle of delay to enter the newly added encoded state machine. At this time, the output using non-blocking assignment will cause the final output signal to be delayed by one clock cycle. This is also a characteristic of the Moore-type state machine.
**When assigning the output signal, using blocking assignment can advance by one clock cycle.**
Modify the output logic as follows.
## Example
// (3.2) output logic, using block assignment reg [1:0] change_r ; reg sell_r ; always @(*) begin change_r = 'b0 ; sell_r = 'b0 ; //not list all condition, initializing them if (st_cur == GET20 ) begin sell_r = 1'b1 ; end else if (st_cur == GET25) begin change_r = 2'b1 ; sell_r = 1'b1 ; end end
**The simulation results of the output signal blocking assignment are as follows:**
As shown in the figure, the output signal is now consistent with the 3-segment Mealy-type state machine.
### Source Code Download
[Download](https://www.tutorialpro.org/wp-content/uploads/2020/09/6.3state-machine.zip)
-[1.1 Verilog Tutorial](verilog-tutorial.html)
-[1.2 Verilog Introduction](verilog-intro.html)
-[1.3 Verilog Environment Setup](verilog-install.html)
-[1.4 Verilog Design Method](verilog-design-method.html)
-[2.1 Verilog Basic Syntax](verilog-basic-syntax.html)
-[2.2 Verilog Numerical Representation](verilog-number.html)
-[2.3 Verilog Data Types](verilog-data-type.html)
-[2.4 Verilog Expressions](verilog-expression.html)
-[2.5 Verilog Compile Instructions](verilog-compile-instruction.html)
-[3.1 Verilog Continuous Assignment](verilog-assign.html)
-[3.2 Verilog Time Delay](verilog-time-delay.html)
-[4.1 Verilog Process Structure](verilog-process-structure.html)
-[4.2 Verilog Process Assignment](verilog-process-assign.html)
-[4.3 Verilog Timing Control](verilog-timing-control.html)
-[4.4 Verilog Statement Blocks](verilog-statements-block.html)
-[4.5 Verilog Conditional Statements](verilog-condition-statement.html)
-[4.6 Verilog Multi-branch Statements](verilog-case.html)
-[4.7 Verilog Loop Statements](verilog-loop.html)
-[4.8 Verilog Process Continuous Assignment](verilog-deassign.html)
-[5.1 Verilog Modules and Ports](verilog-module-port.html)
- 5.2 Verilog Module Instantiation
- 5.3 Verilog Parameterized Instantiation
- 6.1 Verilog Functions
- 6.2 Verilog Tasks
- 6.3 Verilog State Machine
- 6.4 Verilog Race and Hazard
- 6.5 Verilog Avoiding Latch
- 6.6 Verilog Simulation Stimulus
- 6.7 Verilog Pipeline Design
- 7.1 Verilog Divider Design
- 7.2 Verilog Parallel FIR Filter Design
- 7.3 Verilog Serial FIR Filter Design
- 7.4 Verilog CIC Filter Design
- 7.5 Verilog FFT Design
- 7.6 Verilog DDS Design
- 8.1 Verilog Numerical Conversion
- Advanced Verilog Tutorial