A Dual-Clock Asynchronous FIFO implemented in Verilog HDL for safe data transfer between two independent clock domains. This design follows industry-standard Clock Domain Crossing (CDC) practices and is suitable for FPGA-based digital systems and academic projects.
An asynchronous FIFO enables reliable communication between subsystems running on different clock frequencies without data corruption.
This implementation uses:
- Dual-Port RAM for storage
- Binary counters for memory addressing
- Gray-coded pointers for safe clock domain crossing
- 2-Flip-Flop synchronizers to reduce metastability risk
- FULL / EMPTY flags for flow control
- ALMOST_FULL / ALMOST_EMPTY flags for early warning
This architecture is widely used in SoCs, communication systems, DSP pipelines, and high-speed digital designs.
| Block | Description |
|---|---|
| Write Pointer Handler | Maintains write pointer in binary and Gray formats |
| Read Pointer Handler | Maintains read pointer in binary and Gray formats |
| Dual-Port RAM | Stores FIFO data using binary addresses |
| 2-FF Synchronizers | Safely transfer Gray pointers across clock domains |
| Full Flag Logic | Detects FIFO full condition in write domain |
| Empty Flag Logic | Detects FIFO empty condition in read domain |
wr_enwritesdininto FIFO memory- Binary write pointer increments
- Binary pointer converted to Gray code
- Gray pointer synchronized into read clock domain
fullandalmost_fullflags generated
rd_enreads FIFO data intodout- Binary read pointer increments
- Binary pointer converted to Gray code
- Gray pointer synchronized into write clock domain
emptyandalmost_emptyflags generated
| Signal Type | CDC Method Used |
|---|---|
| Pointer transitions | Gray coding (only 1 bit changes at a time) |
| Cross-domain pointer transfer | 2-Flip-Flop synchronizers |
| Full/Empty detection | Gray pointer comparison |
This FIFO is functionally correct and CDC-safe for FPGA and educational use, but has the following limitations:
-
ALMOST flags are not fully CDC-clean
almost_fullandalmost_emptyconvert synchronized Gray pointers back to binary- This can introduce small metastability risk in strict ASIC flows
-
No ECC or parity protection
- Memory corruption detection is not included
-
Depth must be power of 2
- Required for proper Gray code pointer wrapping
-
Not formally verified
- Verified through simulation only
-
No backpressure beyond flags
- System using FIFO must obey
fullandemptysignals
- System using FIFO must obey
A self-checking testbench is used to verify correctness.
Verification features:
- Independent write and read clocks
- Burst write and read sequences
- Scoreboard-based data integrity checking
- Pointer tracking for output validation
- Waveform inspection using GTKWave
✔ No data loss ✔ No duplication ✔ Data order maintained ✔ Correct flag behavior observed
| Tool | Purpose |
|---|---|
| Icarus Verilog | Simulation |
| GTKWave | Waveform visualization |
| VS Code / Any Editor | RTL development |
| GitHub | Version control and hosting |
async-fifo/
│
├── rtl/
│ └── async_fifo.v
│
├── tb/
│ └── async_fifo_tb.v
│
├── waves/
│ └── async_fifo.vcd
│
├── docs/
│ ├── fifo_block_diagram.png
│ └── waveform_screenshot.png
│
└── README.md
iverilog -o fifo_sim rtl/async_fifo.v tb/async_fifo_tb.v
vvp fifo_sim
gtkwave async_fifo.vcd| File | Purpose |
|---|---|
fifo_block_diagram.png |
FIFO architecture overview |
waveform_screenshot.png |
Simulation waveform proof |
Below is an example of how this FIFO can be instantiated inside a Verilog design:
async_fifo #(
.DATA_WIDTH(8),
.DEPTH(16)
) fifo_inst (
.wr_clk(wr_clk),
.wr_rst(wr_rst),
.wr_en(wr_en),
.din(din),
.full(full),
.almost_full(almost_full),
.rd_clk(rd_clk),
.rd_rst(rd_rst),
.rd_en(rd_en),
.dout(dout),
.empty(empty),
.almost_empty(almost_empty)
);This project is released under the MIT License. You are free to use, modify, and distribute this design with attribution.

