VHDL · Chapter 9.1 · Finite State Machines
FSM Fundamentals
Almost every controller is a finite state machine: a design that is always in one of a finite set of named states, moves between them based on its inputs, and drives its outputs from where it currently is. An FSM is built from three cooperating parts, a clocked state register that resets to a known start, next-state logic that computes where to go from the current state and inputs, and output logic that produces the outputs. This module opener establishes that structure, introduces states as an enumerated type, and previews the Moore versus Mealy output distinction and the standard coding styles. It frames the FSM as the organising pattern that ties together all the clocked state and reset you have learned so far.
Foundation16 min readVHDLFSMState MachineMooreMealyController
1. Engineering intuition — a controller that is always somewhere
A finite state machine formalises a simple idea: the design is always in exactly one of a handful of named situations — idle, waiting, transferring, done — and what it does next depends on which situation it is in and what its inputs say. That is how humans describe controllers ("when idle, if start arrives, begin transferring; when transferring, if the last byte goes, finish"), and an FSM turns that description directly into hardware. The power is that arbitrarily complex sequential behaviour reduces to a finite list of states and the transitions between them — easy to specify, draw, review, and verify.
2. Formal explanation — the three parts of an FSM
library ieee; use ieee.std_logic_1164.all;
-- States as an ENUMERATED type (lesson 2.7) — named, type-safe, tool-encoded.
type state_t is (IDLE, RUN, DONE);
signal state, next_state : state_t;
-- (1) STATE REGISTER: clocked, reset to a known start (Module 8).
state_reg : process (clk, rst_n)
begin
if rst_n = '0' then state <= IDLE;
elsif rising_edge(clk) then state <= next_state;
end if;
end process;
-- (2) NEXT-STATE LOGIC: combinational; where to go from (state, inputs).
next_logic : process (all)
begin
next_state <= state; -- default: stay (latch-free)
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 DONE => next_state <= IDLE;
end case;
end process;
-- (3) OUTPUT LOGIC: combinational; outputs from the state (Moore) here.
busy <= '1' when state = RUN else '0';
done <= '1' when state = DONE else '0';An FSM has three cooperating parts: a state register (clocked, reset), next-state logic (combinational
case on the current state and inputs, defaulting to "stay" to avoid latches), and output logic
(combinational). States are an enumerated type so they are named and the tool chooses the encoding (lesson
9.3). This three-block view is the foundation for every coding style and machine type in the module.
3. Production RTL — a complete small FSM
library ieee; use ieee.std_logic_1164.all;
-- A simple request/ack handshake controller.
type st_t is (IDLE, REQ, WAIT_ACK, DONE);
signal st, st_n : st_t;
reg : process (clk, rst_n)
begin
if rst_n = '0' then st <= IDLE;
elsif rising_edge(clk) then st <= st_n;
end if;
end process;
nxt : process (all)
begin
st_n <= st; -- default: hold
case st is
when IDLE => if start = '1' then st_n <= REQ; end if;
when REQ => st_n <= WAIT_ACK;
when WAIT_ACK => if ack = '1' then st_n <= DONE; end if;
when DONE => st_n <= IDLE;
end case;
end process;
req <= '1' when st = REQ or st = WAIT_ACK else '0'; -- Moore outputs
busy <= '0' when st = IDLE else '1';What hardware does this become? A state register (two flip-flops for four states, or more with one-hot),
combinational next-state logic (a case decode), and combinational output logic. It asserts req while
requesting/waiting and de-asserts in idle — a clean handshake controller. This state-register + next-state +
output structure is exactly the same as the generic FSM above, just with the states of this protocol.
4. Hardware interpretation — register, next-state, output
5. Simulation interpretation — stepping through states
The handshake FSM stepping through its states on the clock
8 cycles6. Debugging example — the FSM stuck or starting wrong
Expected: a controller that advances correctly and starts in idle. Observed: it never leaves a state,
or powers up in a wrong/illegal state, or an output latches. Root cause: stuck usually means a transition
condition that never becomes true (or a missing transition); a wrong start means the state register was not
reset to a known state; a latched output means the next-state or output logic left a signal unassigned on some
path. Fix: reset the state register to a defined start (Module 8), default next_state <= state and every
output at the top of the combinational logic (Module 6), and check each state has a reachable exit. Engineering
takeaway: most FSM bugs are a missing reset, a missing default (latch), or a missing/unreachable transition —
the three-block structure makes each easy to locate.
-- Reset to a known state; default next_state to 'stay' so every path is covered (latch-free).
if rst_n = '0' then state <= IDLE; elsif rising_edge(clk) then state <= next_state; end if;
-- next_state logic: next_state <= state; case state is ... end case; -- default = hold7. Common mistakes & what to watch for
- Not resetting the state register. The FSM can power up in an illegal state; reset it to a defined start.
- Missing the default in next-state/output logic. Default
next_state <= stateand every output to avoid latches (Module 6). - Unreachable or dead-end states. Ensure every state has a reachable entry and a way out.
- Encoding the state by hand as bits. Use an enumerated type and let the tool encode (lesson 9.3); manual bit patterns are error-prone.
- Confusing Moore and Mealy outputs. Decide whether an output depends only on the state (Moore) or also on inputs (Mealy) — the next lesson covers the difference and its timing.
8. Engineering insight & continuity
The FSM is where everything in the foundation comes together: enumerated states (Module 2), combinational next-state and output logic (Module 6), a clocked, reset state register (Modules 7–8), all organised into the controller pattern. Its three-block structure — register, next-state, output — is the mental model for the whole module and for real controllers in industry. With the fundamentals set, the next lessons make the choices precise: Moore vs Mealy (where outputs come from and the timing difference), State Encoding (binary, one-hot, gray and their trade-offs), and the one-, two-, and three-process coding styles, before output logic, safe states, and the common bugs that complete a robust FSM methodology.