Transitions
Cover sequences of values with transition bins, so the model can ask whether a handshake ever stalled, stalled twice, or went back to back.
- Lesson
- C4
- Time
- 25 min
- Runs on
- Coverage build
- Check
- 5 questions
A sink design lost data only when it stalled twice in a row and then accepted a packet. Every value of the handshake had been covered: idle cycles, waiting cycles and transfers all appeared thousands of times. Nobody had asked about the order in which they appeared, and the stimulus never produced two stalls in a row.
One column per rising edge. Each state value was common; this sequence of them never happened.
A coverpoint for the handshake
To cover the handshake, first turn it into one value per cycle. The example computes state: IDLE when valid is 0, WAIT when a packet is offered but ready is 0, and XFER when the packet moves.
A coverpoint on state with ordinary bins answers "did each state occur?". In the opening story the answer was yes for all three, which is why it gave no warning. The bug lived in the order of states, and ordinary bins cannot see order.
Turning several signals into one named state is a common first step when covering behaviour over time. It keeps the transition bins short, and their names read like the protocol description.
Transition bins
A transition bin is covered when the coverpoint takes a given sequence of values at consecutive samples. (IDLE => XFER) means one sample of IDLE immediately followed by one sample of XFER; (IDLE => WAIT => WAIT => XFER) is a sequence of four samples.
| Bin | Sequence of samples | Handshake meaning |
|---|---|---|
no_stall | IDLE => XFER | accepted at once |
one_stall | IDLE => WAIT => XFER | one cycle of backpressure |
two_stalls | IDLE => WAIT => WAIT => XFER | two cycles of backpressure, the opening story |
back2back | XFER => XFER | a new packet right after the last |
stall_after | XFER => WAIT | a stall straight after a transfer |
The transition bins in the example. Each one is a case the sink handles in its own way.
Which sequences to list comes from the design. This sink's buffer behaves differently after one stall, two stalls, or a stall straight after a transfer, so each is its own bin. A sink with a deeper buffer would need longer stall sequences.
A transition bin gets a hit each time its whole sequence completes, so a long test can hit it many times. Like a value bin, it is covered after the first hit.
Transitions work on any coverpoint, not only on enums. A bin such as (7 => 0) on a 3-bit counter checks that the counter really wrapped.
A transition can also start from a set of values: (IDLE, XFER => WAIT) is covered by IDLE then WAIT, or by XFER then WAIT.
Sample every cycle for transitions
Transitions are about consecutive samples, so the covergroup must be sampled once per cycle, including idle cycles. Here that is exactly what the clocking event @(posedge clk) does, and it is the opposite of the advice in lesson C2.
The difference is in what is being covered. Packet fields exist only during a transfer, so they are sampled on transfers. The handshake state exists in every cycle, so it is sampled in every cycle. If the state were sampled only on transfers, every sample would be XFER and no stall could ever be seen.
The values are driven on the falling edge and sampled at the rising edge, so they are stable when the covergroup reads them. Lesson C6 looks at sampling time in more detail.
Sampling every cycle has a cost: the covergroup runs on every edge of a long simulation. That is fine for a handful of transition bins, and one more reason to keep transition coverage small and focused.
Write each sequence out
The standard also allows shorthand for repeated values, such as WAIT [* 2] for two WAITs in a row, and arrays of transition bins, one per sequence. Writing each sequence out in full, with its own name, is clearer to read in a report and works on every simulator.
The example runs four phases of handshake, each adding one pattern of ready. Coverage climbs from 40% to 100% as each new sequence appears, and the report would name exactly which sequence is still missing.
Transition holes are often the hardest to close, because the stimulus must control timing, not just values. Here the sink's ready pattern decides which sequences occur, so closing a stall hole means changing the sink, not the packets.
Try it
Phase A transfers at once and then back to back: 2 of 5 bins. Phase B adds a single stall, phase C two stalls in a row, and phase D a stall straight after a transfer.
Delete phase C's call and predict the final percentage. Then think about what kind of sink would make phase C happen in a real random test.
phase A: 40.00% phase B: 60.00% phase C: 80.00% phase D: 100.00%Check yourself
Remember
- Value bins cannot see order; transition bins cover sequences of consecutive samples.
(a => b => c)is three samples in a row; a comma lists alternatives for one step.- Sample in every cycle when covering transitions of a value that exists in every cycle.
- Write each important sequence out as its own named bin.