The Implicit State Machine
Legacy RTL codebases often accumulate sprawling webs of boolean flags to track control flow. A module might start with an is_active flag, gain an is_waiting flag, and eventually collapse under the weight of mutually exclusive flip-flops. Refactoring these implicit state machines into explicit, encoded Finite State Machines (FSMs) is essential for maintainability and timing closure.
The target module manages a memory transaction sequence. It rests in an idle state until a start signal is received. It then asserts a read enable for one cycle, waits for an acknowledgment, asserts a write enable for one cycle, signals completion for one cycle, and returns to idle. If an error occurs during the wait phase, it traps in an error state until the start signal is deasserted.
The original design used six individual flags (flag_idle, flag_read, flag_wait, flag_write, flag_done, flag_error). The new specification requires a single 3-bit state register to handle the exact same cycle timing.
- Clock edge:
posedge clk - Reset type: Asynchronous, active-low (
negedge rst_n) - On reset, the module enters the IDLE state and all control outputs (
read_en,write_en,done,busy) are 0. - State transitions occur on
posedge clk. - Outputs are combinational based purely on the current state (Moore machine).
busyis 1 in all states except IDLE.- Priority in WAIT state:
errhas priority overack.
Cycle 1: rst_n=0 → state_out=0, busy=0, read_en=0, write_en=0, done=0 Cycle 2: rst_n=1, start=1 → state_out=1, busy=1, read_en=1, write_en=0, done=0 Cycle 3: start=0, ack=0, err=0 → state_out=2, busy=1, read_en=0, write_en=0, done=0 Cycle 4: ack=1 → state_out=3, busy=1, read_en=0, write_en=1, done=0 Cycle 5: ack=0 → state_out=4, busy=1, read_en=0, write_en=0, done=1 Cycle 6: none → state_out=0, busy=0, read_en=0, write_en=0, done=0
flowchart LR
RESET(( )) -->|reset| IDLE
IDLE((IDLE)) -->|start=1| READ
IDLE -->|start=0| IDLE
READ((READ)) -->|unconditional| WAIT
WAIT((WAIT)) -->|err=1| ERROR
WAIT -->|err=0, ack=1| WRITE
WAIT -->|err=0, ack=0| WAIT
WRITE((WRITE)) -->|unconditional| DONE
DONE((DONE)) -->|unconditional| IDLE
ERROR((ERROR)) -->|start=0| IDLE
ERROR -->|start=1| ERROR{ "signal": [
{ "name": "clk", "wave": "P....." },
{ "name": "rst_n", "wave": "01...." },
{ "name": "start", "wave": "010..." },
{ "name": "ack", "wave": "00010." },
{ "name": "err", "wave": "0....." },
{ "name": "state_out", "wave": "======", "data": ["0", "1", "2", "3", "4", "0"] },
{ "name": "busy", "wave": "01...0" },
{ "name": "read_en", "wave": "010..." },
{ "name": "write_en", "wave": "0..10." },
{ "name": "done", "wave": "0...10" }
], "head": { "text": "Normal transaction sequence without errors." } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset | | start | input | 1 | Initiates a transaction from IDLE | | ack | input | 1 | Acknowledges the read, allows transition to WRITE | | err | input | 1 | Flags an error during the WAIT state | | busy | output | 1 | High in all states except IDLE | | read_en | output | 1 | High only in the READ state | | write_en | output | 1 | High only in the WRITE state | | done | output | 1 | High only in the DONE state | | state_out | output | 3 | Current FSM state |
Constraints
- The
state_outport must strictly follow this 3-bit encoding: IDLE (3'b000), READ (3'b001), WAIT (3'b010), WRITE (3'b011), DONE (3'b100), ERROR (3'b101). - Outputs
busy,read_en,write_en, anddonemust be driven combinationally based on the current state. - Transitions from READ to WAIT, WRITE to DONE, and DONE to IDLE are unconditional.
- If
errandackare asserted simultaneously in the WAIT state, the FSM must transition to ERROR.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.