Draft preview. Lessons are being written and reviewed.

Digital Design / Module 6: Finite state machines

38. Debugging and safe FSMs

Handle stuck states and unused encodings.

Lecture coming soon

See it move

The idea

FSMs fail in a few recognisable ways. They hang in a state, take a wrong branch, or reach an encoding that should never occur. Knowing these patterns makes debugging far faster.

Finding a hang

  • Display the state by name in your waveform, not as a number.
  • Find the state it got stuck in.
  • List what could cause it to leave.
  • See which of those signals is missing. It's often a that the machine waits for and never receives, or a pulse that came while it was looking elsewhere.

Missed pulses are especially common. If a one-cycle done pulse arrives while the FSM is in a different state, it is lost for good, and the machine then waits forever. Fix this by holding the signal until it is acknowledged.

Illegal states

A 5-state binary FSM has 3 unused codes. It shouldn't reach them, but a bit upset, a timing failure or a bad reset could put it there. If nothing handles them, the machine can stay stuck until reset. Try the upset button in the animation above.

default: next = IDLE;  // recover from any illegal state

One warning: synthesis may treat unreachable states as and remove this logic. If you need real recovery, use your tool's safe-FSM option, and check the result. A safety-critical design would also raise an error, rather than quietly resume.

Assertions

Assertions catch errors at their origin, not later.

assert property (@(posedge clk) disable iff (!rst_n)
  state inside {IDLE, LOAD, RUN, DONE});

assert property (@(posedge clk) disable iff (!rst_n)
  (state == RUN) |-> ##[1:1000] (state == DONE));

The second one flags a hang automatically.

Common mistake

Treating a hang as a timing issue and slowing down the clock. Trace the logic first. Most hangs are a wrong assumption about when a signal arrives.

Key ideas

  • Show state names in waveforms.
  • Unused encodings need a recovery path.
  • Assertions catch illegal states early.

Your exercise

Fix a supplied FSM that hangs after an unusual input.

Find the bug

This code has one deliberate bug. Read the symptom, then click the line you think is wrong.

What goes wrong: A bit upset puts the state register at 110. The machine stops there and never leaves, until a reset.

Interview questions

coreWhat happens on an illegal state?

basicA 5-state FSM is encoded in binary and, separately, one-hot. How many illegal codes does each encoding have?

basicAn FSM in simulation stops making progress. What are your first debugging steps?

coreThis controller sometimes hangs in WAIT forever, but only with a fast peripheral. Why?

always @(posedge clk)
  if (rst) state <= IDLE;
  else case (state)
    IDLE: if (start) state <= REQ;
    REQ:  state <= WAIT;          // req goes out here
    WAIT: if (done) state <= IDLE; // done is a 1-cycle pulse
    default: state <= IDLE;
  endcase

coreThis 5-state counter FSM has no default branch. What happens if a bit flip puts it in state 110?

always @(posedge clk)
  if (rst) st <= 3'd0;
  else case (st)
    3'd0: st <= 3'd1;
    3'd1: st <= 3'd2;
    3'd2: st <= 3'd3;
    3'd3: st <= 3'd4;
    3'd4: st <= 3'd0;
  endcase

coreYou added a default branch that sends illegal states to IDLE. Is that guaranteed to survive synthesis?

coreWrite a plain Verilog-2005 check that reports an error if the FSM sits in WAIT for more than 20 clocks.

reg [5:0] wait_cnt;
always @(posedge clk)
  if (rst || state != WAIT) wait_cnt <= 0;
  else begin
    wait_cnt <= wait_cnt + 1;
    if (wait_cnt == 20)
      $display("ERROR %0t: stuck in WAIT", $time);
  end

advancedA colleague says an FSM hang went away when they halved the clock frequency, so it must be a timing problem. What do you say?

advancedFor a safety-critical controller, is it enough for an illegal state to quietly return to IDLE?

Practise these 9 questions with animations