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

  • How to Use This Course
  • Reading Path
  • CDC/RDC Glossary
  • CDC/RDC Metrics Reference
  • CDC/RDC Interview Prep
  • CDC/RDC Signoff Cheatsheet
  • Clock Domains and Failure Modes8
  • Metastability and Synchronizers16
  • CDC Protocols and Handshakes16
  • Reconvergence and Gray Coding16
    • Gray Code Crossing
      • The One-Bit-Change Rule
      • Gray Counters
      • Where Gray Fails
      • Non-Power-of-Two Depths
    • Reconvergence Analysis
    • Multi-bit Crossing Strategies
    • Reconvergence Debug
  • Reset Domain Crossing16
  • Architecture and Design Rules16
  • CDC Signoff Methodology24
  • RDC Signoff16
  • Debug and Case Studies11
  • CDC and RDC Interview Prep30
  • Capstone: Sign Off a Multi-clock Peripheral4
Loading lesson

‹Gray Code Crossing
  1. Topics
  2. CDC & RDC
  3. Reconvergence and Gray Coding
  4. Gray Code Crossing
  5. Gray Counters

Part 4 · Reconvergence and Gray Coding · All levels

Gray Counters

Binary-to-Gray conversion, registering the Gray value in the source domain, and an exhaustive self-check.

On this page

    A Gray counter is a binary counter with its Gray image registered beside it. Both registers update together in the source domain, and only the Gray register crosses. Registering matters: a Gray value computed combinationally from the counter can glitch while the binary bits settle, putting several changing bits on the crossing in the very cycle the rule must hold.

    The pattern

    Binary register feeding XOR conversion into a Gray register that crosses to the destination.
    Binary and Gray registers update together in the source domain; only the Gray register output crosses, one synchroniser per bit.

    The conversion g = b ^ (b >> 1) applies to the next binary value, so the two registers always agree. The destination decodes Gray back to binary with a running XOR from the top bit down, or compares Gray values directly as FIFO full and empty logic does (see async FIFO design).

    Complete example with exhaustive self-check

    A 4-bit Gray counter and a testbench that steps through all 16 values and checks that every step, including the wrap from 15 back to 0, flips exactly one bit, and that every value is visited.

    gray_counter.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    `timescale 1ns/1ps
    
    // 4-bit Gray counter for crossings: the binary count advances, and the Gray
    // image of the NEXT value is registered alongside it. The crossing taps the
    // registered Gray output, never a combinational conversion, so no glitch can
    // reach the synchroniser.
    module gray_counter (
      input  logic clk, rst_n, en,
      output logic [3:0] gray
    );
      logic [3:0] bin, bin_next, gray_next;
      assign bin_next = bin + (en ? 4'd1 : 4'd0);
      assign gray_next = (bin_next >> 1) ^ bin_next;
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin bin <= '0; gray <= '0; end
        else begin bin <= bin_next; gray <= gray_next; end
    endmodule
    

    What the checking and the review look for

    • The Gray register is a flop in the source domain, fed by the conversion, with no logic between it and the synchroniser.

    • The adjacency proof covers the wrap step, not just the counting steps.

    • The enable cannot skip: when en is high the binary count advances by exactly one.

    Common pitfall

    Computing Gray combinationally at the crossing (assign gray = cnt ^ (cnt >> 1) into the synchroniser) reintroduces multi-bit glitches as the counter bits settle at slightly different times. The simulation symptom is occasional invalid jumps that vanish when probed. Register first, then cross.

    Check yourself Why does the testbench check the wrap step from 15 to 0 separately rather than trusting the counting steps?

    The counting steps prove single-bit change along the sequence, but only the wrap step proves the sequence is a cycle. A sequence that is Gray-ordered but does not wrap cleanly tears exactly when the pointer rolls over, which is the hardest failure to catch in system test.

    Related topics

    • The one-bit-change rule

    • Next: where Gray fails

    Previous

    48 / 179

    Next: Where Gray Fails

    Up next

    Up nextWhere Gray Fails

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Non-Power-of-Two Depths