VHDL · Chapter 9.8 · Finite State Machines
Safe FSMs and Illegal-State Recovery
An FSM has a finite set of legal states, but its state register can hold more bit patterns than that, the illegal states such as unused binary codes or any non-one-hot pattern in a one-hot machine. In normal operation the FSM never enters them, yet a single-event upset, a glitch, a metastable capture, or a reset problem can drive it into one, and a naive machine may then sit there forever. A safe FSM guarantees recovery, so from any state, including illegal ones, it returns to a known legal state. This lesson shows how to add that recovery for every unlisted state, why one-hot encodings have especially many illegal patterns, what the safe-FSM synthesis attribute does, and how to keep the synthesiser from optimising the recovery logic away as unreachable.
Foundation14 min readVHDLFSMSafe StateIllegal StateRecoveryReliability
1. Engineering intuition — plan for the state you should never be in
You design an FSM to move among its legal states, but the hardware can end up elsewhere: a cosmic-ray upset flips a state bit, a glitch or metastable capture lands the register on an unused code, or a reset issue leaves it undefined. If your transition logic only describes the legal states, the machine has no defined move from an illegal one — so it can freeze. A safe FSM anticipates this: it makes every possible state, legal or not, lead back to a known state (usually idle/reset). It is cheap insurance, and for anything that must not hang — safety, long-running, or radiation-exposed systems — it is mandatory.
2. Formal explanation — recovery for every state
library ieee; use ieee.std_logic_1164.all;
type state_t is (IDLE, RUN, PAUSE, DONE); -- 4 legal states
signal state, next_state : state_t;
nlogic : process (all)
begin
next_state <= state; -- default: stay
case state is
when IDLE => if go = '1' then next_state <= RUN; end if;
when RUN => if fin = '1' then next_state <= DONE; end if;
when PAUSE => next_state <= RUN;
when DONE => next_state <= IDLE;
when others => next_state <= IDLE; -- SAFE RECOVERY: any illegal state → IDLE
end case;
end process;The when others => next_state <= IDLE; is the recovery: it defines a transition from any state the case did
not explicitly list — which, for an enum that the tool may encode with spare codes, includes the illegal
patterns. From any illegal state the machine returns to IDLE within a clock. Without it, an illegal state has no
defined exit and the FSM can hang.
3. Production RTL — safe one-hot and the synthesis attribute
library ieee; use ieee.std_logic_1164.all;
-- (A) Tell the tool to build a SAFE FSM (recover from illegal states) via an attribute.
attribute fsm_safe_state : string;
attribute fsm_safe_state of state : signal is "reset_state"; -- recover illegal → reset state
-- (vendor attribute names vary; "safe_fsm"/"fsm_safe_state" select a safe implementation)
-- (B) For one-hot, an explicit check: a legal one-hot has exactly one bit set.
-- If 'state_oh' is ever NOT one-hot (zero or multiple bits), force recovery.
-- if (number of set bits in state_oh) /= 1 then next_state <= IDLE; end if;What hardware does this become? With the safe-FSM attribute (or explicit when others), the synthesiser
adds logic so any out-of-range or non-one-hot pattern transitions to the reset/idle state. For one-hot machines
this matters most — a one-hot register has 2^N patterns but only N legal ones, so almost every pattern is
illegal, and an upset is likely to produce an illegal (multi-hot or zero-hot) pattern that needs recovery.
4. Hardware interpretation — every state leads home
5. Simulation interpretation — upset, then recover
An upset drives the FSM to an illegal state; safe recovery returns it to IDLE
8 cycles6. Debugging example — the recovery the tool deleted
Expected: the FSM recovers from illegal states. Observed: in the gate-level netlist the recovery is
gone — the when others branch was optimised away — so an injected upset hangs the FSM. Root cause: the
synthesiser proved the illegal states are unreachable in normal operation and removed the recovery logic as
dead code; it does not know you want it for upset tolerance. Fix: use the vendor safe-FSM attribute
(which tells the tool to keep/insert recovery) rather than relying on a when others it may delete; for
critical FSMs, verify the recovery survives to the netlist (and consider explicit one-hot checks). Engineering
takeaway: a when others recovery can be optimised away because it looks unreachable — enable the safe-FSM
attribute to make the tool preserve illegal-state recovery, and confirm it in the netlist.
-- The 'when others' may be removed as unreachable; the safe-FSM attribute tells the tool to keep recovery.
attribute fsm_safe_state of state : signal is "reset_state";
-- ... and still write the explicit recovery for simulation/intent:
when others => next_state <= IDLE;7. Common mistakes & what to watch for
- No illegal-state recovery. An upset can hang the FSM; add
when others => <known state>(and the safe-FSM attribute). - Relying only on
when others. The tool may delete it as unreachable; use the safe-FSM attribute to preserve recovery, and verify in the netlist. - Ignoring one-hot's many illegal states. One-hot registers have far more illegal than legal patterns; recovery (or a one-hot check) is especially important.
- Recovering to a busy/unsafe state. Recover to idle/reset (a benign known state), not into the middle of an operation.
- Assuming reset alone is enough. Reset fixes power-up, not a mid-operation upset; recovery handles illegal states that arise during running.
8. Engineering insight & continuity
A safe FSM treats illegal states as inevitable, not impossible: from any state, legal or not, it returns to a
known one, guaranteeing the machine can never hang. The mechanism is a when others recovery plus the safe-FSM
synthesis attribute that keeps the tool from optimising it away — essential for one-hot encodings and for any
system that must not freeze. This is the reliability capstone of FSM design. The module's final lesson pulls
together everything that can go wrong — the Common FSM Bugs — into a single catalog with fixes, before the
curriculum moves to Packages and Reuse.