Part 8 · Senior & Interview Prep · Intermediate
Step 1: Spec Analysis & Verification Plan
The FIFO spec, feature list extraction, the verification plan table, and the corner-case inventory.
The spec as given
Everything starts from the spec — read it as a verifier: every "shall" becomes a feature row, and every silence becomes a logged question.
FIFO SPECIFICATION (v1.2)
Parameters
WIDTH : data width in bits (default 8, range 1-64)
DEPTH : number of entries (default 16, power of 2, >= 2)
Interface (all synchronous to clk, async active-low rst_n)
write side: in_valid (in) in_ready (out) in_data[WIDTH] (in)
read side: out_valid (out) out_ready (in) out_data[WIDTH] (out)
status: full (out) empty (out)
Behavior
1. A push occurs when in_valid && in_ready on a clk edge.
2. A pop occurs when out_valid && out_ready on a clk edge.
3. in_ready == !full; out_valid == !empty.
4. full asserts when count == DEPTH; empty when count == 0.
5. Data emerges in push order (strict FIFO), unmodified.
6. Push at full is ignored (in_ready low blocks the handshake).
7. Simultaneous push+pop is legal at any non-boundary fill level;
at full: pop proceeds, push accepted ONLY if pop frees a slot
in the same cycle (spec v1.2 clarification Q-003).
8. rst_n clears the FIFO to empty within 1 cycle; in-flight
data is discarded.Ambiguities we logged (and their answers)
Q-003: push+pop in the same cycle at full — allowed? Answer (architect, spec updated to v1.2): pop wins, the freed slot may absorb the push that same cycle.
Q-004: out_data validity when empty — defined? Answer: undefined when out_valid is low; checkers must not compare it.
Q-005: behavior if rst_n asserts mid-handshake — Answer: transaction discarded, no partial state; flags valid 1 cycle after deassert.
Feature extraction
Three spec passes produce the feature list. Note how behavior rule 7 — one sentence in the spec — becomes three separate features , because each has a different stimulus and check.
F-01 Data integrity: every pushed word pops exactly once, unmodified, in push order.
F-02 full asserts exactly at count == DEPTH, deasserts on the next pop.
F-03 empty asserts exactly at count == 0, deasserts on the next push.
F-04 in_ready mirrors !full; out_valid mirrors !empty (combinational, same cycle).
F-05 Push at full is blocked — no data loss, no corruption, count unchanged.
F-06 Pop at empty is blocked — no spurious data, count unchanged.
F-07 Simultaneous push+pop at intermediate fill: count unchanged, order preserved.
F-08 Simultaneous push+pop at full: pop proceeds; push absorbed per Q-003.
F-09 Reset mid-traffic: empty within 1 cycle, in-flight data discarded, clean restart.
F-10 Backpressure: sustained out_ready == 0 fills the FIFO; release drains in order.
F-11 Parameter sweep: behavior holds at DEPTH 2 (minimum) and WIDTH 1 (degenerate).
The verification plan table
VERIFICATION PLAN — fifo v1.2
ID │ Feature │ Approach │ Coverage / Check │ Owner
─────┼─────────────────────┼───────────────────────┼─────────────────────────┼──────
F-01 │ data integrity, │ random, all tests │ scoreboard in-order │ SB
│ in-order │ │ compare; a_data_integ │
F-02 │ full @ count=DEPTH │ burst-fill directed │ a_full_def; │ SB
│ │ + random │ cp_count.full bin │
F-03 │ empty @ count=0 │ drain directed │ a_empty_def; │ SB
│ │ + random │ cp_count.empty bin │
F-04 │ ready/valid mirror │ assertion, always on │ a_ready_def, a_valid_def│ SB
F-05 │ push @ full blocked │ stress + error test │ a_no_push_full; │ RK
│ │ │ x_op_state full bin │
F-06 │ pop @ empty blocked │ stress + error test │ a_no_pop_empty; │ RK
│ │ │ x_op_state empty bin │
F-07 │ push+pop mid-level │ random mixed-rate │ cp_simul bin │ SB
F-08 │ push+pop @ full │ directed corner test │ cp_simul_full bin │ SB
F-09 │ reset mid-traffic │ reset-storm test │ cp_reset_busy bin; │ RK
│ │ │ post-reset SB restart │
F-10 │ backpressure drain │ burst/drain scenario │ cp_backpressure bins │ SB
F-11 │ param corners │ regression configs │ DEPTH=2 + WIDTH=1 runs │ RK
Status column omitted here — all rows start "open".Corner inventory — the cases that find FIFO bugs
Exact boundaries: the cycle full asserts, the cycle empty asserts — off-by-one heaven (count == DEPTH-1 vs DEPTH).
Simultaneous push+pop at empty+1, at full-1, at full (F-08) — the pointer-update ordering bugs live here.
Reset mid-traffic, mid-burst, and reset released directly into a push — F-09.
Wrap-around: pointers crossing DEPTH back to 0 repeatedly — masked when tests push fewer than DEPTH total items.
Sustained backpressure then sudden drain at full rate — F-10.
Key takeaways
One spec sentence can hide several features — extract until each row has one stimulus and one check.
Ambiguities (simultaneous ops at full, data validity at empty) go to the architect, never guessed from RTL.
The corner inventory is the FIFO bug map: boundaries, simultaneity, reset, wrap-around, backpressure.
Common pitfalls
Testing only deep FIFOs — DEPTH=2 exposes pointer bugs big configs hide.
Comparing out_data while out_valid is low — spec says undefined (Q-004).
Pushing fewer than DEPTH items in any test — pointer wrap-around never exercised.