7.3.1 Directed fill and drain

EasyImplementVerilator · local serverReview the topic

Generate the directed test that pushes a FIFO one write past full and one read past empty.

Hardware context: Traffic generation and pin driving for FIFO verification. Drive a deterministic fill/drain sequence and verify normal termination.

The first directed test in the FIFO plan proves the two boundaries: the FIFO refuses a write when it is full and refuses a read when it is empty. A generator that stops at exactly depth writes never asks the FIFO to refuse anything, and the test passes against a FIFO that overflows.

Write fill_and_drain(depth, ops). Append one fifo_op per clock edge: first depth + 1 writes, carrying data 1, 2, 3 and so on, then depth + 1 reads. Never set both enables in one operation. ops arrives empty.

Your operations are replayed through the FIFO rules: the last write must be refused at full and the last read refused at empty.

Signals in the timeline

SignalWidthRole
depth8input of each check
Full specification
The operation type (supplied)
typedef struct packed {
  bit       write_en;
  bit       read_en;
  bit [7:0] data;
} fifo_op;
What you write
function automatic void fill_and_drain(input int depth, ref fifo_op ops[$]);

The replay counts operations, accepted and refused writes and reads, operations with both enables, whether write k (counting from 1) carries data k, whether every write comes before the first read, and the occupancy at the end.

Examples

Example 1

Depth 1
Input
depth = 1
Output
operations = 4, writes_accepted = 1, writes_refused = 1, reads_accepted = 1, reads_refused = 1, both_enables = 0, write_data_in_order = yes, writes_before_reads = yes, final_occupancy = 0

Two writes (data 1, 2) and two reads: one of each is refused.

Example 2

Depth 3
Input
depth = 3
Output
operations = 8, writes_accepted = 3, writes_refused = 1, reads_accepted = 3, reads_refused = 1, both_enables = 0, write_data_in_order = yes, writes_before_reads = yes, final_occupancy = 0

Four writes and four reads; write 4 meets a full FIFO and read 4 an empty one.

Example 3

Depth 16
Input
depth = 16
Output
operations = 34, writes_accepted = 16, writes_refused = 1, reads_accepted = 16, reads_refused = 1, both_enables = 0, write_data_in_order = yes, writes_before_reads = yes, final_occupancy = 0

34 operations; the FIFO ends empty.

Constraints and contract

  • depth is 1 to 16.
  • Every operation has exactly one enable set.
  • Keep the function name and arguments.

Hints

Hint 1

How many writes does it take to make the FIFO refuse one? Count from empty.

Hint 2

Two loops are enough: one for the writes, then one for the reads.

Hint 3

Build each operation as a struct value and push_back it; the data of write i (from 0) is i + 1.

What this judge verifies: Your operations are replayed through the FIFO rules at depths 1 to 16, counting accepted and refused operations and checking the write data. Passing shows the test crosses both boundaries once.

16 checks on Verilator · local server. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.

See all 5 steps and the final capstone
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

Depth 1

Input
depth = 1
Expected output
operations = 4, writes_accepted = 1, writes_refused = 1, reads_accepted = 1, reads_refused = 1, both_enables = 0, write_data_in_order = yes, writes_before_reads = yes, final_occupancy = 0

Two writes (data 1, 2) and two reads: one of each is refused.

Run samples executes all 3 example checks. Check all tests runs 16 checks.

Verilator · local server