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 Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
    • Controller and Datapath
    • Moore vs Mealy
    • State Encoding
      • Encodings Compared
      • Area and Speed Trade-off
      • Illegal States and Recovery
      • Choosing an Encoding
    • Multi-Cycle Sequencers
    • UART Transmitter
    • Memory Controller
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹State Encoding
  1. Topics
  2. RTL Design
  3. FSM & Control
  4. State Encoding
  5. Encodings Compared

Part 4 · FSM & Control · Intermediate

Encodings Compared

Binary, Gray, one-hot and Johnson codes for eight states, with the property each one guarantees.

On this page

    Why this matters

    An FSM whose state changes three bits at once can be read as a state it never entered. A receiver that samples it asynchronously sees 111 for a moment while the machine goes from S3 to S4, and a decode fires that should not.

    After this lesson you can: write the binary, Gray, one-hot and Johnson codes for eight states and say which ones change one bit per step and which do not.

    Four ways to number eight states

    Eight states need three binary bits, eight one-hot bits, or four Johnson bits. The table lists every code.

    State

    Binary

    Gray

    One-hot

    Johnson (4-bit)

    S0

    000

    000

    00000001

    0000

    S1

    001

    001

    00000010

    0001

    S2

    010

    011

    00000100

    0011

    S3

    011

    010

    00001000

    0111

    S4

    100

    110

    00010000

    1111

    S5

    101

    111

    00100000

    1110

    S6

    110

    101

    01000000

    1100

    S7

    111

    100

    10000000

    1000

    Properties that matter

    Property

    Binary

    Gray

    One-hot

    Johnson

    Bits changing per step

    1 to 3 (e.g. 011→100 flips all three)

    Always 1

    Always 2 (one falls, one rises)

    Always 1

    Decode one state

    n-input AND

    n-input AND

    Read one bit

    2-input AND

    Flops for N states

    ⌈log₂ N⌉

    ⌈log₂ N⌉

    N

    N/2

    Can express any N?

    Yes

    Any N as an open sequence; a closed one-bit ring must have even length and its wrap must be checked

    Yes

    Only even N

    The transition counts describe the eight-state rings shown above, including wraparound. Binary is the smallest code, one-hot is the easiest to decode, and these Gray and Johnson rings change one bit per step. Truncating a Gray sequence can break its wrap: 00 → 01 → 11 → 00 changes one bit on the first two transitions but two bits on the last. An odd-length closed ring with exactly one changing bit per transition is impossible: each bit flip toggles the parity of the number of ones, so an odd number of flips cannot return to the starting code. Branches, aborts and resets need their own transition audit.

    One bit changing per step matters when the state is sampled asynchronously or drives glitch-sensitive outputs. With several bits changing, a receiver can briefly see a code that is neither the old nor the new state.

    Each slot is half a nanosecond, and the skews are illustrative numbers. The two bus lanes show the code the receiver sees, in hex, and the decode lanes are a combinational test for the code 111 (state S7 in binary).

    • Binary, slots 0 and 1: the code is 3 (011), state S3.

    • Binary, slot 2: bit 2 has risen but bits 1 and 0 have not yet fallen, so the receiver sees 7 (111). The decode pulses high for one slot although the FSM never visits S7.

    • Binary, slots 3 and 4: the code passes through 5 (101) and settles at 4 (100), state S4.

    • Gray: S3 to S4 is 2 (010) to 6 (110). Only one bit changes, so there is no intermediate code and the decode stays low.

    Gray limits adjacent ring steps to one changing bit. This FSM's abort can jump from S4 (110) to S0 (000), changing two bits; S5 (111) to S0 changes three. Reset can make the same jumps. Do not use this raw Gray FSM state for CDC. Transfer a stable status snapshot with a handshake. Gray FIFO pointers use a constrained sequence plus synchronization and physical timing constraints; see the CDC section.

    Common mistakes

    Common pitfall

    Johnson counters have 2N states in N bits, but the other 2ᴺ − 2N codes are illegal. A single glitch can drop the machine into an illegal loop that never reaches the intended sequence. Add a self-correcting feedback or a recovery condition.

    Check yourself In binary encoding, why can a 3→4 transition cause a momentary wrong output even though both end states are fine?

    Three bits change at once and not at exactly the same instant. For a short time the code can be any mix (for example 111 or 000), which a combinational decode may interpret as a different state, producing a glitch.

    Check yourself Does the three-state sequence 00 → 01 → 11 form a one-bit Gray ring when it wraps to 00?

    No. The wrap 11 → 00 flips two bits. Changing the codes or adding bits cannot make an odd-length closed ring one-bit throughout: each one-bit transition toggles ones parity, and returning to the original code requires an even number of toggles.

    Testbench

    The listing checks the eight-state code sequences and their wrap transitions, then checks the two-bit wrap of a truncated three-state Gray sequence.

    code_check.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
    module code_check;
      // Generate the codes from the state number and verify the properties in the table above.
      function automatic logic [2:0] to_gray(logic [2:0] b);   return b ^ (b >> 1);               endfunction
      function automatic logic [7:0] to_onehot(logic [2:0] b); return 8'b1 << b;                  endfunction
      function automatic logic [3:0] to_johnson(logic [2:0] b);
        // 4-bit Johnson counter value after b steps: shift in the inverted MSB
        logic [3:0] j = 4'b0000;
        for (int i = 0; i < b; i++) j = {j[2:0], ~j[3]};
        return j;
      endfunction
    
      int errors = 0, nx, flips_g, flips_j, flips_h, ones_h, flips_bin;
      logic [2:0] g0, g1, dg;
      logic [3:0] j0, j1, dj;
      logic [7:0] h0, h1, dh;
      initial begin
        for (int i = 0; i < 8; i++) begin
          nx = (i + 1) % 8;                                          // next state (wraps 7 -> 0)
          g0 = to_gray(i);    g1 = to_gray(nx);
          j0 = to_johnson(i); j1 = to_johnson(nx);
          h0 = to_onehot(i);  h1 = to_onehot(nx);
          dg = g0 ^ g1;  flips_g = $countones(dg);   if (flips_g != 1) errors++;   // Gray: exactly one bit changes
          dj = j0 ^ j1;  flips_j = $countones(dj);   if (flips_j != 1) errors++;   // Johnson: exactly one bit changes
          dh = h0 ^ h1;  flips_h = $countones(dh);   if (flips_h != 2) errors++;   // one-hot: one falls, one rises
          ones_h  = $countones(h0);        if (ones_h  != 1) errors++;   // exactly one bit set
        end
        // Truncating to three states preserves the open sequence, but not a one-bit wrap.
        for (int i = 0; i < 3; i++) begin
          nx = (i + 1) % 3;
          g0 = to_gray(3'(i)); g1 = to_gray(3'(nx));
          dg = g0 ^ g1;
          flips_g = $countones(dg);
          if (flips_g != ((i == 2) ? 2 : 1)) errors++;
        end
        // binary is not one bit at a time: 3 -> 4 flips all three bits
        g0 = 3'd3 ^ 3'd4;  flips_bin = $countones(g0);
        if (flips_bin != 3) errors++;
        // the table: spot-check a few entries
        if (to_gray(3'd2)  !== 3'b011)     errors++;
        if (to_gray(3'd4)  !== 3'b110)     errors++;
        if (to_johnson(3'd3) !== 4'b0111)  errors++;
        if (to_johnson(3'd7) !== 4'b1000)  errors++;
        if (to_onehot(3'd5)  !== 8'b00100000) errors++;
        if (errors != 0) $fatal(1, "FAIL: encoding property errors=%0d", errors);
        $display("PASS: eight-state Gray/Johnson rings change one bit per step; three-state Gray wrap flips two; one-hot and binary checks pass");
        $finish;
      end
    endmodule

    Remember

    • Binary is the smallest code, one-hot is the easiest to decode, and the Gray and Johnson rings change one bit per step.

    • Aborts, resets and truncated rings break the one-bit rule, so audit every transition.

    • Do not use a raw Gray FSM state for CDC. Transfer a stable snapshot with a handshake.

    Rule of thumb: one bit per step only helps if every transition, including abort and reset, obeys it.

    Keep going

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

    • Practice: Gray encoding for low power and CDC safety

    • Interview: run a mock interview on this topic

    Related topics

    • Area and speed trade-off

    Previous

    99 / 350

    Next: Area and Speed Trade-off

    Up next

    Up nextArea and Speed Trade-off

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Illegal States and Recovery
    • Choosing an Encoding
    bin3754is_7_bingray26is_7_gray
    The step from S3 to S4 with each state bit arriving at its own time: binary passes through 111 and a decode of that code pulses, while Gray changes one bit and the decode stays low