FIFO Design & Depth Calculation

Designing robust buffers for Flow Control and Clock Domain Crossing. The most common interview question in Digital Design.

1. What is a FIFO & Why Use It?

What is it?

A First-In-First-Out (FIFO) memory queue. Data written into the tail is read from the head in the exact same order.

Why do we need it?

  • Rate Adaptation: When the Source writes data in fast bursts but the Destination reads at a slow, constant rate. The FIFO absorbs the burst.
  • Clock Domain Crossing (Async FIFO): Passing data safely between two asynchronous clocks.
  • Width Adaptation: Converting 32-bit data to 8-bit streaming (requires serialization logic + FIFO).

2. Minimum Depth Calculation (The "Burst" Scenario)

The goal is to prevent Overflow. If the Writer is faster than the Reader, the FIFO fills up. We must size the FIFO to hold the accumulated data *during the active burst period*.

The Golden Formula
Min Depth = Burst_Size - (Burst_Size * (R_read / R_write))
          = B * (1 - R_rd/R_wr)
Intuition: Think of a water tank. Include = Water entering (Burst). Exclude = Water leaving (Reading *during* the burst time). Remaining = Tank Size needed.

Example Calculation

  • Write Clk: 100 MHz (10ns)
  • Read Clk: 50 MHz (20ns)
  • Burst: Writer sends 80 items back-to-back (1 item/cycle).
  • Idle: Writer waits 100 cycles between bursts.

Step 1: How long is the burst?
Time = 80 items * 10ns = 800ns.

Step 2: How many items can Reader read in 800ns?
Items = 800ns / 20ns = 40 items.

Step 3: What remains?
Depth = 80 (Written) - 40 (Read) = 40.

3. Async FIFO Design (Gray Pointers)

In an Async FIFO, we must compare the Write Pointer (Write Domain) with the Read Pointer (Read Domain) to generate FULL/EMPTY flags.

The Problem

We cannot just sample a binary pointer (e.g., `011` -> `100`). If bits settle at different speeds, we might sample `111` or `000` (disaster). Pointers must be passed through 2-FF synchronizers.

The Solution: Gray Codes

Convert Binary Pointers to Gray Code before synchronizing. Gray codes only change 1 bit at a time (`000` -> `001` -> `011` -> `010`).

Safety Mechanism: If the synchronizer samples "mid-transition", it either sees the Old Value or the New Value. Since only 1 bit changed, there is no "invalid intermediate state". Both values are safe (though one might be slightly pessimistic).

4. Full vs Empty Logic (Pessimism)

  • Empty Flag: Generated in Read Domain. Compares `rd_ptr` vs `synchronized_wr_ptr`.
    Pessimism: The `wr_ptr` takes 2 cycles to cross over. The FIFO might actually have data (not empty), but the reader thinks it's empty for 2 extra cycles. This is Safe. (Throughput hit, no data loss).
  • Full Flag: Generated in Write Domain. Compares `wr_ptr` vs `synchronized_rd_ptr`.
    Pessimism: The `rd_ptr` takes 2 cycles to cross. The FIFO might have space (not full), but writer thinks it's full. This is Safe. (No overflow).