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

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
  • Sequential, FSM and Memory19
    • Flops, Resets and Enables
    • FSM Synthesis
      • Coding Styles
      • State Encoding
      • Unreachable States
      • Output Registering
      • Yosys FSM Passes
    • Memory and Macro Inference
    • Retiming and Pipelining
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
Loading lesson

‹FSM Synthesis
  1. Topics
  2. Logic Synthesis
  3. Sequential, FSM and Memory
  4. FSM Synthesis
  5. Coding Styles

Part 4 · Sequential, FSM and Memory · Intermediate

Coding Styles

One-, two- and three-process FSM styles and what each one infers.

On this page

    Three ways to write one machine

    A one-process FSM keeps state and next-state selection in a single clocked block. A two-process FSM splits them into a combinational next-state block and a clocked state update.

    A three-process FSM adds a third clocked block that registers the outputs. All three describe the same machine when written carefully; they differ in how the state register shows up to the reader and the tool.

    Style

    Blocks

    State register

    One-process

    One clocked block

    Inside the case: compact but next-state and update share code.

    Two-process

    One combinational plus one clocked block

    A single state <= next line, which keeps the state register isolated.

    Three-process

    Two-process plus a clocked output block

    Same state register; outputs move one cycle later.

    What each style infers

    The state register infers one flop per state bit in every style. The combinational block infers only gates, provided every branch assigns next and a default covers the rest.

    A default that returns to the reset state doubles as the recovery arc of the next lessons. Without either a next = state preamble or a default, an uncovered code holds its value and infers a latch in the combinational block.

    The latch trap

    The classic bug is a two-process combinational block with an incomplete case, no default, and no preamble assignment. The missing codes keep the old next value, so synthesis builds a latch.

    Common pitfall

    Assign next = state; first, then override it per branch, and keep a default. The first line alone removes the latch even if a branch is later forgotten.

    Check yourself A two-process FSM covers three of four binary codes, with no default and no next = state preamble. What does synthesis build?

    A latch on the next-state signal. The missing code must hold its old value, which is storage, not gates.

    Check yourself Why does the two-process form help FSM recognition passes?

    The state register is one isolated update line, which keeps sequential state visibly apart from combinational next-state logic. Recognition still has to fire, as the Yosys lesson shows.

    Testbench

    The same three-state machine written with one process and with two processes, plus a testbench that steps both through identical inputs.

    fsm_1p.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
    35
    36
    37
    38
    39
    module fsm_1p (
      input logic clk, input logic go, input logic fin,
      output logic [1:0] st, output logic busy
    );
      localparam logic [1:0] IDLE = 2'b00, WORK = 2'b01, DONE = 2'b10;
      logic [1:0] state;
      initial state = IDLE;
      always @(posedge clk) begin
        case (state)
          IDLE: if (go) state <= WORK;
          WORK: if (fin) state <= DONE;
          DONE: state <= IDLE;
          default: state <= IDLE;
        endcase
      end
      assign st = state;
      assign busy = (state == WORK);
    endmodule
    
    module fsm_2p (
      input logic clk, input logic go, input logic fin,
      output logic [1:0] st, output logic busy
    );
      localparam logic [1:0] IDLE = 2'b00, WORK = 2'b01, DONE = 2'b10;
      logic [1:0] state, next;
      initial state = IDLE;
      always @(posedge clk) state <= next;
      always_comb begin
        next = state;
        case (state)
          IDLE: if (go) next = WORK;
          WORK: if (fin) next = DONE;
          DONE: next = IDLE;
          default: next = IDLE;
        endcase
      end
      assign st = state;
      assign busy = (state == WORK);
    endmodule
    

    Interview

    Likely probes: sketch two-process structure from memory, and say where the latch comes from.

    • Combinational block assigns next with a default; clocked block holds state.

    • A missing branch with neither a preamble nor a default holds state and grows a latch.

    • Both forms agree cycle by cycle, as the testbench above proves.

    Related topics

    • Up: FSM Synthesis

    • Next: State encoding

    • Flops, Resets and Enables

    Previous

    57 / 139

    Next: State Encoding

    Up next

    Up nextState Encoding

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Unreachable States
    • Output Registering
    • Yosys FSM Passes