The fix matches the check that failed, and each fix below carries its price. Say the price out loud: interviewers promote candidates who cost their fixes.
Failed check | Fix | Trade-off |
|---|---|---|
Non-Gray transitions | True Gray write pointer across the full range, proven one-bit per step. | Encoder logic and range discipline; no throughput cost. |
Illegal synchroniser | Dedicated two-flop chain per pointer bit in the read clock. | Two read cycles of empty-flag latency: the flag is conservative by construction. |
Misplaced comparison | Empty computed in the read domain from local read pointer plus synchronised write pointer. | Duplicated comparison logic per domain; full is mirrored in the write domain. |
Reset misalignment | Both pointers released to empty-state values in a defined order, re-verified after the change. | Reset sequencing constraints the system must honour. |
Three guards keep the fix fixed. First, an assertion that the crossed pointer changes at most one bit per write step, so any future counter edit that breaks Gray fails immediately. Second, a structural check on the pointer crossing in every regression, so no optimisation pass can merge or bypass a synchroniser stage unnoticed. Third, a directed reset test covering every supported reset sequence, asserting the FIFO starts empty and the first burst reads back exactly what was written. The assertion strategy follows Assertions for Protocols.
// bad-example
// Comparing two freshly crossed pointers in one domain: empty_wrong
// mixes a write crossing with a read crossing (two skews, one gate).
// The structural reconvergence check flags exactly this shape.
assign empty_wrong = (wr_ptr_sync == rd_ptr_sync);The snippet above is the shape the comparison-placement check hunts: two synchronised copies meeting in one gate. Legal code compares a local pointer against one synchronised copy, in the comparison's own domain.
Synchroniser latency delays the write pointer's arrival, so empty can assert when data has just arrived but can never deassert while data is missing: the error direction is always safe, stalling rather than corrupting.