Finite State Machines (FSMs) are fundamental building blocks in digital design, controlling everything from simple counters to complex communication protocols. If you’re learning Verilog or designing digital circuits, understanding how to implement FSMs efficiently is essential.
In this blog post, we’ll walk through the core components of an FSM, provide a practical example of a traffic light controller in Verilog, and share a Moore as well as a Mealy machine example for comparison. Whether you’re a beginner or brushing up your skills, this guide will help you write clean, synthesizable FSM code.
What is a Finite State Machine (FSM)?
An FSM is a sequential logic circuit that transitions between a finite number of states based on inputs and clock signals. It consists of three main parts:
- State Register: Holds the current state and updates on clock edges.
- Next State Logic: Combinational logic that decides the next state based on the current state and inputs.
- Output Logic: Generates outputs depending on the current state (Moore machine) or current state and inputs (Mealy machine).
Key Concepts for FSM Implementation in Verilog
- States: Typically represented using
parameter
orlocalparam
for readability and maintainability. - Synchronous Reset: Resets the FSM to a known initial state on a clock edge.
- Combinational Next State Logic: Usually implemented with a
case
statement. - Output Logic: Can be inside the next state block or a separate block depending on Moore or Mealy FSM style.
Example: Traffic Light Controller (Moore FSM)
This example cycles through three states – RED, GREEN, and YELLOW – based on a timer_expired
input signal.
module traffic_light_fsm (
input wire clk,
input wire reset,
input wire timer_expired,
output reg [1:0] light // 2-bit output: 00=RED, 01=GREEN, 10=YELLOW
);
// State encoding using parameters
parameter RED = 2'b00;
parameter GREEN = 2'b01;
parameter YELLOW = 2'b10;
reg [1:0] state, next_state;
// State register: updates on clock edge or reset
always @(posedge clk or posedge reset) begin
if (reset)
state <= RED; // Initial state
else
state <= next_state;
end
// Next state logic: combinational
always @(*) begin
case(state)
RED: next_state = timer_expired ? GREEN : RED;
GREEN: next_state = timer_expired ? YELLOW : GREEN;
YELLOW: next_state = timer_expired ? RED : YELLOW;
default: next_state = RED;
endcase
end
// Output logic: Moore machine (depends only on state)
always @(*) begin
case(state)
RED: light = 2'b00;
GREEN: light = 2'b01;
YELLOW: light = 2'b10;
default: light = 2'b00;
endcase
end
endmodule
Explanation
- The state register holds the current state and updates on the rising clock edge or resets to RED.
- The next state logic decides the next state based on the current state and
timer_expired
input. - The output logic assigns the
light
output based solely on the current state, making this a Moore FSM. timer_expired
acts as an external timer signal to trigger state transitions.
Mealy FSM Example: Traffic Light Controller with Immediate Output Response
In a Mealy FSM, outputs depend on both the current state and inputs, allowing outputs to change immediately with inputs.
module traffic_light_mealy_fsm (
input wire clk,
input wire reset,
input wire timer_expired,
output reg [1:0] light
);
parameter RED = 2'b00;
parameter GREEN = 2'b01;
parameter YELLOW = 2'b10;
reg [1:0] state, next_state;
// State register
always @(posedge clk or posedge reset) begin
if (reset)
state <= RED;
else
state <= next_state;
end
// Next state and output logic combined
always @(*) begin
case(state)
RED: begin
next_state = timer_expired ? GREEN : RED;
light = timer_expired ? 2'b01 : 2'b00; // GREEN or RED
end
GREEN: begin
next_state = timer_expired ? YELLOW : GREEN;
light = timer_expired ? 2'b10 : 2'b01; // YELLOW or GREEN
end
YELLOW: begin
next_state = timer_expired ? RED : YELLOW;
light = timer_expired ? 2'b00 : 2'b10; // RED or YELLOW
end
default: begin
next_state = RED;
light = 2'b00;
end
endcase
end
endmodule
Explanation
- The output
light
changes immediately based on both the current state and the inputtimer_expired
. - This can make the output more responsive compared to a Moore FSM.
- The Mealy FSM may have fewer states or simpler logic for some applications.
Verilog Testbench: Traffic Light Controller
`timescale 1ns / 1ps
module tb_traffic_light_fsm;
reg clk;
reg reset;
reg timer_expired;
wire [1:0] light;
// ============================
// DUT Instantiation:
// Uncomment one of the following lines to test the desired FSM
// ============================
// For Moore FSM:
// traffic_light_fsm uut (
// .clk(clk),
// .reset(reset),
// .timer_expired(timer_expired),
// .light(light)
// );
// For Mealy FSM:
traffic_light_mealy_fsm uut (
.clk(clk),
.reset(reset),
.timer_expired(timer_expired),
.light(light)
);
// Clock generation: 10 ns period (100 MHz)
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Test stimulus
initial begin
// Initialize inputs
reset = 1;
timer_expired = 0;
// Release reset after 15 ns
#15;
reset = 0;
// Generate timer_expired pulses to trigger state transitions
repeat (3) begin
#20; // Wait 20 ns in current state
timer_expired = 1;
#10; // timer_expired asserted for 10 ns
timer_expired = 0;
end
#50;
$finish;
end
// Monitor outputs
initial begin
$display("Time\tReset\tTimer\tLight");
$monitor("%0t\t%b\t%b\t%b", $time, reset, timer_expired, light);
end
endmodule
Explanation:
- A 100 MHz clock toggles every 5 ns.
- Active-high reset asserted initially, then deasserted after 15 ns.
timer_expired
pulses high for 10 ns every 30 ns to simulate timer expiration.- The
$monitor
statement prints the time, reset, timer signal, and outputs from both FSMs side by side.
Implementing FSMs in Verilog is a foundational skill for digital designers. Whether you choose Moore or Mealy depends on your design requirements for output timing and complexity. The traffic light controller example demonstrates clear, synthesizable FSM code in Verilog, suitable for beginners and professionals alike.