R2.1.1 The pipeline that ran ahead

EasyDebugIcarus Verilog · browserReview the topic

Find the first cycle where a two-stage valid and data pipeline shows its data one edge early, name the cause, and make both stages registers again.

Hardware context: A two-stage pipeline carrying a valid flag and a data byte. Find the first cycle where the pipeline shows its data one edge early, and name the cause.

A two-stage pipeline carries a valid flag and a data byte from one block to the next: ports clk, rst_n (asynchronous, active-low), in_valid and in_data[7:0] in, out_valid and out_data[7:0] out. Both outputs must show the inputs of two rising edges ago, so the valid flag and its byte stay together. In the lab the receiver took every byte with the wrong flag (lesson R2.1).

Run the failing test to see its log and waveform: the bench resets the pipeline, sends a burst with one idle cycle in the middle, and compares the outputs after every edge with the inputs two edges earlier.

Step 1: find the first cycle where a signal shows a value a correct pipeline would not, and name the signal. Step 2: choose the cause from four real bugs; each first goes wrong in a different place.

Step 3 is optional: fix the pipeline in the editor and run the tests, which send six steps of valid and idle inputs per case and read the outputs after every edge.

Signals in the timeline

SignalWidthRole
script54input of each check
Full specification
The pipeline's ports (keep the name and the ports)
module pipe2v (
  input  logic       clk,
  input  logic       rst_n,      // asynchronous, active-low
  input  logic       in_valid,
  input  logic [7:0] in_data,
  output logic       out_valid,
  output logic [7:0] out_data
);
  // two stages
endmodule
RuleCorrect pipeline
DelayAfter rising edge e, out_valid and out_data equal in_valid and in_data as they were just before edge e - 1: two stages of flops for each.
Data while idleThe data byte is delayed like the flag, whether in_valid is 1 or 0; nothing is held or skipped.
ResetAsynchronous, active-low: both stages are 0 while rst_n is 0.

Cycle N is the stretch where the cycle counter shows N. A signal is wrong in cycle N if its value there differs from what a correct pipeline shows.

The tests reset the pipeline, apply six input steps before edges 0 to 5 and idle inputs before edges 6 and 7, and record the outputs after every edge: out_valid_after_edges lists the edges after which out_valid was 1, and out_data_e0 to out_data_e7 give out_data after each edge.

Diagnose the failing run

The test below runs the buggy design. Read its log, then find where it first goes wrong in the waveform.

Log

Waveform

Click a signal at a cycle to select it. Or focus the waveform and use the arrow keys: Left and Right move one cycle, Up and Down one signal.

Step 1 · The first bad cycle and signal
Step 2 · The cause

Step 3 is optional: fix the code in the editor, then run the tests.

Examples

Example 1

A burst of three bytes
Input
valid 11, valid 22, valid 33, idle 00, idle 00, idle 00
Output
out_valid_after_edges = {1, 2, 3}, out_data_e0 = 0x0, out_data_e1 = 0x11, out_data_e2 = 0x22, out_data_e3 = 0x33, out_data_e4 = 0x0, out_data_e5 = 0x0, out_data_e6 = 0x0, out_data_e7 = 0x0

A byte driven before edge k shows on out_data after edge k + 1, with its flag beside it: 11, 22 and 33 after edges 1 to 3, and out_valid 1 after the same three edges. The shipped pipeline shows each byte one edge before its flag.

Example 2

A bubble in the middle
Input
valid 11, valid 22, idle 00, valid 9c, valid 45, idle 00
Output
out_valid_after_edges = {1, 2, 4, 5}, out_data_e0 = 0x0, out_data_e1 = 0x11, out_data_e2 = 0x22, out_data_e3 = 0x0, out_data_e4 = 0x9c, out_data_e5 = 0x45, out_data_e6 = 0x0, out_data_e7 = 0x0

The idle step travels like any other: after edge 3 out_valid is 0 and out_data 00, then 9c and 45 follow with the flag set.

Example 3

Data changes while idle
Input
idle 5e, valid a1, idle 07, idle f0, valid 80, idle 3c
Output
out_valid_after_edges = {2, 5}, out_data_e0 = 0x0, out_data_e1 = 0x5e, out_data_e2 = 0xa1, out_data_e3 = 0x7, out_data_e4 = 0xf0, out_data_e5 = 0x80, out_data_e6 = 0x3c, out_data_e7 = 0x0

The byte is delayed whether or not it is valid: 5e, 07, f0 and 3c come out with out_valid 0, a1 and 80 with out_valid 1.

Constraints and contract

  • Inputs change 1 ns after an edge and are known 0/1 values.
  • Keep the module name and the ports.

Hints

Hint 1

Find the first byte in the waveform. On which edge does it enter the first stage, and on which edge does it reach out_data? Count the edges between them.

Hint 2

out_valid arrives where it should; only one of the two signals is early. What is different between the block that drives it and the block that drives out_data?

Hint 3

Inside one clocked block, a line that reads a variable assigned with = on the line before sees the new value, not the old one.

What the grader checks: The failing run is simulated live with the shipped pipeline. The first bad cycle and every option's first wrong value come from simulating the correct pipeline and each buggy one on the same bench; the optional fix is measured over six directed and eight seeded input scripts against a model that delays both inputs by two edges.

14 checks on Icarus Verilog · browser. 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

A burst of three bytes

Input
valid 11, valid 22, valid 33, idle 00, idle 00, idle 00
Expected output
out_valid_after_edges = {1, 2, 3}, out_data_e0 = 0x0, out_data_e1 = 0x11, out_data_e2 = 0x22, out_data_e3 = 0x33, out_data_e4 = 0x0, out_data_e5 = 0x0, out_data_e6 = 0x0, out_data_e7 = 0x0

A byte driven before edge k shows on out_data after edge k + 1, with its flag beside it: 11, 22 and 33 after edges 1 to 3, and out_valid 1 after the same three edges. The shipped pipeline shows each byte one edge before its flag.

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

Icarus Verilog · browser