28 / 37 · Concept
State machines: separating state, transitions and outputs
Build an FSM from a specification table and compare Moore/Mealy outputs, illegal states and request policies.
Lessons are free to read. Enroll to save your learning progress.
State summarizes only the history that matters
Define stored state when present inputs alone do not determine outputs. Instead of retaining all input history, distinguish only the past differences needed to determine future behavior.
Consider a controller for starting and completing work. IDLE waits for requests, BUSY processes work, and DONE indicates completion for one cycle.
| Current state | Condition | Next state | busy | done |
|---|---|---|---|---|
| IDLE | start=0 | IDLE | 0 | 0 |
| IDLE | start=1 | BUSY | 0 | 0 |
| BUSY | work_done=0 | BUSY | 1 | 0 |
| BUSY | work_done=1 | DONE | 1 | 0 |
| DONE | Always | IDLE | 0 | 1 |
busy and done are outputs of the current state. For example, after the edge that observes completion in BUSY, state becomes DONE and done becomes 1. These are Moore outputs.
Each column below records a rising edgeRising edge The instant at which the clock changes from 0 to 1. Distinguish it from a level, which refers to the entire interval during which CLK=1. Learn more. Inputs are pre-edge; states labeled “after” are post-update. Alignment shows sample order, not physical propagation delayPropagation delay The time from an input change until the output settles to the correct value. Logical equivalence and timing behavior are separate properties. Learn more. Starting in IDLE, the edge accepting work_done leads to DONE and done=1. DONE always leads to IDLE, regardless of start.
View waveform data
| Signal | Wave | Bus values |
|---|---|---|
| edge | 2345 | E0 → E1 → E2 → E3 |
| start | 10.1 | |
| work_done | 0.10 | |
| state after | 2.34 | BUSY → DONE → IDLE |
| busy after | 1.0. | |
| done after | 0.10 |
RTL separating transitions from storage
typedef enum logic [1:0] {IDLE, BUSY, DONE} state_t;
state_t state, next_state;
always_comb begin
next_state = state;
case (state)
IDLE: if (start) next_state = BUSY;
BUSY: if (work_done) next_state = DONE;
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
end
always_ff @(posedge clk)
if (rst) state <= IDLE;
else state <= next_state;
assign busy = (state == BUSY);
assign done = (state == DONE);This SystemVerilog example illustrates the control structure. The connected worker's work_done generation and input synchronization must be implemented separately.
Questions easily omitted from a specification
This circuit ignores start in BUSY and DONE. To accept a new request at completion, revise the transition table first. A Mealy output uses both state and current input and can respond quickly, but its combinational timing and glitches need review. Choosing binary versus one-hotOne-hot A representation with exactly one bit set to 1. A condition that also permits all zeros is called one-hot-or-zero. Learn more state encoding is independent of choosing Moore versus Mealy outputs.
Try it yourself
A one-cycle start=1 arrives in DONE. Does this FSM immediately start new work? What must change to allow consecutive jobs?
Read the explanation
No: the table specifies DONE→IDLE, so that request is not accepted. Change DONE to transition to BUSY on start, or design a protocol that retains requests. Verify done pulse width and request-acceptance timing against the revised specification.