R5.3.1 The buffer one stall too small

EasyFixIcarus Verilog + Yosys · serverReview the topic

Fix a receive buffer that sizes its FIFO from the burst arithmetic but leaves out the consumer's stall, so that its depth is the smallest that loses no word.

Hardware context: A receive buffer between a bursting camera and a consumer that stalls, then reads every PERIOD cycles. Fix the burst buffer whose depth formula leaves out the consumer's stall.

A camera sends bursts of up to 16 words, one per cycle, into a receive buffer. The consumer behind it may wait up to 4 cycles before its first read, then reads one word every 2 cycles. The buffer's FIFO is built from flops, so the brief asks for the smallest depth that loses nothing, computed from the parameters (lesson R5.3). In the lab, overflow went high on the longest burst.

This is a Fix problem: the design below works except for one defect. Find it so that every pattern within the brief loses no word and the FIFO holds exactly the depth the brief asks for.

Brief: parameters BURST, PERIOD (2 or more) and STALL; the FIFO ports of R5.3 (clk, rst_n asynchronous and active-low, write_en, write_data, read_en; read_data, read_valid, full, empty, overflow). DEPTH is the smallest depth that loses no word when a burst of BURST words starts in cycle 0 and the consumer waits STALL cycles, then reads in the last cycle of every PERIOD; both requests are decided on the count before the edge. Any shorter burst or stall must fit too. Corner cases: no stall, a burst whose last word arrives with no read, a depth that is a power of two. The tests run five copies with their own parameters. Synthesis check: the design must build on the site's synthesis flow with no latch. The cell and level counts come from an open-source flow and are a proxy for area and depth, not a foundry result.

Signals in the timeline

SignalWidthRole
which3input of each check
burst8input of each check
stall8input of each check
Full specification
The buffer's ports (keep the module names and the ports; sync_fifo is part of your file)
module burst_buf #(
  parameter int BURST  = 16,   // the longest burst: words at one per cycle
  parameter int PERIOD = 2,    // the consumer reads one word every PERIOD cycles (2 or more)
  parameter int STALL  = 4,    // the longest wait before the consumer's first read cycle
  parameter int WIDTH  = 8
) (
  input  logic             clk,
  input  logic             rst_n,         // asynchronous, active-low
  input  logic             write_en,
  input  logic [WIDTH-1:0] write_data,
  input  logic             read_en,
  output logic [WIDTH-1:0] read_data,
  output logic             read_valid,
  output logic             full,
  output logic             empty,
  output logic             overflow       // a write was refused: a word was lost
);
  // the depth, and the FIFO
endmodule
CopyBURSTPERIODSTALL
01624
11123
22035
31240
41032

Each case resets the buffer and fills it with writes only for 24 cycles: capacity is the number of writes accepted. It then resets it again and runs 72 cycles of one pattern within the copy's brief: a burst of words numbered 0, 1, 2 ..., one per cycle from cycle 0, and a consumer that waits s cycles, then reads in the last cycle of every PERIOD. The result is capacity, lost (writes offered while full), most_held (words held after an edge, at most), words_out, order_errors (words read out of order) and overflow at the end.

Examples

Example 1

The default buffer
Input
BURST 16, PERIOD 2, STALL 4: a fill, then a burst of 16 with a stall of 4
Output
capacity = 11, lost = 0, most_held = 10, words_out = 16, order_errors = 0, overflow = no

The consumer first reads in cycle 5 and then every 2 cycles, so 6 of the 16 words leave during the burst and 10 are held at the peak. The last word arrives in cycle 15, a read cycle, so the depth is 11. The shipped buffer counts 8 reads, holds 9 words and loses 2.

Example 2

A stall of 3
Input
BURST 11, PERIOD 2, STALL 3: a fill, then a burst of 11 with a stall of 3
Output
capacity = 8, lost = 0, most_held = 7, words_out = 11, order_errors = 0, overflow = no

4 reads land inside the 11-word burst, so the peak is 7; the last word arrives with a read, so the depth is 8, a power of two. The 8-word FIFO never fills.

Example 3

Reads every 3
Input
BURST 20, PERIOD 3, STALL 5: a fill, then a burst of 20 with a stall of 5
Output
capacity = 16, lost = 0, most_held = 15, words_out = 20, order_errors = 0, overflow = no

Reads in cycles 7, 10, 13, 16 and 19: 5 inside the burst, a peak of 15, and the last word arrives in cycle 19 with a read: 16 words.

Constraints and contract

  • PERIOD is at least 2 and STALL is less than BURST.
  • Keep the module names burst_buf and sync_fifo and their ports; the whole design is in your file.

Hints

Hint 1

Run the first example and compare capacity with most_held. How many words did the consumer take during the burst?

Hint 2

The consumer's first read cycle comes STALL cycles later than it would with no stall. Which of the three localparams should know that?

Hint 3

Count the reads that land inside the burst: they start after the stall, one every PERIOD cycles, so there are (BURST - STALL) / PERIOD of them, rounded down.

What the grader checks: Fifteen patterns run on five copies with their own BURST, PERIOD and STALL: a capacity fill, then a burst and a stall within the copy's brief, with the words held, lost and read compared with an independent model of a FIFO of the depth the brief asks for. Parameters outside the five copies follow the same arithmetic but are not simulated. The synthesis check adds the latch count.

The submitted design must synthesize with 0 latches and no combinational loop. Counts come from the pinned open-source synthesis flow. They are proxies for logic size and depth, not physical area or timing.

15 checks on Icarus Verilog + Yosys · 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 1 steps and the final capstone
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

The default buffer

Input
BURST 16, PERIOD 2, STALL 4: a fill, then a burst of 16 with a stall of 4
Expected output
capacity = 11, lost = 0, most_held = 10, words_out = 16, order_errors = 0, overflow = no

The consumer first reads in cycle 5 and then every 2 cycles, so 6 of the 16 words leave during the burst and 10 are held at the peak. The last word arrives in cycle 15, a read cycle, so the depth is 11. The shipped buffer counts 8 reads, holds 9 words and loses 2.

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

Icarus Verilog + Yosys · server