Finite State Machine
Mealy vs Moore
From state diagrams to synthesizable Verilog — master FSM design with interactive traffic light and sequence detector simulators.
Mealy vs Moore — Core Difference
Moore FSM
- Output depends only on current state
- Output changes on clock edge (synchronized)
- Glitch-free — no combinational output path
- Needs more states than Mealy for same behavior
- State diagram: output labeled inside the state bubble
- Preferred in most RTL design guidelines
Mealy FSM
- Output depends on state AND input
- Output can change when input changes (async)
- Can glitch if inputs have glitches
- Fewer states needed — responds one cycle earlier
- State diagram: output labeled on the transition arrow
- Used when latency matters (serial protocols)
| Property | Moore | Mealy |
|---|---|---|
| Output function | f(state) | f(state, input) |
| Output timing | Registered (safe) | Combinational (fast) |
| Number of states | More | Fewer |
| Glitch risk | None | Possible |
| Response latency | 1 clock later | Same clock cycle |
| Diagram notation | State/Output | Input/Output on arc |
How to Design an FSM — Step by Step
- Identify states — Each distinct condition the system can be in becomes a state. Ask: "what information must the system remember?"
- Determine inputs and outputs — Inputs cause transitions. Outputs are either per-state (Moore) or per-transition (Mealy).
- Draw the state diagram — Circles = states, arrows = transitions labeled with input (and output for Mealy).
- Build the state table — Tabulate: current state × input → next state + output.
- Choose state encoding — Binary, one-hot, Gray, or Johnson. FPGAs: prefer one-hot.
- Derive next-state logic — K-map or boolean algebra from state table. For Verilog: let synthesis handle it.
- Implement and verify — 3-always-block Verilog + testbench with all state/input combinations.
State Encoding Comparison
| Encoding | Flip-flops | Logic Complexity | Best For |
|---|---|---|---|
| Binary | log₂(N) | High (complex decode) | ASIC area-optimized |
| One-Hot | N (one per state) | Low (simple decode) | FPGA (abundant FFs) |
| Gray | log₂(N) | Medium | Low power, counters |
| Johnson | N/2 | Medium | Ring counter variants |
Interactive Simulator — Traffic Light Controller (Moore)
Clock simulation — press Step
Verilog — 3-Always-Block Style
Moore FSM — Traffic Light Controller
// Moore FSM: output depends only on state
module traffic_light (
input logic clk, rst_n,
output logic [2:0] lights // {R, Y, G}
);
typedef enum logic [1:0] {RED, RED_GRN, GREEN, YELLOW} state_t;
state_t state, next;
// 1. State register
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) state <= RED;
else state <= next;
// 2. Next-state logic
always_comb case (state)
RED: next = RED_GRN;
RED_GRN: next = GREEN;
GREEN: next = YELLOW;
YELLOW: next = RED;
default: next = RED;
endcase
// 3. Output logic (Moore: only depends on state)
always_comb case (state)
RED: lights = 3'b100;
RED_GRN: lights = 3'b110;
GREEN: lights = 3'b001;
YELLOW: lights = 3'b010;
default: lights = 3'b100;
endcase
endmodule
Mealy FSM — Sequence Detector (101)
// Mealy FSM: output depends on state AND input
module seq_det_101 (
input logic clk, rst_n, x,
output logic z
);
typedef enum logic [1:0] {S0, S1, S2, S3} state_t;
state_t state, next;
// 1. State register
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) state <= S0;
else state <= next;
// 2. Next-state + output (Mealy: both depend on state AND x)
always_comb begin
next = S0; z = 1'b0;
case (state)
S0: if (x) begin next = S1; z = 0; end
else begin next = S0; z = 0; end
S1: if (x) begin next = S1; z = 0; end
else begin next = S2; z = 0; end
S2: if (x) begin next = S3; z = 1; end // match: 101
else begin next = S0; z = 0; end
S3: if (x) begin next = S1; z = 0; end
else begin next = S2; z = 0; end
endcase
end
endmodule
One-Hot Encoding (FPGA-Preferred)
// One-hot: N states → N flip-flops, exactly one '1' at a time
module fsm_onehot (
input logic clk, rst_n, in_a, in_b,
output logic out
);
typedef enum logic [3:0] {
IDLE = 4'b0001,
LOAD = 4'b0010,
PROC = 4'b0100,
DONE = 4'b1000
} state_t;
state_t state;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) state <= IDLE;
else case (state)
IDLE: state <= in_a ? LOAD : IDLE;
LOAD: state <= PROC;
PROC: state <= in_b ? DONE : PROC;
DONE: state <= IDLE;
default: state <= IDLE; // safe — handles bit errors
endcase
assign out = (state == DONE);
endmodule
Safe FSM — Handling Illegal States
// Always add default — prevents lockup from cosmic ray / power glitch
always_comb case (state)
IDLE: next = START;
START: next = in ? RUN : IDLE;
RUN: next = done ? DONE : RUN;
DONE: next = IDLE;
default: next = IDLE; // ← CRITICAL for safety
endcase
Common FSM Patterns in RTL Design
| Pattern | Use Case | States |
|---|---|---|
| Handshake FSM | AXI, APB, UART — valid/ready protocol | IDLE → REQ → ACK → IDLE |
| Timeout FSM | Watchdog, protocol timeout detection | IDLE → WAIT (counter) → TIMEOUT |
| Arbitration FSM | Bus arbiter, shared resource | IDLE → GRANT_A / GRANT_B → RELEASE |
| Control FSM | Memory controller, DMA | IDLE → FETCH → DECODE → EXECUTE |
| Sequence Detector | Pattern match in serial data | S0→S1→…→MATCH |
| Power Gating FSM | Low-power design, ISO/clamp control | ON → ISOLATE → OFF → RESTORE → ON |
Frequently Asked Questions
What is the difference between a Mealy and Moore FSM?
Moore: output = f(state). Mealy: output = f(state, input). Moore is glitch-free; Mealy responds one cycle faster and needs fewer states.
Why is one-hot encoding preferred on FPGAs?
FPGAs have abundant flip-flops and small LUTs. One-hot decoding is just checking a single bit — minimal LUT depth. Binary encoding would need log₂(N) bits decoded through logic — more LUT levels, slower.
What is a safe FSM and why does it matter?
A safe FSM always transitions back to a known state when in an illegal encoding. Adding default: state <= RESET prevents the FSM from hanging if radiation or a glitch corrupts the state register.
How many always blocks should a Verilog FSM use?
The industry-standard 3-always-block style: (1) state register — always_ff with clock/reset, (2) next-state logic — always_comb, (3) output logic — always_comb for Mealy or Moore. This separation produces clean synthesis and straightforward STA.