CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Sequential Logic

The Implicit State Machine

MediumVerilog / SystemVerilogBuild

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).
  • busy is 1 in all states except IDLE.
  • Priority in WAIT state: err has priority over ack.

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_out port 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, and done must be driven combinationally based on the current state.
  • Transitions from READ to WAIT, WRITE to DONE, and DONE to IDLE are unconditional.
  • If err and ack are asserted simultaneously in the WAIT state, the FSM must transition to ERROR.

Topics

FSMControl LogicRefactoring

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.

Sign in to solveSee what Pro unlocks

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.

Related problems

  • Basic D Flip FlopEasy
  • Debug: Missing Edge in Sensitivity ListMedium
  • Read After Write Hazard DetectionEasy
  • Parameterized Interface with ModportsHard
  • Struct Array PipelineHard
  • T Flip Flop from D Flip Flop TemplateEasy
  • Recursive Generate Reduction TreeHard
  • Four Stage Shift RegisterEasy

Browse all problems · Learning tracks