5 rounds · 33 min · $2.60
Verification plan for sfifo in the target configuration BW=8, LGFLEN=4 (depth 16), OPT_ASYNC_READ=0, OPT_WRITE_ON_FULL=0, OPT_READ_ON_EMPTY=0. The DUT has a plain valid-style push/pop interface with no bus protocol, so no library agent applies. A custom single-clock agent drives i_reset, i_wr, i_data and i_rd. A passive monitor samples all inputs and outputs at each rising edge. A cycle-accurate reference model holds a SystemVerilog queue of up to 16 bytes. At every edge it decides acceptance from its own pre-edge state: write accepted = i_wr && !reset && fill<16; read accepted = i_rd && !reset && fill>0. Reset clears the queue. In the cycle after each edge, a scoreboard compares o_fill, o_empty and o_full exactly against the model, and compares o_data against queue.front() whenever the model is non-empty. o_data is not checked while empty, since the spec leaves it undefined. SVA assertions in a bound checker cover the status invariants and the hold-stable rules. Directed tests target the hard edges: full, empty, fill=1, fill=15, pointer wrap, simultaneous read/write at every boundary, and reset with data held or with inputs active. Constrained-random traffic with varied write/read densities then sweeps all fill levels and pointer phases.
1) Power-on/reset test. Hold i_reset for several cycles with i_wr, i_rd and i_data randomly toggling. Check that fill=0, empty=1 and full=0 after the first reset edge and that nothing is accepted. 2) Single-word test. Write one word into the empty FIFO and check that o_empty drops and o_data equals the word in the next cycle; this exercises the registered read path with FWFT. Hold the word several idle cycles to check o_data stability, then read it and check empty. 3) Fill-to-full test. Write 16 words with no reads and check fill 1..16, with full asserting only after the 16th write. Then attempt writes while full, with distinct marker data, for several cycles, with and without i_rd. Drain all 16 and check order and that no marker word appears. Drain past empty with extra reads, then write again and verify. 4) Walking-bit data test. Write 0x01,0x02,...,0x80, then 0xFE,0xFD,...,0x7F, plus 0x00, 0xFF, 0xAA and 0x55, so every o_data bit is seen at 0 and 1 in every storage slot. Repeat at 16 different pointer offsets by pre-cycling 0..15 words, so every bit of every memory location is covered. 5) Pointer-wrap test. Stream more than 100 words with fill held at 1, 2, 8 and 15 using simultaneous read/write, so the pointers wrap many times at each occupancy. 6) Simultaneous read/write boundary tests. Apply i_wr&&i_rd at fill=0, 1, 2, 8, 15 and 16, single-shot and back-to-back. At fill=1 this checks the new word appears next cycle (read/write same-address bypass). At fill=0 only the write is accepted. At fill=16 only the read is accepted and full stays high for that cycle. 7) Read-on-empty tests. Issue repeated i_rd while empty, including in the cycle immediately after the last word is drained. Then write and check data integrity. 8) Mid-stream reset tests. Assert reset at fill=1, 8, 15 and 16, during simultaneous read/write, and with i_wr/i_rd high in the reset cycle. Use reset pulses of 1 cycle and of several cycles. Then refill with new data and check that no pre-reset data ever appears, including stale words at the read pointer slot. 9) Constrained-random regression of 50+ seeds, about 5k cycles each. Mix weighted modes: write-heavy (wr 90%, rd 20%), read-heavy (wr 20%, rd 90%), balanced 50/50, bursty (long all-write then all-read runs), and full-hover/empty-hover modes that keep fill near 16 or 0. Fully random i_data, independent of i_wr, so i_data activity during i_wr=0 is ignored. Add rare random resets at 0.5%. The scoreboard and SVA run throughout, and coverage closure drives seed count.