Sign in on the Premium hub to save lesson progress. This lesson is open to read so the page is a complete article, not an empty login wall.
Lesson 4.4

Reset, almost-full, power-of-two depth

Reset must not leave one domain “running” with pointers at zero while the other still thinks it is full. Almost-full is occupancy in the write domain from a Gray-converted synced read pointer.

1

Per-domain reset

Assert asynchronously if you want (POR). Deassert synchronously in each domain with a 2FF reset synchronizer on that domain’s clock. Both pointer engines and both 2FF chains return to 0. After both domains release reset, empty=1, full=0.

POR may assert both resets at once. Deassert is synchronized separately so neither pointer engine starts while the other is still in reset with a stale Gray value in the 2FF.

Trap

Do not clear only the write pointer. The read domain would still hold an old rgray; synced into write domain it can look full forever or compare nonsense.

2

Almost-full / almost-empty

In the write domain, convert wq2_rgray back to binary, subtract from wbin (mod 2^PTR_W), get occupancy as seen with CDC delay, compare to a watermark. Because the pointer is stale, almost-full is still conservative if you treat occupancy as an upper bound.

almost_full
wire [PTR_W-1:0] rbin_sync = gray2bin(wq2_rgray);
wire [PTR_W-1:0] occ_wr    = wbin - rbin_sync; // WIDTH PTR_W, wraps correctly
assign almost_full = (occ_wr >= ALMOST_FULL_LEVEL);

Do not use almost-full as a substitute for full. Hard full still gates wr_fire.

3

DEPTH not a power of two

Gray incrementers assume a binary counter that visits 0..2^n−1. A 10-entry FIFO cannot use this pointer coding as-is. Options: implement 16 deep and ignore 6 locations; use a vendor hard FIFO; use a style with Gray of two n-bit counters and more compare logic (error-prone — not this course’s default).

4

Power-on, DFT, and RAM contents

After POR, RAM is X in sim and random in silicon. Empty means those X’s are unreachable if pointers start at 0. Scan reset must not leave one 2FF chain at 1s while pointers are 0 — you would decode full. Tie DFT so both domains see a coordinated reset release, or hold wr_en/rd_en low until a software “FIFO ready” bit that waits for both reset-sync done flags.

5

Choosing almost-full levels

Set almost-full high enough that the producer’s pipeline (2–4 cycles of in-flight beats) can drain into the RAM before hard full. Because of 2FF lag, the true free space is at least as large as the writer thinks — good. Almost-empty should be low enough that the consumer’s pipeline does not starve; remember empty can stay 1 while data is already in RAM, so almost-empty from converted wgray in the read domain is a lower bound on occupancy — also conservative for “do I have a beat?” if you treat it as “maybe not yet.”

Q

Frequently asked questions

How should an async FIFO reset?

Assert can be asynchronous (POR). Deassert each domain’s reset through a 2FF synchronizer on that domain’s clock. Clear both pointer engines and both 2FF chains so empty=1 and full=0 after both sides are out of reset.

Why is staggered deassert OK?

Because each pointer stays 0 until its domain is released. The other domain sees Gray 0 through its 2FF. Do not release one engine while the other still holds a stale non-zero Gray.

How is almost-full computed?

gray2bin of the synced read Gray, subtract from wbin, compare to a watermark. Still gate writes with hard full. Treat occupancy as an upper bound because the read pointer is stale.

Can this Gray FIFO be 10 deep?

Not without wasting locations (use 16) or changing coding. Classic unit-distance wrap needs a power-of-two number of pointer states.

Key takeaways

  • Reset both domains’ pointers and synchronizer flops.
  • Watermarks from converted Gray occupancy, still gated by true full/empty.
  • This Gray FIFO style ⇒ power-of-two DEPTH.