6.2.1 The pipeline that lost a stage

EasyFixVerilator · local serverReview the topic

Fix a two-stage pipeline whose beats come out one edge early.

Hardware context: Clocked DUT pipeline observed across nonblocking updates. Observe a register before and after its nonblocking assignment at a clock edge.

This is a Fix problem: the code in the editor has one realistic defect. Find it and fix it.

delay2 is a two-stage register pipeline. A beat on in_valid and in_data just before edge k is captured into stage 1 at edge k and must be on out_valid and out_data right after edge k + 1. A monitor that samples just before each edge therefore sees it at edge k + 2. Reset empties both stages.

In simulation every beat comes out one edge early, as if the pipeline had a single stage. The scoreboard downstream expects two cycles and reports a mismatch for every beat.

For a single beat 5A presented before edge 1, out_valid must first be 1 after edge 2.

Signals in the timeline

SignalWidthRole
clk1stimulus, the same for every design
rst1stimulus, the same for every design
in_valid1stimulus, the same for every design
in_data8stimulus, the same for every design
out_valid1stimulus, the same for every design
out_data8stimulus, the same for every design
Full specification
The module (keep its ports)
module delay2 (
  input  logic       clk, rst,
  input  logic       in_valid,
  input  logic [7:0] in_data,
  output logic       out_valid,
  output logic [7:0] out_data
);
  // two register stages
endmodule
After edge kCorrect pipeline
stage 1holds the inputs from just before edge k
out_valid, out_datahold what stage 1 held before edge k, so the inputs from before edge k - 1
rst = 1 before edge kboth valid bits are 0 after edge k; data may keep any value

Each case resets the pipeline, then sets the inputs while the clock is low for 12 cycles and reads the outputs after every edge. It reports the first cycle with out_valid high, the number of beats out, the first and last beat, and the cycles with out_valid high.

Examples

Example 1

Through both stages
Input
in_valid 1 in cycle 1 with data 5A
Output
first_out_cycle = 2, beats_out = 1, first_beat = 0x5a, last_beat = 0x5a, cycles_with_out_valid = {2}

Edge 1 captures the beat into stage 1, edge 2 moves it to the outputs: out_valid is 1 in cycle 2 only.

Example 2

A stream keeps its spacing
Input
beats 11, 22, 33 in cycles 1 to 3
Output
first_out_cycle = 2, beats_out = 3, first_beat = 0x11, last_beat = 0x33, cycles_with_out_valid = {2, 3, 4}

They come out in cycles 2 to 4, in order.

Example 3

Reset drops the beats inside
Input
beats A1, B2 in cycles 2 and 3, reset in cycle 4, beat C3 in cycle 6
Output
first_out_cycle = 3, beats_out = 2, first_beat = 0xa1, last_beat = 0xc3, cycles_with_out_valid = {3, 7}

A1 leaves in cycle 3; B2 is in stage 1 when reset comes and is lost. C3 leaves in cycle 7.

Constraints and contract

  • Captured at edge k, on the outputs after edge k + 1, for every beat.
  • Reset clears the valid bit of both stages.
  • Keep the module name and ports.

Hints

Hint 1

Inside one always block, statements run in order. What value of s1_valid does the third statement read?

Hint 2

A flip-flop should capture the value its input had before the edge, not a value computed earlier in the same edge.

Hint 3

There are two ways to write an assignment in a clocked block. Only one of them delays the update until every block has read the old values.

What this judge verifies: The pipeline runs 24 traces of 12 cycles, some with a reset in the middle, and its outputs are read after every edge. Passing shows the two-edge delay and the reset on these traces.

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

Through both stages

Input
in_valid 1 in cycle 1 with data 5A
Expected output
first_out_cycle = 2, beats_out = 1, first_beat = 0x5a, last_beat = 0x5a, cycles_with_out_valid = {2}

Edge 1 captures the beat into stage 1, edge 2 moves it to the outputs: out_valid is 1 in cycle 2 only.

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

Verilator · local server