Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
    • Low-Power RTL Hub
    • DFT and Scan Hub
    • Physical Awareness Hub
    • Waveform Debug Hub
    • STA and ECO Hub
    • RTL-to-Implementation Closure
    • DFT-Ready RTL
    • Capstone: Resilient Streaming Peripheral
    • Principal Design Review
    • Senior RTL Interview Questions & Model Answers
      • Interview: Combinational and Arithmetic
      • Interview: Sequential and Pipelines
      • Interview: FSM and Control
      • Interview: Timing and STA
      • Interview: CDC and Reset
        • A CDC review: what to check
        • Reset assertion vs release
        • Why an async FIFO uses Gray pointers
        • Pulse synchronizers and reset-domain crossings
      • Interview: Memories and Buses
      • Interview: Low-Power Design
      • Interview: Debug and ECO
      • Interview: Coding and Whiteboard
  • Glossary and Notation
Loading lesson

‹Interview: CDC and Reset
  1. Topics
  2. RTL Design
  3. Senior & Interview
  4. Senior RTL Interview Questions & Model Answers
  5. Interview: CDC and Reset
  6. Why an async FIFO uses Gray pointers

Part 9 · Senior · Senior

Why an async FIFO uses Gray pointers

Why async FIFO pointers use Gray code, how full and empty stay safe, and an exhaustive pointer test.

On this page

    Why this matters

    A binary pointer changes several bits at once, so the other clock can sample a count that never existed and the full and empty flags go wrong. The interviewer asks about Gray pointers to hear the multi-bit crossing argument.

    After this lesson you can: explain why Gray pointers cross safely, why the pointer has one extra bit, and how full and empty are compared.

    The question

    “When do you choose an async FIFO, and why Gray pointers?” The interviewer is testing the multi-bit crossing argument, not the FIFO interface.

    The short answer: Gray pointers cross domains while full and empty stay synchronised. The answer below says why each half is needed.

    Model answer

    A FIFO is the structure for streams between unrelated clocks: data waits in memory, and only the pointers cross. Binary pointers fail because several bits change at once, so the destination samples a mix of old and new.

    The pointer steps from 3 to 4 while the destination samples it. Each bit reaches the destination flop at a slightly different time. In binary all three bits change and the sample can read any mix; in Gray only one bit changes.

    Read each panel at the dashed sample line: every bit reads its level at that instant.

    • Binary: bit 2 has already risen, bits 1 and 0 have not yet fallen, so the destination reads 7, a value the counter never held.

    • Gray: only bit 2 moves. Whichever side of the edge the sample lands on, the result is 3 or 4.

    • Old or new is safe for a FIFO flag: a stale pointer only delays full or empty by a cycle, as the table below explains.

    Registered Gray changes one bit per adjacent source step. For an isolated transition the synchronized sample can reflect old or new; a slow destination may skip intermediate pointer values. This requires per-bit synchronizers plus implemented bus-skew/arrival bounds that prevent successive source transitions from overlapping at destination inputs. Derive bounds from the fastest permitted source step across clock modes and audit exception precedence (physical constraints).

    The bottom row is the Gray image of the counter above it. Each step flips exactly one bit.

    • Slot 0: bin 0, gray 0. The crossing is idle.

    • Slot 1: bin 1, gray 1. Bit 0 flips.

    • Slot 2: bin 2, gray 3. Bit 1 flips.

    • Slot 3: bin 3, gray 2. Bit 0 flips back.

    • Slot 4: bin 4, gray 6. Bit 2 flips.

    Status

    Binary meaning

    Gray comparison

    Empty

    Write pointer equals read pointer

    Gray values equal.

    Full

    Same address, opposite lap bit

    Top two Gray bits inverted, rest equal.

    Under those crossing/reset assumptions and correct local next-pointer logic, stale remote pointers conservatively delay permission: full may persist after a read and empty may persist after a write. See almost flags.

    Follow-ups

    Check yourself Why does each pointer carry one extra bit?

    A FIFO with 2^AW entries uses AW + 1 bit pointers. The lower bits address memory and the top bit counts laps, so full (one lap ahead) differs from empty (equal).

    Check yourself The counter sometimes reloads instead of stepping by 1. Does Gray code still hold?

    No. A jump breaks the single-bit rule. Values that can jump need a handshake, not a Gray crossing.

    Check yourself How is full checked without converting back to binary?

    In the Gray domain: the next write Gray pointer equals the synchronised read Gray pointer with its top two bits inverted (pointer lesson).

    Common wrong answers

    Common pitfall

    Comparing a Gray pointer with a binary pointer, or mixing the current pointer with the next-state pointer, are the two classic bugs. Compare Gray with Gray, and compare the next write pointer so that full registers correctly.

    • “Binary pointers with a 2FF each are fine.” Multi-bit changes land in the window and the full and empty flags corrupt.

    • “Full means the pointers are equal.” Equal pointers mean empty. Full is one lap apart.

    Solution and testbench

    A Gray pointer with an exhaustive testbench: one-bit steps including the wrap, plus exact round trip for all 16 values.

    gray_ptr.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // Gray-coded FIFO pointer: binary count with a registered Gray image for the crossing.
    module gray_ptr #(parameter int W = 4) (
      input  logic         clk,
      input  logic         rst_n,
      input  logic         inc,
      output logic [W-1:0] bin,
      output logic [W-1:0] gray
    );
      logic [W-1:0] bin_next;
      assign bin_next = bin + 1'b1;
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin bin <= '0; gray <= '0; end
        else if (inc) begin
          bin  <= bin_next;
          gray <= (bin_next >> 1) ^ bin_next;   // convert before the register: no glitch crosses
        end
    endmodule
    

    Remember

    • Gray code changes one bit per step, so a sampled pointer is either the old or the new value.

    • A FIFO with 2^AW entries uses AW + 1 bit pointers. Equal pointers mean empty; one lap apart means full.

    • Compare Gray with Gray, and use the next write pointer. Stale remote pointers only delay permission.

    Rule of thumb: cross a pointer that can only step by one, and compare it in the domain that owns the flag.

    How this was checked

    Gray pointer testbench Run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It checks one-bit steps including the wrap and the exact round trip for all 16 values. It checks conversion only, not bus routing, metastability or a whole FIFO.

    Keep going

    • Practice: Asynchronous FIFO with Gray pointers and safe flags

    • Practice: Async FIFO pointer mismatch from a CDC bug

    • Code lab: Async FIFO Gray pointers

    • Interview: run a mock interview on this topic

    Related topics

    • Asynchronous FIFO

    • Pointers and Gray conversion

    Previous

    331 / 350

    Next: Pulse synchronizers and reset-domain crossings

    Up next

    Up nextPulse synchronizers and reset-domain crossings

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • A CDC review: what to check
    clkbin01234gray01326
    A 3-bit counter and its Gray code stepping from 0 to 4