FPGA

FSM design in FPGA

By CourseTron Team ·  8 min read ·  Updated Oct 2026 💬 𝕏 in f
Table of Contents
    ? Print / Save as PDF

    In short: A Moore FSM decides outputs from state alone (glitch-free, one cycle later), a Mealy FSM folds inputs into outputs (fewer states, faster response but combinational risk), and on FPGAs one-hot encoding plus an explicit default/reset transition is what keeps a state machine fast, timing-clean, and recoverable from illegal states.

    Finite state machines are the control backbone of almost every RTL block you will ever write — a UART, an SPI master, a memory arbiter, a DMA engine, an AXI handshake. Yet FSMs are also where junior designers quietly lose area, timing, and functional safety. This guide walks through the design decisions that matter in silicon, with concrete numbers and the tool behaviour you will actually see in Vivado, Quartus, Synopsys Design Compiler, or Siemens Questa.

    Moore vs Mealy: where do the outputs come from?

    The only formal difference is the output function. In a Moore machine the output is a function of the current state only: out = f(state). In a Mealy machine the output is a function of state and the current inputs: out = f(state, in). That one change ripples into timing, latency, and testability.

    MOORE: out = f(state) MEALY: out = f(state, in) State reg out = f(S) output changes after clock edge State reg out = f(S,in) in (combinational path) output reacts mid-cycle CourseTron · coursetron.com
    Moore outputs are registered by the state; Mealy outputs ride a combinational path straight from the inputs.

    Because a Moore output changes only after a clock edge, it is naturally glitch-free and easy to constrain — the output leaves a flip-flop or a small decode of registered state. A Mealy output can change mid-cycle as soon as an input wiggles, which is why it reacts one cycle earlier but can also create combinational spikes if you feed it to anything asynchronous. For a protocol like SPI, a Mealy machine typically needs 2–3 fewer states to assert cs_n and sclk at exactly the right phase, but you pay for it with a longer input-to-output timing arc that the synthesis tool must close.

    Rule of thumb: if a downstream block samples your output on a clock edge, Moore is almost always the safer default. Reserve Mealy for latency-critical handshakes (e.g. an AXI VALID/READY pair) where saving a cycle genuinely matters.

    State encoding: binary, gray, and one-hot

    How you number the states is not cosmetic — it directly sets the width of the state register and the depth of the next-state logic. Three schemes dominate:

    EncodingFlip-flops for N statesNext-state logicBest for
    Binaryceil(log2 N)Wide, deep decodeASIC, FF-limited designs
    Grayceil(log2 N)Medium; 1-bit transitionsLow-power, CDC counters
    One-hotNShallow, 1 bit per stateFPGA (FF-rich fabric)

    On an FPGA the arithmetic favours one-hot. A Xilinx or Intel fabric is drowning in flip-flops — every LUT already ships with a paired register — so spending N flops instead of log2(N) costs almost nothing, while the next-state logic collapses to a single AND/OR term per state. A 12-state controller in binary needs 4 FFs but a 3–4 LUT-deep decoder; in one-hot it needs 12 FFs but typically a single LUT level, often shaving 1–2 ns off the critical path. That is exactly why Vivado’s FSM_ENCODING attribute and Quartus default to one-hot for FPGA targets, whereas Design Compiler leans toward binary for a cell-area-limited ASIC flow.

    One-hot register: exactly one bit high S0 bit0 S1 bit1 S2 bit2 S3 bit3 wrap back to S0 register: 1000 → 0100 → 0010 → 0001 CourseTron · coursetron.com
    In one-hot, the active state is a single asserted flip-flop that shifts along as the machine advances — next-state logic is just "which neighbour lit me up?"

    Safe state machines: surviving the illegal state

    One-hot has a hidden cost: of its 2^N raw encodings, only N are legal. A single-event upset (an alpha particle or a glitchy reset) can flip the register to 0000 or 0110 — a state your case never mentions. If the HDL has no defined recovery, the machine locks up until the next power cycle. In aerospace, automotive (ISO 26262), or any 24/7 datacentre FPGA, that is a field failure.

    A safe FSM adds an explicit escape. In SystemVerilog, use a unique case with a default branch that forces the machine back to its reset/idle state, and in Vivado set (* fsm_safe_state = "reset_state" *) so the tool synthesises a hang detector that drives the register to a known-good value. Intel Quartus exposes the same idea through its Safe State Machine setting, and Siemens Questa can formally prove — with an assertion like assert property (@(posedge clk) onehot(state)) — that the live design never leaves the legal set.

    Never let the synthesis tool "optimise away" the default branch. If you write case without default, the tool assumes the illegal states are don’t-cares and may build logic that can never recover. Always code the default, and verify it with a fault-injection testbench.

    Safe FSM: illegal state recovers to IDLE Illegal state 0110 (bit-flip) default branch next = IDLE IDLE legal, one-hot one-hot: only N of 2^N encodings are legal no default: don’t-care, may never recover with default: back to IDLE in one cycle CourseTron · coursetron.com
    A safe one-hot FSM maps an illegal encoding such as 0110 back to IDLE through its default branch.

    A clean three-process template

    The template that survives code review and closes timing cleanly separates concerns into three blocks: a sequential state register, a combinational next-state function, and a combinational (or registered) output function.

    • State register — one always_ff with synchronous or asynchronous reset to IDLE. Nothing else lives here.
    • Next-state logic — one always_comb with a unique case (state) and a mandatory default: next = IDLE;.
    • Output logic — registered for Moore, combinational for Mealy. Keep it a separate block so the intent is unambiguous to both the reader and the tool.

    This structure maps one-to-one onto how pipelining in FPGA stages are reasoned about, and it is the same discipline you apply when you push an FSM into a deeper timing-closure flow. For teams who want hands-on labs with Vivado and Questa, our full FPGA and RTL design courses build these templates up from scratch, and for production IP sign-off the engineers at Avecas design services run the same safe-FSM audits on customer silicon.

    Putting it together: a worked trade-off

    Suppose you are building a memory-controller command sequencer with 9 states. In binary you would use 4 flip-flops and a next-state decoder roughly 3 LUT levels deep — call it 2.1 ns of logic delay at a typical 7 nm speed grade. Re-synthesise as one-hot and you spend 9 flip-flops (still trivial against the tens of thousands on the device) but the decoder drops to a single LUT level, around 0.9 ns, letting you hit a 400 MHz target that the binary version missed. Add Moore outputs so the command bus is glitch-free, and a fsm_safe_state default so a cosmic-ray upset returns you to IDLE within one cycle. That is the whole decision tree in one block.

    FAQ

    Is Mealy always faster than Moore?

    Mealy responds one cycle earlier because the output reacts to inputs within the same cycle, but it adds a combinational input-to-output path that can become your critical timing arc. "Faster to react" is not the same as "easier to close timing."

    Why does Vivado default to one-hot for FPGAs?

    FPGA fabrics are flip-flop rich, so the extra registers one-hot needs are nearly free, while the shallow next-state logic shortens the critical path. On an ASIC, where every cell costs area, binary is usually preferred instead.

    What exactly makes an FSM "safe"?

    A safe FSM defines what happens in every illegal or unreachable encoding — typically a default branch plus a tool-generated hang detector — so a bit-flip from an SEU or glitch always recovers to a known reset state rather than locking up.

    Do I need a default branch if I cover every legal state?

    Yes. With one-hot you only enumerate N of 2^N encodings; without a default, the tool treats the rest as don’t-cares and may synthesise unrecoverable logic. Always code the default and test it with fault injection.

    Ready to build glitch-free, timing-clean FSMs in Vivado and Questa with guided labs? Join the CourseTron FPGA & RTL Design track at coursetron.com/courses and ship controllers that survive sign-off. Prefer instructor-led cohorts? See our training partner ChipXpert.

    Advertisement