RTL Studio Open IDE

Wiki Finite state machines Three-process FSM

Three-process FSM

State register, next-state combo, and output decode as three processes.

The usual readable FSM is three processes: a flop that holds state_q, combo that computes state_d, and combo (or registered) outputs.

flowchart LR
  in[inputs] --> ns[next_state]
  sq[state_q] --> ns
  ns --> sd[state_d]
  sd --> ff[state_reg]
  clk[clk] --> ff
  ff --> sq
  sq --> out[outputs]

The three blocks

always_ff @(posedge clk or negedge rst_n) begin
  if (!rst_n) state_q <= ST_IDLE;
  else        state_q <= state_d;
end

always_comb begin
  state_d = state_q;
  unique case (state_q)
    ST_IDLE: if (start) state_d = ST_RUN;
    ST_RUN:  if (done_i) state_d = ST_DONE;
    default: state_d = ST_IDLE;
  endcase
end

always_comb begin
  busy = (state_q != ST_IDLE);
end

Wrong vs right

Wrong — next-state and outputs jammed into one clocked block with blocking assigns (hard to lint, easy to drop a reset path):

always_ff @(posedge clk) begin
  if (start) state = ST_RUN;
  busy = 1'b1;
end

Right — split register vs combo, always give default recovery.

A two-process style (flop + combined next/output) is fine if the team agrees; do not mix styles inside one module.

See also