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.
Flag | Computed in | From | Assert when | Error direction |
|---|---|---|---|---|
| Write domain | wptr − synchronised rptr | fill ≥ DEPTH − MARGIN | Stale rptr is behind, so fill is over-estimated: flag early (safe) |
| 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.
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.
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).
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.
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.
MARGIN ≥ 4 entries. Count the actual sampling/reaction edges and in-flight words; 3 + 1 applies to this stated contract, not to every producer.
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).