
Synthesizable HDL Models of Sequential Circuits
How to write clocked sequential logic in HDL so it synthesizes to flip-flops correctly.
Description
Synthesizable sequential RTL uses an edge-triggered clocked block with non-blocking assignments and a defined reset. Separate the next-state/output combinational logic from the state register. Following these idioms guarantees the synthesizer infers real flip-flops and a correct FSM.
- Clocked block: always @(posedge clk) (optionally or negedge rst).
- Use non-blocking assignment (<=) for state.
- Define a reset (sync or async) for the start state.
- Keep next-state/output logic in a separate combinational block.
- Don't mix blocking and non-blocking in the same block.
- State register: seq block updates current ← next.
- Next-state logic: comb block (always @(*)).
- Output logic: Moore (state) or Mealy (state+input).
- Use an enum/parameter for state names.
- Two- or three-process style is the safe idiom.
At a glance
What
RTL idioms that synthesize to correct clocked flip-flop logic.
Why
Wrong idioms infer latches, races, or simulation/synthesis mismatch.
How
always @(posedge clk) with non-blocking <=, plus a reset; split comb vs seq.
Where
Every sequential block in real designs.
When
Whenever modeling registers, counters, or FSMs for synthesis.
Think of it like…
Like a relay race with a strict baton-pass rule: state only changes at the whistle (clock edge), and everyone uses the same handoff (non-blocking) so no one trips.
Sequential RTL rules
- Clocked block: always @(posedge clk) (optionally or negedge rst).
- Use non-blocking assignment (<=) for state.
- Define a reset (sync or async) for the start state.
- Keep next-state/output logic in a separate combinational block.
- Don't mix blocking and non-blocking in the same block.
FSM coding style
- State register: seq block updates current ← next.
- Next-state logic: comb block (always @(*)).
- Output logic: Moore (state) or Mealy (state+input).
- Use an enum/parameter for state names.
- Two- or three-process style is the safe idiom.
Comb vs seq blocks
| Block | Trigger | Assign |
|---|---|---|
| Sequential | posedge clk | non-blocking <= |
| Combinational | @(*) | blocking = |
Flip-flop the RTL infers
▶ live simulatorSet inputs, then Run for a live clock (or Step one edge) and watch Q on the waveform.
| D | Q⁺ | note |
|---|---|---|
| 0 | 0 | reset |
| 1 | 1 | set |
Characteristic equation: Q⁺ = D
HDL — Verilog · VHDL · SystemVerilog
module fsm(input clk, rst, x, output reg y);
reg [1:0] state, next;
localparam S0=0, S1=2'd1, S2=2'd2;
always @(posedge clk) if (rst) state<=S0; else state<=next;
always @(*) begin
next = state; y = 0;
case (state)
S0: begin y=0; if (x) next=S1; end
S1: begin y=0; if (x) next=S2; end
S2: begin y=1; if (!x) next=S0; end
endcase
end
endmoduleTwo-process Moore FSM template.
Real-world applications
The 5 Whys
- 1
Why non-blocking for state? Models parallel flip-flop updates.
- 2
Why a reset? Defines a known start state.
- 3
Why split comb/seq? Clear, race-free, synthesizable FSMs.
- 4
Why enum states? Readable and tool-friendly.
- 5
Root cause: matching RTL idioms to flip-flop semantics yields correct hardware.
Cheat sheet
Working principle
- always @(posedge clk) with non-blocking <=, plus a reset; split comb vs seq.
- RTL idioms that synthesize to correct clocked flip-flop logic.
Formulas & Boolean expressions
- Use non-blocking assignment (<=) for state.
Key facts
- Clocked block: always @(posedge clk) (optionally or negedge rst).
- State register: seq block updates current ← next.
Why it exists
- Root cause: matching RTL idioms to flip-flop semantics yields correct hardware.