ECParts Toolkit LogoECParts Toolkit

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 states

Variable 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.

LayerDesign checkFailure mode
Source counterRegister binary state and derive or register the corresponding Gray pointerCombinational decode glitches must not become a CDC input
SequenceVerify every legal successive word differs by one bit, including wrapA non-power-of-two truncated sequence may break adjacency
Bus routingBound inter-bit arrival skew against the source update intervalSuccessive one-bit transitions can overlap at the receiver
SynchronizationSynchronize each Gray pointer bit through the intended destination-clock stagesTwo-flop structure reduces but does not eliminate metastability risk
DecodeCompare or decode only the synchronized pointer in the destination domainMixing raw and synchronized bits defeats coherency
FlagsDerive full/empty conservatively from correctly synchronized pointersExtra latency changes when flags assert and clear
ResetCoordinate both domains and release reset using the selected device methodologyOne 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

TestExpected evidenceBoundary
Sequence sweepAll adjacent source Gray words have Hamming distance 1Include wrap and reset transitions
Clock ratio sweepFlags remain conservative across asynchronous phase relationshipsRTL simulation cannot prove metastability MTBF
Bus timingSkew constraint passes after routingCheck actual update interval and corners
Reset releasePointers and flags converge without false full/emptyBoth domains need documented release behavior
Encoder benchPosition errors and invalid jumps are boundedTest vibration, speed, and edge alignment
Data integrityNo lost or duplicated FIFO words under legal trafficExercise 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.