Gray code is a binary encoding system where adjacent values differ by only one bit, eliminating the multi-bit transition errors that plague standard binary encoding. From rotary encoders and ADCs to clock domain crossing and finite state machine design, Gray code ensures error-free transitions in applications where timing uncertainties and glitches could cause catastrophic failures.

Learning Objectives

  • Understand how Gray code differs from binary code in single-bit-change property
  • Convert between binary and Gray code using XOR-based algorithms
  • Analyze why Gray code prevents glitches in asynchronous systems and state machines
  • Apply Gray code to clock domain crossing, ADCs, and rotary encoder applications

Reading time: 12 minutes | Difficulty: Intermediate | Prerequisites: Binary System, Finite State Machines

What is Gray Code?

Gray code, also known as Gray binary code or reflected binary code, is a binary numeral system where adjacent values differ by only one bit. In other words, Gray code is a binary code where each successive value differs from the previous value by only one bit.

For example, the binary representation of decimal numbers 1 and 2 is 0001 and 0010 respectively. Note that two LSB bits (bit#0 and bit#1) have to change for the transition from 1 to 2. In Gray code, 1 and 2 are represented by 0001 and 0011 respectively, but the same transition now requires only a change of one bit (bit#1 from LSB).

Binary vs. Gray Code Transition Comparison

This code is used in many applications, including digital communications, error correction, and electronic devices. One of the main advantages of Gray code is that it eliminates the possibility of errors that could occur when transitioning between two consecutive binary values.

Gray Code Table (0-15)

Here's the Gray code for binary values from 0 to 15:

DecimalBinaryGrayBits Changed from Previous
000000000-
1000100011 bit (bit 0)
2001000111 bit (bit 1)
3001100101 bit (bit 0)
4010001101 bit (bit 2)
5010101111 bit (bit 0)
6011001011 bit (bit 1)
7011101001 bit (bit 0)
8100011001 bit (bit 3)
9100111011 bit (bit 0)
10101011111 bit (bit 1)
11101111101 bit (bit 0)
12110010101 bit (bit 2)
13110110111 bit (bit 0)
14111010011 bit (bit 1)
15111110001 bit (bit 0)

Key observation: Every transition from one Gray code value to the next changes exactly one bit. This single-bit-change property is what makes Gray code valuable for error-sensitive applications.

Common Usage

1. Digital-to-Analog and Analog-to-Digital Converters (DACs/ADCs)

Gray code is used in digital-to-analog converters (DACs) and analog-to-digital converters (ADCs) to reduce the likelihood of errors in the conversion process. In these applications, the Gray code is used to represent the output voltage or the input signal in a way that minimizes the error due to small variations in the voltage or signal level.

For example, in a binary-encoded ADC, if the analog input is at the transition point between 7 (0111) and 8 (1000), timing uncertainty could cause the ADC to briefly read any value from 0 to 15 because all four bits change simultaneously. With Gray code (0100 → 1100), only one bit changes, limiting errors to adjacent values.

2. Limiting Transition Errors

Because adjacent values differ in only one bit, a bit that is misread or arrives late during a transition produces an error of at most one step. Gray code does not detect or correct errors by itself; error-detecting and error-correcting codes, such as parity or Hamming codes, are separate techniques.

3. Clock Domain Crossing (CDC)

Gray code is also used to represent a counter value, such as a FIFO pointer, that is transferred between two clock domains. This works because such a value changes by one step at a time. The value is first encoded into Gray code in the source clock domain, and then decoded from Gray code in the destination clock domain.

The advantage of using Gray code in clock domain crossing (CDC) is that it minimizes the probability of errors caused by metastability, which can occur when data is sampled at an uncertain time between two clock edges. With Gray code, even if the data is sampled at the wrong time, the resulting error is limited to a single bit flip, which can be detected and corrected more easily than if multiple bits had changed.

FIFO Pointer Synchronization: Asynchronous FIFOs use Gray-coded read and write pointers when crossing clock domains. Since pointers increment by one each cycle, Gray encoding ensures that even if the receiving clock domain samples the pointer during a transition, it will read either the old value or the new value (differing by only one bit), never a corrupted intermediate value with multiple bits in transition.

Binary to Gray Code Conversion

Converting a binary number to its equivalent Gray code representation involves a simple algorithm that can be applied to each bit in the binary number. Here's the algorithm:

  1. Copy the MSB: Start with the most significant bit (MSB) of the binary number and copy it to the corresponding bit in the Gray code.
  2. XOR adjacent bits: For each subsequent bit of Gray code, set it to 0 if values in the corresponding bit position in binary and the previous bit position are the same, else 1. (This is an XOR operation.)

Step-by-Step Example

Here's an example to illustrate the algorithm:

Binary number: 101011
  1. Copy the most significant bit (MSB) to the corresponding bit in the Gray code.
  2. For bit#4 in Gray: bit#5 and bit#4 in binary are different (1 and 0), so result should be 1.
  3. For bit#3 in Gray: bit#4 and bit#3 in binary are different (0 and 1), so result should be 1.
  4. For bit#2 in Gray: bit#3 and bit#2 in binary are different (1 and 0), so result should be 1.
  5. For bit#1 in Gray: bit#2 and bit#1 in binary are different (0 and 1), so result should be 1.
  6. For bit#0 in Gray: bit#1 and bit#0 in binary are the same (1 and 1), so result should be 0.

Result: Binary 101011 = Gray 111110

Mathematical Formula

The conversion can be expressed mathematically as:

Gray[n-1] = Binary[n-1]  (MSB, just copy)
Gray[i] = Binary[i+1] ⊕ Binary[i]  (for i = n-2 down to 0)

Where ⊕ represents XOR operation

Common Beginner Mistakes

Mistake #1: Assuming Gray Code Can Be Used for Arithmetic

Wrong: Trying to add, subtract, or perform arithmetic operations directly on Gray-coded numbers.

Right: Convert Gray code to binary first, perform arithmetic, then convert back to Gray code if needed.

Why: Gray code is not a weighted positional system like binary. The bits don't have place values (1, 2, 4, 8, etc.), so arithmetic operations don't work. Gray code is for encoding/decoding only.

Mistake #2: Forgetting the Reflection Property

Wrong: Treating Gray code generation as an arbitrary assignment of codes.

Right: Understand that Gray code has a reflection property—the second half mirrors the first half with the MSB flipped.

Why: This reflection property is how Gray code is constructed and why it's called "reflected binary code." Understanding this helps in generating larger Gray code sequences.

Mistake #3: Confusing Binary-to-Gray with Gray-to-Binary Conversion

Wrong: Using the same algorithm for both directions of conversion.

Right: Binary→Gray uses XOR of adjacent bits. Gray→Binary uses cumulative XOR starting from MSB.

Why: The conversions are different algorithms. Binary-to-Gray: G[i] = B[i+1] ⊕ B[i]. Gray-to-Binary: B[i] = G[i] ⊕ B[i+1] (cumulative XOR from MSB down).

Mistake #4: Using Gray Code Where Standard Binary Is Sufficient

Wrong: Using Gray code for all digital counters and state machines.

Right: Use Gray code only when single-bit transitions are critical (CDC, asynchronous sampling, rotary encoders). Use binary for arithmetic and most synchronous systems.

Why: Gray code adds complexity (encoding/decoding) and prevents direct arithmetic. Only use it where the single-bit-change property provides a tangible benefit.

Disadvantages

Although Gray code has several advantages, it also has some disadvantages. Here are some of the main disadvantages of Gray code:

  • Increased complexity: Gray code requires additional hardware or software to encode and decode the data. This can increase the complexity and cost of the system.
  • Decoding delay: Encoding binary to Gray code takes one XOR gate per bit, but decoding Gray code back to binary is a running XOR from the MSB, which adds delay as the number of bits grows unless it is built as a parallel XOR tree.
  • Non-standard representation: Gray code is not a standard binary representation, which can make it difficult to interface with other systems or devices that use traditional binary representation.
  • Limited arithmetic operations: Gray code cannot be used directly for arithmetic operations such as addition or multiplication, which can limit its usefulness in some applications.

Real-World Applications

Rotary Encoders and Position Sensors: Mechanical rotary encoders use Gray code to encode shaft position. As the encoder wheel rotates, optical or magnetic sensors read the Gray-coded pattern. Because only one bit changes per increment, even if sensors read the pattern during a transition (when the wheel is between positions), the error is limited to ±1 position. With binary encoding, a transition from 7 (0111) to 8 (1000) could be misread as any value from 0 to 15 during the brief moment when bits are changing.

FSM State Encoding: Finite state machines can use Gray-coded state assignments to minimize glitches during state transitions. In asynchronous or asynchronous-reset FSMs, using Gray code ensures that if a state transition is captured at the wrong time, the FSM will only see adjacent states, not wildly incorrect states caused by multiple bits changing simultaneously.

Quick Check

Question: Convert binary 1101 to Gray code step by step.

Answer: Gray code = 1011

Step-by-step conversion:

  1. Start with binary: 1101
  2. Gray[3] (MSB): Copy Binary[3] = 1
  3. Gray[2]: Binary[3] ⊕ Binary[2] = 1 ⊕ 1 = 0
  4. Gray[1]: Binary[2] ⊕ Binary[1] = 1 ⊕ 0 = 1
  5. Gray[0] (LSB): Binary[1] ⊕ Binary[0] = 0 ⊕ 1 = 1

Result: 1011

Verification:

DecimalBinaryGray
1211001010
1311011011
1411101001

Notice that from Gray 1010 (decimal 12) to Gray 1011 (decimal 13), only bit 0 changed—the single-bit-change property holds! ✓

Summary

  • Gray code is a binary encoding where adjacent values differ by exactly one bit, eliminating multi-bit transition errors.
  • Binary-to-Gray conversion uses XOR of adjacent bits: G[i] = B[i+1] ⊕ B[i], with the MSB copied directly.
  • Gray code is essential for clock domain crossing (CDC), preventing metastability errors in asynchronous FIFO pointers.
  • Rotary encoders and position sensors use Gray code to limit read errors to ±1 position during transitions.
  • ADCs and DACs use Gray code to minimize conversion errors at transition points between analog levels.
  • Gray code cannot be used for arithmetic—it must be converted to binary first for addition, subtraction, or comparison.
  • Use Gray code only when single-bit transitions are critical, not as a general-purpose binary replacement.
Did you find what you were looking for?

Quiz

No quiz questions available for this article.