Parameterizable Depth Asynchronous FIFO
Modern SoCs consist of multiple independent clock domains interacting constantly. When a high-speed PCIe controller needs to pass data to a slower system bus, an asynchronous FIFO acts as the critical elastic buffer between these domains. Hardcoding FIFO dimensions leads to massive code duplication across a large chip; parameterizable IP is essential for scalable and maintainable hardware design.
This module implements a robust asynchronous FIFO with parameterized data width and depth. It safely transfers data across two unrelated clock domains (wclk and rclk). Write operations occur in the write clock domain when winc is asserted and the FIFO is not full. Read operations occur in the read clock domain when rinc is asserted and the FIFO is not empty. Cross-domain pointer synchronization must be handled via Gray code conversion and two-stage flip-flop synchronizers to prevent metastability. The memory array depth is determined by $2^{\text{ADDR\_WIDTH}}$.
Timing and Reset Rules
- Clock edge: Both
wclkandrclktrigger on the positive edge. - Reset type:
wrst_nandrrst_nare asynchronous and active-low. - Reset behaviour: On reset, internal pointers clear.
wfullgoes to 0,remptygoes to 1, andrdatagoes to 0. - Read behaviour: This is a standard FIFO, not First-Word Fall-Through (FWFT).
rdataupdates on the clock edge whererincis high. - Priority: If
wincis asserted whilewfullis high, the write must be ignored. Ifrincis asserted whileremptyis high, the read must be ignored.
Worked Trace
Cycle 1: wrst_n=0, rrst_n=0 • Pointers reset. wfull=0, rempty=1. Cycle 2: wrst_n=1, winc=1, wdata=0xAA • Data written to memory. Write pointer increments. Cycle 3: (Wait for synchronizers) • Write pointer converted to Gray code, crosses to rclk domain via 2-stage synchronizer. Cycle 4: rempty=0 • Read domain detects FIFO is no longer empty. Cycle 5: rinc=1 • Data read from memory. rdata=0xAA. Read pointer increments. Cycle 6: (Wait for synchronizers) • Read pointer converted to Gray code, crosses to wclk domain via 2-stage synchronizer.
Timing Diagram
{ "signal": [
{ "name": "wclk", "wave": "p........" },
{ "name": "winc", "wave": "010......" },
{ "name": "wdata", "wave": "x4x......", "data": ["D0"] },
{ "name": "wptr_gray", "wave": "34.......", "data": ["0", "1"] },
{},
{ "name": "rclk", "wave": "p........" },
{ "name": "rq1_wptr", "wave": "3..4.....", "data": ["0", "1"] },
{ "name": "rq2_wptr", "wave": "3...4....", "data": ["0", "1"] },
{ "name": "rempty", "wave": "1...0...." }
], "head": { "text": "Write pointer synchronization leading to rempty de-assertion." } }Port Table
| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | wclk | input | 1 | Write domain positive-edge clock | | wrst_n | input | 1 | Write domain asynchronous active-low reset | | winc | input | 1 | Write increment enable | | wdata | input | DATA_WIDTH | Write data input | | wfull | output | 1 | Write domain full flag; 1 when FIFO is full | | rclk | input | 1 | Read domain positive-edge clock | | rrst_n | input | 1 | Read domain asynchronous active-low reset | | rinc | input | 1 | Read increment enable | | rempty | output | 1 | Read domain empty flag; 1 when FIFO is empty | | rdata | output | DATA_WIDTH | Read data output |
*Module Parameters:* • DATA_WIDTH: Default 8. Width of the data bus. • ADDR_WIDTH: Default 4. Determines FIFO depth as $2^{\text{ADDR\_WIDTH}}$.
Constraints
- You must use Gray code for crossing pointers between clock domains. Binary pointer crossing will fail timing in real hardware.
- You must use two-stage flip-flop synchronizers for all cross-domain signals.
- The full condition must be strictly evaluated in the
wclkdomain to prevent false negatives. - The empty condition must be strictly evaluated in the
rclkdomain to prevent false negatives. - The FIFO depth is strictly $2^{\text{ADDR\_WIDTH}}$. Memory bounds checking must use this parameter.
- Writes to a full FIFO and reads from an empty FIFO must not corrupt pointers.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.