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

  • How to Use This Course
  • Reading Path
  • CDC/RDC Glossary
  • CDC/RDC Metrics Reference
  • CDC/RDC Interview Prep
  • CDC/RDC Signoff Cheatsheet
  • Clock Domains and Failure Modes8
  • Metastability and Synchronizers16
  • CDC Protocols and Handshakes16
  • Reconvergence and Gray Coding16
  • Reset Domain Crossing16
  • Architecture and Design Rules16
  • CDC Signoff Methodology24
  • RDC Signoff16
  • Debug and Case Studies11
    • Reading a CDC Report
    • Classic Bug Anatomy
      • Lost Pulse Bug
      • Torn Bus Bug
      • FIFO Pointer Bug
      • Reset Release Bug
    • Case Studies
  • CDC and RDC Interview Prep30
  • Capstone: Sign Off a Multi-clock Peripheral4
Loading lesson

‹Classic Bug Anatomy
  1. Topics
  2. CDC & RDC
  3. Debug and Case Studies
  4. Classic Bug Anatomy
  5. FIFO Pointer Bug

Part 9 · Debug and Case Studies · Advanced

FIFO Pointer Bug

Wrong full and empty from a binary pointer crossing: the symptom, the torn-pointer waveform, and why only Gray survives review.

On this page

    The symptom is a FIFO that lies about itself: full asserted with space left, empty asserted with data waiting, and eventually overflow or underflow corrupting the stream. The pointers look right in single-clock simulation because both sides see every update atomically; the failure needs the two clocks and the skew between pointer bits, which is exactly what unit simulation never provides.

    What the waveform shows

    The simulation output below crosses a 3-bit binary write pointer through per-bit synchronisers with deterministic per-bit skew, the honest model of wires with different delays. The pointer steps 3 to 4, changing all three bits at once.

    How to read it: ptr is the source pointer stepping 1, 2, 3, 4, 5. q1 is the first synchroniser stage and sync the second. Single-bit steps cross cleanly, but the three-bit step from 3 to 4 tears: the first stage captures 7 and the second stage delivers 7, a value a one-step counter can never produce between 3 and 4, before settling to 4.

    Root cause

    A binary pointer routinely changes several bits in one step, and each bit resolves independently in its own synchroniser, so the sampled pointer mixes old and new bits. Full and empty are computed by comparing the local pointer against the crossed one, so a torn sample manufactures a false full or a false empty. The damage compounds: a false empty reads stale data forward, a false full drops a write, and the stream is corrupt with no flag to say so.

    The finding that would have caught it

    Structural analysis expects Gray pointers on FIFO crossings and reports a binary pointer as a multi-bit crossing without a protocol. The Gray-pointers lesson of the async-FIFO topic states what the check looks for: a registered Gray value advancing one step at a time, synchronised bit by bit. Any pointer that can reload or skip breaks the one-bit discipline and needs a different structure, not Gray.

    Fix and regression guard

    Fix it by crossing registered Gray pointers and converting back at the destination, with the full and empty logic written conservatively so each flag errs on its safe side. The guard is an assertion the design can carry forever: the sampled pointer must always equal the old or the new source value within the synchroniser latency, never a third value. That assertion fails on binary pointers the first time a multi-bit step aligns with a sampling edge, which is precisely the regression this bug needs.

    Interview

    “The FIFO works in simulation but corrupts data on the bench. Where do you look?” Answer: the pointer crossing, binary versus Gray, and the impossible-value signature in the sampled pointer. Then name the assertion that would have caught it in regression.

    Check yourself The sampled write pointer reads 7 while the source stepped from 3 to 4. Why is 7 impossible rather than merely early or late?

    A one-step counter between 3 and 4 can only ever hold 3 or 4; 7 matches neither, so it is a mix of old and new bits, not a timing offset.

    Check yourself Why does this bug survive single-clock FIFO simulation?

    With one clock both sides sample every pointer update atomically, so no torn sample can form. The tear needs two clocks plus skew between the pointer bits.

    Related topics

    • Gray Pointers in Signoff

    • Full and Empty

    • RTL: Asynchronous FIFO

    Previous

    141 / 179

    Next: Reset Release Bug

    Up next

    Up nextReset Release Bug

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Lost Pulse Bug
    sclkptr12345q1123745sync0123745
    Simulation output: a binary pointer step from 3 to 4 sampled through skewed per-bit synchronisers, delivering the impossible value 7