Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
    • Digital Logic for RTL Engineers
    • Number Systems for RTL Engineers
    • Verilog Fundamentals
    • Verilog Operators and Types
    • SystemVerilog for RTL
      • Why SystemVerilog Improves RTL Quality
      • The `logic` Type and Assignment Model
      • always_ff and always_comb
      • typedef, enum and Robust FSM Coding
      • Interfaces and Modports
      • SystemVerilog RTL Cheat Sheet
    • Simulation and Testbenches
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹SystemVerilog for RTL
  1. Topics
  2. RTL Design
  3. RTL Foundations
  4. SystemVerilog for RTL
  5. typedef, enum and Robust FSM Coding

Part 1 · Foundations · Beginner

typedef, enum and Robust FSM Coding

Typed states, safe defaults, and a state machine template whose RTL recovers from illegal encodings.

On this page

    Why this matters

    A 3-state machine in a 2-bit register has an unused encoding, 2'b11. With a default branch in RTL it returns to IDLE in one clock, but synthesis may drop that path unless the flow is told to keep it.

    After this lesson you can: write an FSM with a typed enum, the two-block template and an illegal-state recovery branch, and test it.

    Named, typed states

    An FSM state is a label, not a number. A typedef enum names the states and gives them a checked type, so arbitrary constants can no longer reach the state register.

    design.sv
    1
    2
    3
    4
    5
    typedef enum logic [1:0] {
      IDLE   = 2'd0,
      ACTIVE = 2'd1,
      FINISH = 2'd2
    } state_e;

    The robust two-block template

    State storage sits in a clocked block, while next-state and output logic stay combinational. Every output gets a default, and default covers illegal states.

    State diagram with IDLE, ACTIVE and FINISH and the transitions between them.
    The handshake FSM. Every state has an outgoing path, and in RTL simulation an illegal encoding goes back to IDLE.

    Checklist for a robust FSM

    1. Typed enum for the state; no raw numbers.

    2. next = state; and output defaults at the top of always_comb.

    3. A default branch that sends illegal states to a safe state in RTL, checked later on the gate netlist.

    4. A reset to a known state, plus tests that visit every transition.

    5. Moore outputs that depend on state alone, unless Mealy behavior is deliberate.

    A 3-state machine in a 2-bit register leaves one encoding unused (2'b11). In RTL simulation, forcing 2'b11 makes the next-state logic take default, and the machine is back in IDLE on the next clock edge. The testbench below does exactly that.

    Warning

    That is RTL behaviour, not a hardware guarantee. Synthesis may re-encode the state (one-hot or gray) or treat the unreachable encoding as don't-care and drop the default path, unless the flow is told to keep the recovery logic. Whether a real upset recovers is a question for the hardware and the flow: confirm it with a post-synthesis fault check, forcing the illegal state in the gate-level netlist simulation.

    Check yourself Why give next a default value (next = state;) before the case?

    It guarantees next is assigned on every path, which prevents latch inference and makes “stay in this state” the default behavior, so each branch only has to describe transitions.

    Testbench

    The template plus a testbench that walks IDLE to ACTIVE to FINISH and back, checks ACTIVE hold, abort alone and simultaneous abort/last_beat priority, then forces the illegal encoding 2'b11 and checks RTL recovery on the next edge. The state_e type sits outside the module so the testbench can cast to it.

    handshake_fsm.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    typedef enum logic [1:0] {IDLE, ACTIVE, FINISH} state_e;   // shared, so the testbench can name the type
    
    module handshake_fsm (
      input  logic clk, rst_n,
      input  logic start, last_beat, abort,
      output logic busy, done
    );
      state_e state, next;
    
      // 1) state register
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) state <= IDLE;
        else        state <= next;
    
      // 2) next-state and outputs, with defaults
      always_comb begin
        next = state;                 // default: stay
        busy = 1'b0;
        done = 1'b0;
        unique case (state)
          IDLE:   if (start)          next = ACTIVE;
          ACTIVE: begin
                    busy = 1'b1;
                    if (abort)        next = IDLE;
                    else if (last_beat) next = FINISH;
                  end
          FINISH: begin
                    done = 1'b1;
                    next = IDLE;
                  end
          default: next = IDLE;       // illegal encoding: recover to a safe state
        endcase
      end
    endmodule
    

    Remember

    • A typedef enum names the states and stops arbitrary constants reaching the state register.

    • Put next = state; and the output defaults at the top of always_comb.

    • The default branch recovers in RTL. Synthesis may re-encode or drop it, so check the gate netlist.

    Rule of thumb: reset to a known state and send every illegal state somewhere safe.

    How this was checked

    The testbench is directed RTL evidence of recovery from the illegal encoding 2'b11 in simulation. It is not proof of fault recovery in the synthesised design.

    Keep going

    • Practice: FSM design with enums and unique/priority case

    • Practice: FSM safe-state recovery from illegal states

    • Interview: run a mock interview on this topic

    Related topics

    • FSM and control — the full topic

    Previous

    28 / 350

    Next: Interfaces and Modports

    Up next

    Up nextInterfaces and Modports

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Why SystemVerilog Improves RTL Quality
    • The `logic` Type and Assignment Model
    • SystemVerilog RTL Cheat Sheet