Digital Logic Guide
Gray Code Across Clock Domains: Encoder Sampling, FIFO Pointers, and Verification
Gray coding reduces how many bits are intended to change at once. Reliable crossing still depends on registered source values, physical bus timing, synchronizers, flag logic, and reset behavior.
17 min · Advanced · Updated October 16, 2026
Separate Code Conversion from CDC Safety
The Gray Code Converter checks binary-reflected code words and conversions. It does not model flip-flop metastability, interconnect skew, or asynchronous FIFO control. A legal Gray sequence is one input to a safe crossing, not the crossing itself. For basic binary representation and counter sizing, see Digital Timing, Binary Arithmetic, Counters, and Code Conversion.
Formula reference
Binary-reflected Gray conversion
g = b XOR (b >> 1)b[n-1] = g[n-1]b[i] = b[i+1] XOR g[i] for i descendingHammingDistance(g[k], g[k+1]) = 1 for legal adjacent statesVariable definitions
- b is a fixed-width unsigned binary counter value
- g is its binary-reflected Gray representation
- Hamming distance counts differing bit positions
- For an n-bit power-of-two cyclic sequence, the last-to-first transition is also one bit
For a 4-bit pointer, binary 7 = 0111 converts to Gray 0100; binary 8 = 1000 converts to Gray 1100. Only the most significant Gray bit changes. Decoding 1100 by cumulative XOR returns 1000. This is a code property, not a bound on physical arrival time.
Why Bus Skew Matters
Suppose source pointer increments on two successive source clocks. The first increment changes Gray bit A, and the next changes bit B. If routing bit A is much slower than B, the receiver can observe the second transition before the first arrives. The receiver then sees a word not equal to the current or previous source pointer, despite each source transition being one bit at the registers.
Constrain and verify the Gray bus so inter-bit arrival skew cannot overlap successive updates under the actual source clock and routing corners. The exact max-delay or bus-skew constraint depends on the FPGA/ASIC timing tool and source/destination topology. A common fast-to-slow crossing requires a bound tied to the fast source update period, but a single numeric rule is not universal. Review the placed-and-routed timing report rather than assuming RTL adjacency survives physical implementation.
Build a Pointer Crossing
An asynchronous FIFO keeps write and read state in separate clock domains. It commonly uses binary pointers locally for address arithmetic and Gray-coded pointers for domain crossing. Register the source pointer, synchronize the Gray bits into the opposite clock domain using the intended synchronizer structure, then compare or decode only the synchronized result. An extra wrap state distinguishes full from empty when address bits coincide. Full/empty flags are necessarily delayed by the pointer synchronizer latency and must be designed conservatively.
The Counter & Modulus Calculator can establish width and wrap count for a counter. It does not synthesize an asynchronous FIFO, prove a Gray sequence for an arbitrary truncated modulus, or verify full/empty flags. A binary-reflected cycle of 2^n states has one-bit adjacency including wrap; a non-power-of-two truncation needs its own transition proof.
| Layer | Design check | Failure mode |
|---|---|---|
| Source counter | Register binary state and derive or register the corresponding Gray pointer | Combinational decode glitches must not become a CDC input |
| Sequence | Verify every legal successive word differs by one bit, including wrap | A non-power-of-two truncated sequence may break adjacency |
| Bus routing | Bound inter-bit arrival skew against the source update interval | Successive one-bit transitions can overlap at the receiver |
| Synchronization | Synchronize each Gray pointer bit through the intended destination-clock stages | Two-flop structure reduces but does not eliminate metastability risk |
| Decode | Compare or decode only the synchronized pointer in the destination domain | Mixing raw and synchronized bits defeats coherency |
| Flags | Derive full/empty conservatively from correctly synchronized pointers | Extra latency changes when flags assert and clear |
| Reset | Coordinate both domains and release reset using the selected device methodology | One domain can observe a stale or illegal pointer during release |
What Synchronizers Do and Do Not Do
A two-stage destination-clock synchronizer gives a metastable first stage additional time to resolve before downstream logic samples the second. Reliability depends on the device, clock rate, input transition rate, and available resolution time. It is probabilistic, not absolute. Keep the stages adjacent per device guidance and prevent logic between them unless the architecture requires it and is analyzed.
Synchronizing every bit of an arbitrary binary word independently does not make the word coherent. Gray pointers are a special case because the source sequence limits intended changes and the consumer understands pointer semantics. For a general multi-bit payload use a handshake, toggle protocol, asynchronous FIFO, or another proven CDC architecture. A single-bit pulse also needs attention: a destination clock can miss a pulse shorter than its capture opportunity even when a synchronizer is present.
Encoder Sampling Is a Different Physical Problem
Optical or mechanical encoders may use Gray tracks so adjacent ideal positions differ by one track. Real edges are not perfectly aligned; contacts bounce, optical thresholds move, and the sensor can straddle a boundary. Filter electrical noise, choose a sampling rate appropriate to motion, validate allowed neighboring transitions, and define how to handle illegal jumps or missing samples. A displayed Gray word that differs by multiple bits from the previous sample might reflect missed positions as well as noise; a one-bit rule is not a complete speed model.
A K-map also uses Gray ordering, but for adjacency during Boolean minimization, not for clock crossing. Do not infer CDC safety from K-map arrangement. For physical timing and setup/hold budget definitions, the Digital Timing Calculator is a first-pass synchronous tool; CDC paths and synchronizer MTBF need separate analysis.
Verification Plan
| Test | Expected evidence | Boundary |
|---|---|---|
| Sequence sweep | All adjacent source Gray words have Hamming distance 1 | Include wrap and reset transitions |
| Clock ratio sweep | Flags remain conservative across asynchronous phase relationships | RTL simulation cannot prove metastability MTBF |
| Bus timing | Skew constraint passes after routing | Check actual update interval and corners |
| Reset release | Pointers and flags converge without false full/empty | Both domains need documented release behavior |
| Encoder bench | Position errors and invalid jumps are bounded | Test vibration, speed, and edge alignment |
| Data integrity | No lost or duplicated FIFO words under legal traffic | Exercise almost-full, almost-empty, and wrap states |
Use CDC lint, static timing, formal properties where practical, and hardware testing together. Verify that intended synchronizer cells are recognized by implementation tools, that the Gray bus constraints were not disabled by broad false-path declarations, and that full/empty behavior remains safe if synchronized pointers lag.
Common Mistakes
- Claiming Gray code eliminates metastability.
- Crossing a combinationally glitching Gray encoder without a source register.
- Leaving Gray bus bits unconstrained after routing.
- Using a truncated counter without checking wrap adjacency.
- Decoding raw asynchronous bits before synchronization.
- Treating independent bit synchronizers as a general multi-bit protocol.
- Assuming two flip-flops capture every short pulse.
- Ignoring synchronizer latency when deriving full/empty flags.
- Treating mechanical bounce as a legal adjacent encoder transition.
- Calling a clean RTL waveform proof of CDC reliability.
Support reference
FAQ
Why use Gray code across clock domains?
Adjacent ideal code words change one bit, reducing ambiguous multi-bit sampling during one pointer transition. This does not remove metastability or replace a CDC protocol.
How do I convert binary to Gray code?
For a fixed-width binary value b, reflected Gray code is g = b XOR (b >> 1). Preserve the intended bit width when generating a sequence.
How do I convert Gray code back to binary?
The most significant binary bit equals the most significant Gray bit. Each following binary bit is the previous binary bit XOR the current Gray bit.
Does Gray code guarantee only one bit changes at the receiver?
No. Routing skew can overlap successive source transitions. Constrain and verify the complete Gray bus relative to its update interval.
Does a two-flop synchronizer eliminate metastability?
No. It reduces the probability of metastability propagating beyond the synchronizer when used under appropriate device and clock conditions; the probability is not zero.
Can I synchronize ordinary binary data one bit at a time?
Not for an arbitrary changing multi-bit word. Independent bit synchronizers can capture values from different updates; use a handshake, FIFO, stable-data protocol, or another suitable CDC architecture.
Why does an asynchronous FIFO use an extra pointer bit?
A wrap or phase bit distinguishes an empty condition from a full condition when the address portions of write and read pointers match. The exact full comparison depends on the chosen pointer encoding and architecture.
Can Gray code fix a bouncing mechanical encoder?
No. A physical encoder can bounce, misalign, or pass through ambiguous optical or contact states. Debounce, sensing geometry, rate limits, and sequence validation are still needed.
How should a Gray CDC path be verified?
Check encoded sequence adjacency, synchronizer structure, Gray bus timing constraints, reset release, clock-ratio corners, full/empty behavior, and implementation reports. Simulate legal transitions and fault cases without treating RTL simulation as metastability proof.
Summary
Verify the Gray sequence first, then verify the physical crossing. Registered source words, bus-skew constraints, destination synchronizers, conservative flags, and reset behavior are all required for a trustworthy asynchronous pointer design.
