Draft preview. Lessons are being written and reviewed.

Digital Design / Module 10: Clock domain crossing

57. Gray code pointers

Use one-bit-change encodings.

Lecture coming soon

See it move

The idea

In Gray code, consecutive values differ in exactly one bit. If you sample a Gray counter while it changes, that one bit reads as either old or new. So the sample is always either the old value or the new value, and never a false one. That's what makes multi-bit crossing possible for counters.

Converting

// Binary to Gray
assign gray = bin ^ (bin >> 1);

// Gray to binary: each bit is the XOR of all higher Gray bits
always_comb begin
  bin[N-1] = gray[N-1];
  for (int i = N-2; i >= 0; i--)
    bin[i] = bin[i+1] ^ gray[i];
end

The first is one XOR per bit. The second is a chain of XORs, so it is slower.

The sequence

ValueBinaryGray
3011010
4100110
7111100
0000000

From 3 to 4, binary flips all three bits, while Gray flips one. The wrap from 7 to 0 also flips just one, and this only works for wraps at a power of two.

The conditions

All of these must hold for a Gray crossing to be safe:

  • The value changes by at most one step per source clock.
  • The Gray value comes straight from a register, with no logic after it, because a combinational converter could .
  • The path across the bus is less than about one period of the destination clock. Modern constraints check this using set_max_delay.

Sampling a fast counter

If the source is much faster, the destination can miss some values and go from, for instance, 5 to 8. That's fine, because each sampled value was real. pointers rely on this: the other side's pointer is merely old, and "old" is always safe.

Common mistake

Applying Gray code to arbitrary data. It helps only for sequences that move in single steps. If a value can jump by two or more, then multiple bits can change, and you lose the guarantee. Try value 7 in the animation above, and note how many values binary can produce.

Key ideas

  • Binary to Gray: g = b xor (b >> 1).
  • A one-bit change gives either old or new value on capture, never a false one.
  • Applies only for sequences changing by one step at a time.

Lab: Clock crossing lab

Your exercise

Write binary-to-Gray and Gray-to-binary converters.

Find the bug

This code has one deliberate bug. Read the symptom, then click the line you think is wrong.

What goes wrong: Some consecutive values differ in two bits, so the pointer is unsafe to cross clock domains.

Interview questions

coreWhy does a Gray pointer cross safely?

basicConvert binary 1011 to Gray code, and convert the result back to binary.

basicA 4-bit counter steps from 7 to 8. If each bit is sampled independently while it changes, how many different values could the destination read in binary, and in Gray code?

coreWrite a Gray-to-binary converter for a 4-bit value in Verilog-2005 and say why it is slower than binary-to-Gray.

function [3:0] g2b;
  input [3:0] g;
  integer i;
  begin
    g2b[3] = g[3];
    for (i = 2; i >= 0; i = i - 1)
      g2b[i] = g2b[i+1] ^ g[i];
  end
endfunction

coreA 4-bit binary-to-Gray converter is written with a shift in the wrong direction. What goes wrong?

assign gray = bin ^ (bin << 1);

coreA counter that adds 2 every cycle is sent across a clock boundary in Gray code. Is it safe?

coreWhy must the Gray value that crosses come straight from a register, rather than from XOR gates after a binary register?

advancedA Gray counter runs at 300 MHz and is read through a synchronizer at 100 MHz. The destination sees 5 and then 8. Is that a bug?

advancedWhy do the bits of a Gray-coded bus need to arrive close together, and roughly how close?

Practise these 9 questions with animations