Sign in on the Premium hub to save lesson progress. This lesson is open to read so the page is a complete article, not an empty login wall.
Lesson 1.1

Why FIFOs are needed

A FIFO is not a memory trick. It is a rate-matching and backpressure block: the producer and consumer no longer have to handshake on every beat in lockstep. Start here before Gray code or dual clocks — those only make sense after you know what problem the FIFO is solving.

Definition

FIFO = First-In, First-Out queue. Writes push at the tail. Reads pop from the head. Order is preserved. Overflow is writing when full. Underflow is reading when empty.

1

The problem without a FIFO

Two blocks want to exchange data. If they share a wire and a ready/valid handshake on the same clock, they still stall each other every time the consumer cannot accept a beat. If they run at different average rates, or in bursts, a single-register handshake is not enough.

Burst vs average

A camera dumps 1920 pixels in a line, then goes idle during blanking. The downstream DMA wants a steady stream. A FIFO absorbs the burst.

Backpressure

full tells the producer to stop. empty tells the consumer there is nothing to pop. Those flags are the entire contract.

Clock domains

UART RX at 115200 baud vs a 200 MHz core. You cannot share a pointer register between those clocks. That is the async FIFO — later in this course.

Analogy

A warehouse between a truck (bursty writer) and a retail counter (steady reader). If the warehouse is full, the truck waits. If it is empty, the counter waits. The warehouse depth is sized from the burst, not from the average rate alone.

2

When a single flop / skid buffer is enough

A skid buffer (1–2 deep registered handshake) covers one cycle of downstream stall. Use a FIFO when occupancy can grow beyond one or two beats, or when clocks differ.

BlockDepthClocksUse when
Registered ready/valid0–1SameCombinational ready cut; no burst
Skid buffer1–2SameOne-cycle stall isolation
Sync FIFON (power of 2 typical)SameBursts, rate matching, elastic buffering
Async FIFON, power of 2 required for Gray pointersDifferentCDC of a data stream
3

Depth sizing (interview formula)

If the writer can produce faster than the reader for a finite burst:

depth ≥ burst_beats + ceiling((W − R) × T_burst / beat_time) + margin

Where W and R are write and read rates during the burst window. If long-term W > R, no finite FIFO works — you must throttle the writer or speed up the reader. A FIFO never creates bandwidth; it only stores it.

Trap

Sizing from “it felt full in sim” is not a method. Interviews want: identify the worst-case burst, compute occupancy, add CDC pointer-sync latency (async case), then round up to the next power of two if you use Gray pointers.

4

Waveform — producer burst, consumer drain

Writes raise occupancy. When full is 1, further wr_en must not commit (wr_fire = wr_en && !full). Reads lower occupancy until empty.

Open the free simulator and type a 4-deep register file plus two pointers — that is already a FIFO. We write the real one in lesson 2.2. Launch Verilog simulator →

5

Mapping FIFO flags to ready/valid

On AXI-Stream style interfaces, the producer’s tready is usually !full (sometimes registered). The consumer’s tvalid is !empty for a standard FIFO, or a peek of the head for FWFT. Never drive tready combinationally from a path that also depends on tvalid in a loop — that is how you get combinational deadlock. A registered full flag plus a skid in front of the FIFO is a common fix.

If the producer ignores tready and keeps pulsing tvalid, that is overflow at the protocol layer even if your FIFO RTL gated the write. The contract is end-to-end: the writer FSM must stall.

6

A FIFO never creates bandwidth

Suppose a writer emits 200 MB/s for 40 µs (one video line) and a reader can only take 80 MB/s continuously. During the line you accumulate (200−80)×40e-6 = 4.8 kB. After the line, blanking lets the reader catch up. The FIFO must hold at least 4.8 kB plus CDC margin. If the next line starts before the FIFO drains, occupancy ratchets up until you overflow — that is a system-rate bug, not a FIFO-depth typo you can hide forever.

Interviews like the phrase: the FIFO stores energy in the rate mismatch; it does not generate energy. Clock-crossing adds extra apparent occupancy because full/empty lag by a few destination clocks.

7

Worked example — UART to 100 MHz core

UART at 115200 baud, 8N1, is one byte every 86.8 µs. A 100 MHz core that reads one byte per cycle could empty a 16-deep FIFO in 160 ns. Depth is set by software interrupt latency, not by the UART bit rate: if firmware can take 200 µs to service RX, you need about 200e-6 / 86.8e-6 ≈ 3 bytes plus margin — 8 or 16 is typical. The async FIFO exists because the UART APB clock is not the CPU clock; Gray pointers carry occupancy across that boundary.

Contrast a 10 GbE MAC writing 64-byte packets every 67 ns into a 200 MHz DMA that sometimes stalls for 2 µs on a DRAM bubble: occupancy can jump by dozens of beats. That is why NIC designs use deep async FIFOs or store-and-forward packet memories, not a 4-entry toy queue.

Q

Frequently asked questions

Why is a FIFO used in digital design?

A FIFO is an elastic First-In First-Out queue that absorbs bursts and applies backpressure with full and empty flags. It matches two rates over a finite window. It does not create extra bandwidth if the writer is permanently faster than the reader.

When is a skid buffer enough instead of a FIFO?

Use a 1–2 deep skid buffer when you only need to cut a combinational ready path or survive a single-cycle stall. Use a FIFO when occupancy can grow over many beats, or when the producer and consumer use different clocks.

How do you size FIFO depth for an interview?

Identify the worst-case burst length, subtract what the reader can drain during that window, add margin for pointer-synchronizer delay on an async FIFO, then round up to a power of two if you use Gray pointers. If average write rate exceeds average read rate, no finite depth works.

Is overflow the same as the full flag?

No. Full means the producer must stall (wr_fire stays 0). Overflow means a write still committed while occupancy was already DEPTH, destroying unread data. A correct RTL never overflows.

Key takeaways

  • FIFOs exist for elastic buffering: bursts, backpressure, and (later) clock crossing.
  • full / empty are the contract. Overflow and underflow are bugs, not “retry later”.
  • Finite depth cannot fix a permanently faster writer.