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 Foundations57
  • Combinational Design58
  • Sequential Design61
  • FSM & Control66
    • Controller and Datapath
    • Moore vs Mealy
    • State Encoding
      • Encodings Compared
      • Why encoding matters
      • Area and Speed Trade-off
      • Encoding options
      • Binary encoding
      • Illegal States and Recovery
      • Choosing an Encoding
      • One-hot encoding
      • Gray encoding
      • Johnson encoding
      • Key takeaways
      • Worked Examples and Waveforms
    • Multi-Cycle Sequencers
    • UART Transmitter
    • Memory Controller
  • Timing & Clocking64
  • Reset & CDC58
  • Memory & Buses94
  • Advanced RTL60
  • Senior & Interview175
  • Glossary and Notation
Loading lesson

‹State Encoding
  1. Topics
  2. RTL Design
  3. FSM & Control
  4. State Encoding
  5. Area and Speed Trade-off

Part 4 · FSM & Control · Intermediate

Area and Speed Trade-off

One 8-state FSM in three encodings, bounded functional checks and a synthesis comparison recipe.

On this page

    Why this matters

    One-hot is often called the fast encoding. For a small eight-state ring, a generic synthesis run built it as 21 cells against 14 for binary, so the claim needs a measurement on your target, not a rule.

    After this lesson you can: compare binary, Gray and one-hot builds of the same FSM, say what generic cell counts do and do not show, and name when one-hot may help timing.

    The experiment

    One ring sequencer advances on step and returns to S0 on abort. Three outputs report busy (not in S0), last (S7) and odd (S1, S3, S5 or S7).

    Three coded versions run under one testbench with random stimulus. Outputs must match on every cycle, and the full code sits under Testbench below.

    What a synthesizer builds

    The counts below come from the recipe further down (synth -top <module> -nofsm; stat, generic gate mapping, FSM recoding disabled). Flip-flops are the $_DFFE_* cells; logic gates are every other cell.

    Encoding

    Flip-flops

    Logic gates

    Total cells

    Binary

    3

    11

    14

    Gray

    3

    12

    15

    One-hot

    8

    13

    21

    These are generic cell counts, not silicon area or delay. In this table one-hot uses the most flops and, for this tiny ring, slightly more logic cells too: its simple output decode does not pay back the per-bit next-state logic. Cell sizes, fan-in, fanout and wiring can reverse the physical ranking. No speed winner follows from these counts.

    Reproduce the generic comparison

    Use only the three design modules from the listing below as enc.sv (exclude tb_enc). Run each top from a fresh Yosys invocation. Record the source revision/hash, yosys -V, complete command and log. The built-in generic gate mapping has no target Liberty library or device; synth already invokes ABC, so do not count a second mapping pass as the same experiment.

    Diagram
    yosys -V
    yosys -p 'read_verilog -sv enc.sv; synth -top seq_bin -nofsm; stat' > seq_bin.log
    yosys -p 'read_verilog -sv enc.sv; synth -top seq_gray -nofsm; stat' > seq_gray.log
    yosys -p 'read_verilog -sv enc.sv; synth -top seq_onehot -nofsm; stat' > seq_onehot.log

    For a speed decision, repeat with the actual FPGA part/flow or ASIC Liberty/corner and physical flow. Hold clock period, I/O delays, output loads, reset constraints and optimization settings constant; record encoding reports, flop/LUT or area totals, worst path endpoints, delay/slack and routing stage. Compare state-to-state and state-to-output paths, not just gate totals. Your counts can differ with another Yosys version. See the primary Yosys synth command reference.

    Check yourself One-hot spends 5 extra flip-flops, and in this tiny ring the generic mapping does not even save logic (13 gates against 11 for binary). Why can one-hot still help timing on a larger FSM?

    Each state bit's next-state logic depends only on its own predecessors and guards, and a single-state output is one bit. On a larger FSM with sparse transitions, that can keep the logic in front of each flop shallow, while a binary code needs a full decode of every state bit. Whether it actually wins must be measured on the target flow.

    When one-hot may help timing

    • Sparse incoming transitions can give shallow per-bit next-state logic. Many predecessors or complex guards add AND/OR depth and routing load; depth is not constant for arbitrary FSMs.

    • Single-state output decode can be just a bit: last is s[7]. Combined outputs such as odd still require an OR network, and even a wire has fanout and routing cost.

    • Platform resources matter: try one-hot where the target has available registers and binary decode is the reported bottleneck. Compare mapped resource use and timing before choosing; FPGA/ASIC labels alone do not select a winner.

    Common pitfall

    Neither FSM size nor branching alone guarantees a speed advantage. Keep functional equivalence checks and encoding reports alongside timing results; an encoding change that improves one path can worsen another or increase clock-tree and routing cost.

    Testbench

    The listing audits hold, advance, wrap, abort and reset transitions from every state, then checks identical outputs over 20000 random cycles. Only ring advances guarantee one Gray bit changes; aborts explicitly demonstrate multiple-bit changes.

    seq_bin.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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    module seq_bin (
      input  logic clk, rst_n, step, abort,
      output logic busy, last, odd
    );
      typedef enum logic [2:0] {S0, S1, S2, S3, S4, S5, S6, S7} state_t;
      state_t state, next;
    
      always_comb begin
        next = state;
        if (abort)     next = S0;
        else if (step) unique case (state)
          S0: next = S1;  S1: next = S2;  S2: next = S3;  S3: next = S4;
          S4: next = S5;  S5: next = S6;  S6: next = S7;  S7: next = S0;
        endcase
      end
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) state <= S0; else state <= next;
    
      assign busy = (state != S0);
      assign last = (state == S7);
      assign odd  = (state == S1) || (state == S3) || (state == S5) || (state == S7);
    endmodule
    
    module seq_onehot (
      input  logic clk, rst_n, step, abort,
      output logic busy, last, odd
    );
      logic [7:0] s;                                   // s[i] = 1 means "in state Si"
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n)      s <= 8'b0000_0001;
        else if (abort)  s <= 8'b0000_0001;
        else if (step)   s <= {s[6:0], s[7]};          // rotate: S0 -> S1 -> ... -> S7 -> S0
    
      assign busy = !s[0];
      assign last = s[7];
      assign odd  = s[1] | s[3] | s[5] | s[7];
    endmodule
    
    module seq_gray (
      input  logic clk, rst_n, step, abort,
      output logic busy, last, odd
    );
      // 3-bit Gray sequence: consecutive states differ in exactly one bit
      localparam logic [2:0] G0 = 3'b000, G1 = 3'b001, G2 = 3'b011, G3 = 3'b010,
                             G4 = 3'b110, G5 = 3'b111, G6 = 3'b101, G7 = 3'b100;
      logic [2:0] s;
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n)      s <= G0;
        else if (abort)  s <= G0;
        else if (step) begin
          case (s)
            G0: s <= G1;  G1: s <= G2;  G2: s <= G3;  G3: s <= G4;
            G4: s <= G5;  G5: s <= G6;  G6: s <= G7;  default: s <= G0;
          endcase
        end
    
      assign busy = (s != G0);
      assign last = (s == G7);
      assign odd  = (s == G1) || (s == G3) || (s == G5) || (s == G7);
    endmodule
    

    Remember

    • Generic cell counts are not silicon area or delay, and they name no speed winner.

    • One-hot can give shallow next-state logic when each state has few incoming transitions, and a single-state output is just one bit.

    • Compare state-to-state and state-to-output paths on the real flow, with the same constraints for each encoding.

    Rule of thumb: pick the encoding from the implemented timing report, not from the FSM size.

    How this was checked

    Cell counts (binary 3 flip-flops and 11 logic gates, Gray 3 and 12, one-hot 8 and 13) come from Yosys 0.69, run 2026-10-16 with synth -top <module> -nofsm; stat, generic gate mapping and FSM recoding disabled. They contain no target timing evidence.

    Keep going

    • Practice: One-hot versus binary encoding: trade-offs and pitfalls

    • Code lab: Build a one-hot control FSM

    • Interview: run a mock interview on this topic

    Related topics

    • Illegal states and recovery

    Previous

    202 / 694

    Next: Encoding options

    Up next

    Up nextEncoding options

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Encodings Compared
    • Binary encoding
    • Illegal States and Recovery