0
0
VerilogHow-ToBeginner · 4 min read

Verilog Traffic Light Controller FSM Code Example and Guide

A traffic light controller FSM in Verilog uses states to represent light colors and transitions between them on a clock. You define states with parameter, use a case statement inside an always block triggered by a clock, and output signals for red, yellow, and green lights accordingly.
📐

Syntax

A traffic light controller FSM in Verilog typically includes:

  • State definitions: Use parameter to name each state.
  • State register: Holds the current state, updated on clock edges.
  • Next state logic: Determines the next state based on the current state.
  • Output logic: Sets the traffic light signals based on the current state.

The FSM runs inside an always @(posedge clk or posedge reset) block to update states synchronously.

verilog
module traffic_light_fsm(
    input wire clk,
    input wire reset,
    output reg red,
    output reg yellow,
    output reg green
);

    // State encoding
    parameter RED = 2'b00, GREEN = 2'b01, YELLOW = 2'b10;

    reg [1:0] state, next_state;

    // State update
    always @(posedge clk or posedge reset) begin
        if (reset)
            state <= RED;
        else
            state <= next_state;
    end

    // Next state logic
    always @(*) begin
        case(state)
            RED: next_state = GREEN;
            GREEN: next_state = YELLOW;
            YELLOW: next_state = RED;
            default: next_state = RED;
        endcase
    end

    // Output logic
    always @(*) begin
        red = (state == RED);
        yellow = (state == YELLOW);
        green = (state == GREEN);
    end

endmodule
💻

Example

This example shows a simple traffic light controller FSM cycling through red, green, and yellow lights on each clock pulse. The reset input sets the light to red initially.

verilog
module traffic_light_fsm(
    input wire clk,
    input wire reset,
    output reg red,
    output reg yellow,
    output reg green
);

    parameter RED = 2'b00, GREEN = 2'b01, YELLOW = 2'b10;

    reg [1:0] state, next_state;

    always @(posedge clk or posedge reset) begin
        if (reset)
            state <= RED;
        else
            state <= next_state;
    end

    always @(*) begin
        case(state)
            RED: next_state = GREEN;
            GREEN: next_state = YELLOW;
            YELLOW: next_state = RED;
            default: next_state = RED;
        endcase
    end

    always @(*) begin
        red = (state == RED);
        yellow = (state == YELLOW);
        green = (state == GREEN);
    end

endmodule

// Testbench to simulate the FSM
module tb;
    reg clk = 0;
    reg reset = 1;
    wire red, yellow, green;

    traffic_light_fsm uut(.clk(clk), .reset(reset), .red(red), .yellow(yellow), .green(green));

    always #5 clk = ~clk; // 10 time units clock period

    initial begin
        $monitor($time, " ns: Red=%b Yellow=%b Green=%b", red, yellow, green);
        #10 reset = 0; // release reset
        #100 $finish;
    end
endmodule
Output
10 ns: Red=1 Yellow=0 Green=0 20 ns: Red=0 Yellow=0 Green=1 30 ns: Red=0 Yellow=1 Green=0 40 ns: Red=1 Yellow=0 Green=0 50 ns: Red=0 Yellow=0 Green=1 60 ns: Red=0 Yellow=1 Green=0 70 ns: Red=1 Yellow=0 Green=0 80 ns: Red=0 Yellow=0 Green=1 90 ns: Red=0 Yellow=1 Green=0 100 ns: Red=1 Yellow=0 Green=0
⚠️

Common Pitfalls

Common mistakes when writing a traffic light FSM in Verilog include:

  • Not using a reset signal to initialize the state, causing unpredictable outputs.
  • Mixing combinational and sequential logic incorrectly, leading to latches or glitches.
  • Forgetting to cover all states in the case statement, which can cause simulation warnings or unexpected behavior.
  • Assigning outputs inside the clocked block instead of a separate combinational block, reducing clarity.
verilog
/* Wrong: Missing reset and incomplete case */
always @(posedge clk) begin
    case(state)
        RED: state <= GREEN;
        GREEN: state <= YELLOW;
        // Missing YELLOW case
        default: state <= RED;
    endcase
end

/* Right: Include reset and all states */
always @(posedge clk or posedge reset) begin
    if (reset)
        state <= RED;
    else
        case(state)
            RED: state <= GREEN;
            GREEN: state <= YELLOW;
            YELLOW: state <= RED;
            default: state <= RED;
        endcase
end
📊

Quick Reference

Remember these key points when building a traffic light FSM in Verilog:

  • Use parameter to name states clearly.
  • Update state only on clock edges with reset support.
  • Use separate always blocks for state update, next state logic, and output logic.
  • Cover all states in your case statements to avoid latches.
  • Test your FSM with a simple testbench to verify correct light sequences.

Key Takeaways

Define states clearly using parameters and update them synchronously on clock edges with reset.
Separate next state logic and output logic into different combinational always blocks for clarity.
Always cover all states in your case statements to prevent unintended latches or simulation warnings.
Use a reset signal to initialize the FSM to a known state like RED.
Test your FSM with a simple testbench to confirm the traffic light cycles correctly.