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
    • Reset Architecture
    • Metastability and Synchronisation
    • Asynchronous FIFO
      • Why an Async FIFO Is the Standard
      • Pointers and Gray Conversion
      • Full, Empty and the Complete Design
      • Almost Full and Almost Empty
      • Reset and Initialisation
      • Verification and CDC Closure
      • Sizing a FIFO, End to End
    • CDC Protocols
    • Reset Domain Crossing
    • CDC Verification
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Asynchronous FIFO
  1. Topics
  2. RTL Design
  3. Reset & CDC
  4. Asynchronous FIFO
  5. Almost Full and Almost Empty

Part 6 · Reset & CDC · Intermediate

Almost Full and Almost Empty

Conservative almost-full and almost-empty flags derived from stale pointers, and margin sizing.

On this page

    Why this matters

    Full and empty are hard limits, but a pipeline with reaction latency needs warning before them. With DEPTH = 16, a warning at 8 and up to 6 more accepted writes, the peak is 14 and a MARGIN of 4 is not enough.

    After this lesson you can: choose MARGIN from the producer's reaction budget and explain why an almost flag never replaces full or empty.

    Early warning

    full and empty are hard limits. Almost full and almost empty are early warnings for pipelines with reaction latency.

    Each flag is computed from the synchronised pointer of the other side. Asserted early, it stops traffic before overflow or underflow.

    fillw​=wptrbin​−rptrsync,bin​fillr​=wptrsync,bin​−rptrbin​

    Flag

    Computed in

    From

    Assert when

    Error direction

    walmost_full

    Write domain

    wptr − synchronised rptr

    fill ≥ DEPTH − MARGIN

    Stale rptr is behind, so fill is over-estimated: flag early (safe)

    ralmost_empty

    Read domain

    synchronised wptr − rptr

    fill ≤ MARGIN

    Stale wptr is behind, so fill is under-estimated: flag early (safe)

    The previous lesson supplies checks that require the corresponding flag whenever true occupancy is within MARGIN of full or empty. The five-ratio test and the endpoint tests apply those checks.

    Choosing the margin

    1. Count the maximum additional accepted writes from the threshold crossing until the producer stops: include flag sampling, registered reaction, pipeline/skid buffers and any extra acceptance at the boundary edge. Do not count the same in-flight word twice.

    2. Pointer crossing latency: already built into the conservative calculation, but allow 2 or 3 cycles of the write clock for the flag to react to read-side activity (that is the pessimism, not extra margin).

    3. Require MARGIN ≥ maximum post-threshold arrivals minus guaranteed reads during reaction (use zero reads unless guaranteed). The RTL permits 0 through DEPTH inclusive. There is no universal DEPTH/4 limit: a long pipeline can require a large reserve. If the reserve exceeds DEPTH, enlarge the FIFO or change the acceptance contract.

    Illustrative contract: DEPTH=16, warning threshold 8, at most 6 subsequent accepted writes and no guaranteed reads gives a peak of 14, leaving 2 slots. MARGIN=4 would not satisfy that reaction budget. The hard full gate still prevents storage overflow but may force the upstream pipeline to retain words. MARGIN=DEPTH warns even when empty; a producer that refuses all writes while warned will make no progress.

    A 16-entry FIFO at the moment almost-full is raised, with 6 more writes still accepted and no guaranteed reads

    Read each bar left to right as FIFO slots; the orange line is where almost-full rises.

    • With MARGIN = 8 the warning comes at 8 stored words. The 6 writes already on their way bring the peak to 14, and 2 slots stay free.

    • With MARGIN = 4 the warning comes at 12. The same 6 writes would need 18 slots, so wfull stops the last 2 and the upstream pipeline must hold them.

    • The margin is set by the writes that cannot be stopped, not by a fixed fraction of the depth.

    Measure throughput under the chosen warning policy and workload. The previous listing now includes MARGIN=2 and 8 policy instances with deterministic saturated offers, identical 10 ns / 40.3 ns clocks, immediate warning reaction, and per-instance accepted/cycle, warning-stall cycles and maximum fill reports. The reports give 0.2484 accepted/cycle for MARGIN=2 and 0.2483 for MARGIN=8: a finite policy throughput cost (1 − rate8/rate2) of 0.0006 for this workload. A service-limited steady stream may have nearly equal throughput despite less burst capacity; burst/pause and actual reaction-latency traces must also be evaluated for a product.

    Common mistakes

    Common pitfall

    Do not use almost_empty to decide that the FIFO has no data. It means “nearly empty”; only empty means empty. Likewise, almost_full is not full; the writer must still obey wfull.

    Tip

    If you need the exact occupancy on one side (say, for software to read a fill level), expose the conservative fill_w or fill_r as a status and document that it lags by a few cycles.

    Check yourself A producer can accept one boundary-edge word plus 3 more words before stopping, with no guaranteed reads. What reserve is needed?

    MARGIN ≥ 4 entries. Count the actual sampling/reaction edges and in-flight words; 3 + 1 applies to this stated contract, not to every producer.

    Remember

    • MARGIN must be at least the post-threshold arrivals minus guaranteed reads. Count reads as zero unless they are guaranteed.

    • almost_empty is not empty and almost_full is not full. The writer must still obey wfull.

    • A larger margin costs throughput that depends on the workload. Measure it under the warning policy you chose.

    How this was checked

    The five-ratio test and the endpoint tests, run with Icarus Verilog 13.0 (2026-10-16), pass.

    Policy throughput, run with Icarus Verilog 13.0 (2026-10-16): 0.2484 accepted/cycle for MARGIN=2 and 0.2483 for MARGIN=8, a finite policy throughput cost of 0.0006 for this workload (saturated offers, 10 ns / 40.3 ns clocks, immediate warning reaction).

    Keep going

    • Practice: FIFO with almost-full and almost-empty flags

    • Code lab: FIFO almost-full flag

    • Interview: run a mock interview on this topic

    Related topics

    • Reset and initialisation

    • Sizing a FIFO, end to end

    Previous

    168 / 350

    Next: Reset and Initialisation

    Up next

    Up nextReset and Initialisation

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Why an Async FIFO Is the Standard
    • Pointers and Gray Conversion
    • Verification and CDC Closure