Wishbone · Module 26
Monitors
Turning clocks into transactions. Emit on the presented clock instead of the completion and one transfer becomes fifteen — on a design with zero protocol violations. A broken observer indicts a correct design.
A bus has clocks. A scoreboard needs transactions. The monitor is what converts one into the other, and every mistake it can make looks exactly like a design bug to everything downstream.
A scoreboard is only as trustworthy as its observations. So this chapter builds the monitor, then audits it against a census computed independently of it.
1. Passive Means Passive
// the observed bus - INPUTS ONLY. This module has no outputs to the DUT.
input logic cyc_i,
input logic stb_i,The monitor has no output that reaches the design. That is not a style preference: an observer that can influence the thing it observes cannot be used to judge it, and a monitor that drives even a single signal has become part of the DUT.
2. The Transaction
Every field earns its place:
// ── THE TRANSACTION ─────────────────────────────────────────────────────
// Every field earns its place; none is decoration.
// adr which location sel which byte lanes
// we direction wdat what was written
// rdat what was read term ACK / ERR / RTY
// waits clocks presented unanswered - the endpoint's cost
// seq monotonic attempt number - makes ordering checkableterm and waits are the two most often omitted, and each omission destroys a different kind of evidence. Without term a failed access is indistinguishable from a successful one. Without waits the coverage model in Chapter 26.5 cannot tell a zero-wait transfer from a slow one — and that distinction is exactly where commit-timing bugs hide.
3. The Rule That Decides When To Emit
// ── THE RULE THAT DECIDES WHEN TO EMIT ──────────────────────────────────
// DO NOT EMIT A TRANSACTION MERELY BECAUSE [STB_O] IS HIGH.
//
// [STB_O] stays asserted across wait states - RULE 3.60 obliges the
// master to hold the whole request still - so a monitor that emits per
// presented clock reports one transfer as many. The DUT is fine; the
// observation is wrong.One line of RTL separates the correct monitor from the broken one:
logic emit;
assign emit = DUPLICATE_MONITOR ? present : (present && term);present is a request on the wire. present && term is an attempt finishing.
4. The Rule That Decides When To Sample
// RULE 3.65 "SLAVE interfaces MUST qualify the following signals with
// [ACK_O], [ERR_O] or [RTY_O]: [DAT_O()]."
//
// Read data is meaningful ON THE TERMINATION CLOCK and at no other time.
// Sampling a clock early does not read stale data - it reads something
// the slave was never required to be driving at all. logic [DW-1:0] rdat_q;
logic [DW-1:0] rdat_use;
assign rdat_use = EARLY_READ_SAMPLE ? rdat_q : rdat_i;Chapter 24.2 built the slave side of RULE 3.65. This is the observer side, and the failure mode is the same rule read from the other direction.
5. Attempts Are Not Transfers
// ── ATTEMPTS ARE NOT TRANSFERS ──────────────────────────────────────────
// B3's [RTY_I] description: "the interface is not ready... the bus cycle
// should be retried at a later time." A retry is a SEPARATE ATTEMPT.
//
// A monitor that merges a RTY with its later successful retry has
// destroyed the evidence that the first attempt happened - and with it
// any chance of noticing a design that retries forever. So this monitor
// emits one transaction PER ATTEMPT and carries the termination class."RTY is just a long wait state" is wrong, and the difference is observable. A wait state keeps the phase open; a RTY terminates it. Merging the two loses the fact that the bus was released and re-acquired — and with it any chance of measuring how often it happened.
6. The Monitor Trust Gate
The environment computes a raw pin census independently of the monitor, so the monitor can be audited rather than believed:
// ── the RAW pin census. Computed here, independently of the monitor,
// so §14's trust gate has something to compare the monitor against.Measured across three classes:
rig raw A/E/R monitor A/E/R txns
correct + RTY 4 1 1 4 1 1 6
LOST_TERM_CLASS 4 1 1 6 0 0 6 -> THE CORRECT MONITOR REPRODUCES ALL THREE CLASSES
EXACTLY: 4 ACK, 1 ERR, 1 RTY, matching the
raw pins in every column. The retry appears as
its own attempt, and the scoreboard counted 1
RTY observation(s) WITHOUT consuming an
expectation - the intended operation had not
happened yet.And look at LOST_TERM_CLASS: the transaction count is still right. A gate that only counted events would pass it. Only comparing the classes column by column catches it.
7. One Transfer, Reported Sixteen Times
rig raw ACK/ERR/RTY monitor A/E/R txns
correct 5 1 0 5 1 0 6
DUPLICATE_MONITOR 5 1 0 18 1 0 19 -> THE BROKEN ONE REPORTS 19 TRANSACTIONS FOR THE
SAME 6 COMPLETIONS. The DUT scored 0 protocol
failures - IT IS NOT WRONG. The observation is.THIS IS A TESTBENCH BUG, NOT A DUT BUG, and it is the reason the scoreboard reports mismatches on a design that is behaving perfectly. A failing scoreboard does not prove the DUT is wrong.
The downstream damage is visible as orphan observations — transactions arriving with no expectation behind them:
end else if (empty) begin
// an observation with no expectation behind it. A duplicate
// monitor produces these by the dozen.
nor_q <= nor_q + 16'd1;8. Right Count, Wrong Payload
EARLY_READ_SAMPLE emits at exactly the right moments and carries the wrong data:
rig mon txns sb data mm sb total SPEC
correct 6 0 0 0
EARLY_READ_SAMPLE 6 3 3 0 -> THE TRANSACTION COUNT IS IDENTICAL (6 and 6).
The broken monitor emits at the right moments and
carries the wrong payload, so a census-only check
passes it. Only comparing the DATA catches it:
3 data mismatches against 0.Three defects, three different detectors:
| monitor defect | census catches it? | class column? | scoreboard? |
|---|---|---|---|
DUPLICATE_MONITOR | yes — count differs | no | yes, as orphans |
LOST_TERM_CLASS | no — count identical | yes | yes, as term mismatches |
EARLY_READ_SAMPLE | no — count identical | no | yes, as data mismatches |
9. The Monitor Audits Its Own Fields
A transaction carrying an X is worse than no transaction, because every downstream comparison against it is unknown rather than false:
// a field is unknown if any bit of it is X or Z at emission
logic fields_unknown;
assign fields_unknown = (^adr_i === 1'bx) || (^sel_use === 1'bx)
|| (we_i === 1'bx)
|| (we_i && (^wdat_i === 1'bx))
|| (!we_i && (^rdat_use === 1'bx));That check earned its place during this module's own development. An early version of the coverage testbench read a memory location it had never written; the reads returned X, and the unknown-field counter is what identified it as a stimulus error rather than a design one.
MONITOR TRUST GATE, ALL RIGS
rig duplicates missing unknown fields
correct 0 0 0
DUPLICATE_MONITOR 13 0 0
EARLY_READ_SAMPLE 0 0 010. Where The Monitor Watches
The monitor in this environment observes the master port, alongside the protocol checker. That is a decision with consequences, and Chapter 26.2 measured them: a fault injected downstream of the observation point is invisible to everything watching upstream.
A monitor at the slave boundary would reconstruct a different transaction stream — one that includes whatever the fabric did to the request in between. Neither is more correct; they answer different questions, and a verification plan should say which one it is asking.
11. Debugging From Monitor Evidence
When a scoreboard fires, the monitor's census is the first thing to read, because it decides whether you are looking at a design problem at all.
| census reading | means | look at |
|---|---|---|
| monitor count greater than raw completions | duplicate emission | the emit condition |
| monitor count less than raw completions | missed emission | the emit condition, or a class the monitor ignores |
| counts equal, classes differ | misclassification | the termination decode |
| counts and classes equal, data differs | sampling clock, or a real DUT bug | RULE 3.65 qualification |
| any unknown field | the stimulus reached uninitialised state | the testbench, not the design |
The last row is not hypothetical. It is how this module found that its own coverage testbench was reading a memory location it had never written — six data mismatches that had nothing to do with the design.
Work outward: raw pins, then monitor census, then classes, then payload. Each step narrows which of the three models — design, observer, predictor — can still be the one that is wrong.
12. What A Monitor Cannot See
A passive observer on the master port is blind to a great deal, and knowing the list is part of using one:
- anything internal to a slave. A register that was written correctly and then corrupted by hardware looks identical on the bus.
- anything the fabric does downstream, unless a second monitor watches there.
- whether the transaction should have happened at all. The monitor reports what was asked; only the reference model knows what should have been.
- a value that is right by accident. A stale read that happens to match is indistinguishable from a correct one.
That last blind spot is why Chapter 26.5 insists on stimulus sensitivity rather than bin hits: an observation is only as discriminating as the data it was given to observe.
13. What This Chapter Did Not Build
- No transaction-level protocol. The analysis output is a pulse plus fields, not a class object; Chapter 26.6 shows where that becomes a
uvm_sequence_item. - No multi-master monitoring. One master port, one observer.
- No timestamping beyond
seq. A monotonic attempt number is enough to check ordering; wall-clock time is a debugging concern and Module 27 owns debugging. - No burst reconstruction. Classic phases only; a BLOCK cycle's phases would each be their own attempt.
Next: Chapter 26.4 — Scoreboards asks the question no checker and no monitor can answer: the transfer was legal and correctly observed — but was it right?
Continue learning
Related tutorials
- Related topic
The RTY Signal
RTY ends the transfer. It is not a wait state and not an error. One slave produces all three termination classes from a single resource condition, with the deferred write enqueuing nothing.
- Related topic
Read Logic
RULE 3.65 qualifies DAT_O with the termination, so everything the read caused is qualified too. Fire a FIFO pop on the presented clock instead and four words leave for one read — a write can be repeated, a popped word is gone.
- Related topic
CPU to Peripheral Communication
A CPU reaches hardware outside itself by reading and writing addressed locations, and a peripheral is hardware it cannot execute. Everything a driver does has to be expressed as a read or a write of a location the peripheral answers for — and once more than a couple of peripherals exist, wiring each one to the core separately stops scaling. That is the problem an on-chip bus is the answer to.
- Related topic
Memory-Mapped IO
Memory-mapped I/O does not turn a peripheral into memory. It gives the peripheral's registers addresses in the processor's address space, so an ordinary load or store selects them. The address then does two jobs — name the target, name the register inside it — and the map that assigns them is a contract between software and RTL.
Standards & specifications
- Governing standard
- Wishbone SoC Interconnection Architecture (OpenCores)(opens OpenCores in a new tab)
Defines the Wishbone signal set, the bus cycles built from it and the interface rules a portable IP core must follow. It deliberately leaves interconnect topology, address map and arbitration policy to the integrator, so those are system decisions rather than requirements of the specification.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Wishbone curriculum.
