December 2025 · Verilog

Asynchronous FIFO for Clock-Domain Crossing

A Verilog FIFO that moves data safely between two unrelated clocks, following Clifford Cummings' SNUG 2002 design: Gray-code pointers, two-flop synchronizers, and full and empty flags generated in the clock domain that needs them.

  • Verilog
  • Clock-domain crossing
  • Gray code
  • Vivado simulation

Modules

ModuleRole
fifomemDual-port RAM, 2ADDRSIZE words of DATAWIDTH bits (8-bit by default)
wptr_fullWrite pointer and full flag, in the write clock domain
rptr_emptyRead pointer and empty flag, in the read clock domain
sync_w2r, sync_r2wTwo-flop synchronizers carrying each Gray-code pointer into the other domain
bin2gray, gray2binPointer conversions between binary and Gray code
async_fifo_wrapperTop level, also packaged as a Vivado block design
tb_fifoTestbench

Design notes

Gray-code pointers
A binary counter can change several bits at once (0111 to 1000 changes four). Sampled mid-transition in the other clock domain, that can read as a completely wrong value. A Gray-code count changes exactly one bit per step, so a synchronized pointer is either the old value or the new one.
Two-flop synchronizers
The first flop may go metastable; the second gives it a full clock period to settle. That does not make failure impossible, but it pushes the mean time between failures far beyond the life of the product at normal clock rates.
Empty and full
Pointers carry one extra bit. Empty is when the read pointer equals the synchronized write pointer. Full is when the write pointer equals the synchronized read pointer with its two most significant bits inverted: same address, but the writer has wrapped once more.
Safe by design
Each flag is computed in the domain that acts on it, from a pointer that is a little stale. Stale pointers can only make the FIFO look fuller or emptier than it is, never cause an overflow or underflow.
Depth
A power of two, set by ADDRSIZE, so the Gray-code wrap-around works.

Simulation

Vivado simulator waveform of the FIFO testbench showing the write and read clocks, data buses and flags
Testbench waveform in the Vivado simulator. Select to enlarge.

Links