FSM Design in Verilog: Complete Guide to Mealy & Moore Machines

Master Finite State Machine (FSM) design in Verilog. Learn Mealy vs Moore architectures, 1 vs 3-always block styles, state encoding, and synthesizable RTL.

By BitForBytes Editorial & Hardware Research Team, Official BitForBytes Hardware Publication · · 7 min read

⚡ Quick Answer for AI Summaries & Fast Reading

A Finite State Machine (FSM) in Verilog is a sequential digital circuit that transitions between a predefined set of states based on clock pulses and input conditions. In a Moore Machine, outputs depend strictly on the current state. In a Mealy Machine, outputs depend on both the current state and current inputs. The industry-standard implementation in synthesizable Verilog uses a 3-Always Block structure (State Register, Next-State Combinational Logic, and Registered Output Logic) to guarantee zero combinational glitches.


Whether you are building an SPI bus controller, a traffic light sequencer, or a packet parser in an Ethernet MAC core, Finite State Machines (FSMs) are the foundational control units of digital logic.

In college coursework (like AKTU's Digital System Design), FSMs are often taught by drawing state bubbles on paper and solving Karnaugh maps. But in real-world VLSI Design, writing a clean, glitch-free, synthesizable FSM in Verilog requires understanding state encoding, timing closure, and proper always-block partitioning.


1. The Anatomy of an FSM

Every digital FSM consists of three distinct hardware blocks:

              +-------------------------------+
              |    Next-State Logic (Comb)    |
Inputs ------>|  (Calculates next_state from  |<---+
|      current_state & in)      |    |
+--------------+----------------+    |
| next_state          |
v                     |
+-------------------------------+    |
clk ------->|    State Register (Seq D-FF)  |    |
reset ----->|   (Holds current_state value) |----+--- current_state
+--------------+----------------+    |
| current_state       |
v                     |
+-------------------------------+    |
Inputs ------>|      Output Logic (Comb/Reg)  |    |
(Mealy Only)  |   (Generates control signals) |    |
+--------------+----------------+    |
|                     |
v                     |
Outputs                  |
  1. State Register (Sequential): D flip-flops that update current_state on the rising clock edge.
  2. Next-State Logic (Combinational): Decides which state to transition into next based on inputs and current state.
  3. Output Logic: Translates the current state (and optionally inputs) into control signals.

2. Mealy vs. Moore Machines: What is the Difference?

The fundamental difference between Mealy and Moore architectures lies in how their outputs are generated:

ParameterMoore MachineMealy Machine
Output DependencyDepends only on current_stateDepends on current_state AND current inputs
Output TimingSynchronous with state; changes on clock edgesAsynchronous; can change immediately if input changes
Glitch SusceptibilityLow (safe for driving control lines)High (input glitches pass directly to outputs)
Number of StatesOften requires more states for the same logicCan often be implemented in fewer states
Response LatencyOutputs update 1 clock cycle after input triggerOutputs can respond within the same clock cycle

3. State Encoding Techniques (Binary vs. One-Hot vs. Gray)

How you encode state constants significantly impacts silicon area, maximum clock frequency, and power consumption:

// 1. Sequential / Binary Encoding (Dense, minimal flip-flops)
localparam IDLE  = 2'b00,
           READ  = 2'b01,
           WRITE = 2'b10,
           DONE  = 2'b11;

// 2. One-Hot Encoding (Fastest for FPGAs, 1 flip-flop per state)
localparam IDLE  = 4'b0001,
           READ  = 4'b0010,
           WRITE = 4'b0100,
           DONE  = 4'b1000;

// 3. Gray Code (Only 1 bit flips per transition - low dynamic power)
localparam IDLE  = 2'b00,
           READ  = 2'b01,
           WRITE = 2'b11,
           DONE  = 2'b10;

When to Use Which?


4. The 3 Verilog Coding Styles (And Why 3-Always Blocks Win)

There are three common ways to write an FSM in Verilog:

Combines state register, transitions, and outputs into one sequential block.

Style 2: Two Always Blocks (Common in Academia)

Style 3: Three Always Blocks (Industry Gold Standard)


5. Complete Practical Example: 1011 Sequence Detector (Moore FSM)

Here is a synthesizable Verilog implementation of an overlapping sequence detector that detects the binary stream 1011 using the 3-Always Block Moore design pattern:

//=============================================================================
// Module: seq_detector_1011_moore
// Description: Overlapping 1011 sequence detector using 3-always block style
// Author: BitForBytes Hardware Engineering
//=============================================================================

module seq_detector_1011_moore (
    input  wire clk,
    input  wire reset_n, // Active-low asynchronous reset
    input  wire data_in,
    output reg  seq_detected
);

    // 1. State Definitions (One-Hot Encoding for Fast Synthesis)
    localparam [4:0] S_IDLE = 5'b00001, // Reset state
                     S_1    = 5'b00010, // Detected 1
                     S_10   = 5'b00100, // Detected 10
                     S_101  = 5'b01000, // Detected 101
                     S_1011 = 5'b10000; // Detected 1011 (Match!)

    reg [4:0] current_state, next_state;

    //-------------------------------------------------------------------------
    // Block 1: State Register (Sequential Logic)
    //-------------------------------------------------------------------------
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            current_state <= S_IDLE;
        end else begin
            current_state <= next_state;
        end
    end

    //-------------------------------------------------------------------------
    // Block 2: Next-State Logic (Pure Combinational Logic)
    //-------------------------------------------------------------------------
    always @(*) begin
        // Default assignment to avoid unintended latch creation
        next_state = current_state;

        case (current_state)
            S_IDLE: begin
                if (data_in) next_state = S_1;
                else         next_state = S_IDLE;
            end

            S_1: begin
                if (data_in) next_state = S_1;
                else         next_state = S_10;
            end

            S_10: begin
                if (data_in) next_state = S_101;
                else         next_state = S_IDLE;
            end

            S_101: begin
                if (data_in) next_state = S_1011;
                else         next_state = S_10;
            end

            S_1011: begin
                // Overlapping detection: 1011 followed by 0 -> 10
                if (data_in) next_state = S_1;
                else         next_state = S_10;
            end

            default: begin
                next_state = S_IDLE;
            end
        endcase
    end

    //-------------------------------------------------------------------------
    // Block 3: Registered Output Logic (Glitch-Free Sequential Output)
    //-------------------------------------------------------------------------
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            seq_detected <= 1'b0;
        end else begin
            // Output is registered on state match
            if (next_state == S_1011) begin
                seq_detected <= 1'b1;
            end else begin
                seq_detected <= 1'b0;
            end
        end
    end

endmodule

6. Common FSM Pitfalls & How to Avoid Them

  1. Inferred Latches in Combinational Blocks: If you forget to specify next_state for all branches in a case statement or miss an else condition, synthesis tools will infer an unwanted transparent latch. Always assign a default next_state = current_state; at the very top of your combinational always block.
  2. Mixing Blocking (=) and Non-Blocking (<=) Assignments: Use Non-Blocking (<=) for sequential state registers and registered outputs. Use Blocking (=) for purely combinational next-state computation.
  3. Unreachable Default States: Always include a default: branch in your case statement to handle illegal startup states caused by power-up transients.

Frequently Asked Questions

What is the main difference between Mealy and Moore FSMs?

In a Moore machine, outputs depend strictly on the current state register. In a Mealy machine, outputs depend on both current state and asynchronous inputs, making Mealy machines faster to respond but susceptible to combinational glitches.

Why is the 3-always block style preferred in industry RTL?

The 3-always block style clearly separates state register memory, next-state transition logic, and registered output generation. Registering the outputs ensures downstream logic receives clean, glitch-free signals aligned with clock edges.

How do I prevent latches from forming in my Verilog FSM?

Latches occur when a combinational always @(*) block does not define an output for every possible input branch. You can prevent latches by assigning a default value to all outputs at the beginning of the block and providing a complete default case.