Fix a monitor that waits on its clocking block but takes one value from the raw pins.
Hardware context: Driver and monitor clocking views of a synchronous bus. Sample the bus through a clocking view with an explicit input skew.
This is a Fix problem: the code in the editor has one realistic defect. Find it and fix it.
beat_monitor records every beat a source hands to a sink. It waits for the clocking event of mon_cb, which samples the bus just before each rising edge, and counts a transfer when valid and ready were both 1.
The transfer count is right, but the recorded data is wrong whenever beats follow each other: the monitor logs beat 2 for the first transfer, beat 3 for the second, and so on. Only the last beat of a burst comes out right.
For three back-to-back beats 10, 35 and 5A, the monitor must record first 10, last 5A and a sum of 0x9F.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
clk | 1 | stimulus, the same for every design |
valid | 1 | stimulus, the same for every design |
ready | 1 | stimulus, the same for every design |
data | 8 | stimulus, the same for every design |
Full specification
interface rv_if (input logic clk);
logic valid;
logic ready;
logic [7:0] data;
clocking mon_cb @(posedge clk);
default input #1step;
input valid, ready, data;
endclocking
endinterface
class beat_monitor;
virtual rv_if vif;
int transfers;
logic [7:0] first_data, last_data;
logic [15:0] data_sum;
function new(virtual rv_if vif);
task run(input int edges); // watch this many clocking events
endclass
The source updates valid and data with nonblocking assignments at the rising edge, and loads its next beat as soon as one is accepted. The sink changes ready while the clock is low.
Each case resets the source, starts run(20) and gives 20 cycles of the ready pattern. It reports the transfers, the first and last beat recorded and their sum.
Examples
Example 1
Back-to-back beats- Input
three beats from 10, ready always 1
- Output
transfers = 3, first_beat = 0x10, last_beat = 0x5a, data_sum = 0x9f
Beats 10, 35 and 5A move on three edges in a row; their sum is 0x9F.
Example 2
Stalls in between- Input
three beats from 40, ready on every other cycle
- Output
transfers = 3, first_beat = 0x40, last_beat = 0x8a, data_sum = 0x12f
Each beat waits one cycle, then moves. The data must still be 40, 65 and 8A.
Example 3
A single beat- Input
one beat A0, accepted on the fourth edge
- Output
transfers = 1, first_beat = 0xa0, last_beat = 0xa0, data_sum = 0xa0
One transfer: first and last beat are both A0.
Constraints and contract
- Record a beat only for an edge where valid and ready were both 1.
- data_sum is 16 bits.
- Keep the class, field and task names.
Hints
Hint 1
Two beats in a row come out shifted by one, but the last beat is right. What does the source do at the very edge where a beat is accepted?
Hint 2
The clocking event of mon_cb fires late in the time step, after the source’s nonblocking updates. Which values still show the bus as it was before the edge?
Hint 3
Every value the monitor uses should come from the same place as the handshake it just tested.
What this judge verifies: The monitor watches 24 runs of 20 cycles with directed and seeded random ready patterns. Passing shows it records the beat of each transfer on these runs.
25 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