Part 5 · Functional Coverage · Intermediate
Cross Coverage Patterns
Classic intent crosses — opcode×operand corner, burst×length×alignment, state×event, error×recovery — and a worked spec-to-cross example.
Four patterns that cover most real crosses
Most production crosses are instances of a small number of patterns. Recognizing the pattern tells you which coverpoints to build, how coarse the bins should be, and which cells to prune.
The pattern catalog
Opcode × operand-corner — does every operation handle the special values (zero, max, negative-min)? Drives ALU/FPU bugs out.
Burst-type × length × alignment — does every transfer shape meet every address alignment? Drives interconnect/DMA bugs out.
State × input-event — was every input observed in every state where it is legal? Drives FSM bugs out.
Error-type × recovery-path — was every error seen down every recovery route? Drives error-handling bugs out.
// PATTERN 1: opcode x operand-corner
covergroup alu_cg @(posedge clk iff op_valid);
cp_op : coverpoint opcode { bins arith[] = {OP_ADD, OP_SUB, OP_MUL, OP_DIV}; }
cp_b : coverpoint operand_b {
bins zero = {0};
bins max = {32'h7FFF_FFFF};
bins min = {32'h8000_0000};
bins mid = default;
}
x_op_corner : cross cp_op, cp_b {
// div-by-zero is the plan's #1 corner: keep it as its own bin
bins div_zero = binsof(cp_op) intersect {OP_DIV} && binsof(cp_b.zero);
}
endgroup
// PATTERN 3: state x input-event
covergroup fsm_cg @(posedge clk);
cp_state : coverpoint ctrl_state { bins s[] = {IDLE, BUSY, DRAIN}; }
cp_evt : coverpoint event_in { bins e[] = {EV_REQ, EV_ABORT, EV_TIMEOUT}; }
x_se : cross cp_state, cp_evt {
// spec: ABORT is ignored in IDLE — impossible to observe an effect
ignore_bins idle_abort = binsof(cp_state.s) intersect {IDLE} &&
binsof(cp_evt.e) intersect {EV_ABORT};
}
endgroupWorked example — from spec table to cross
The strongest coverage models are transcriptions of a spec table. Here is a DMA burst table and the cross it becomes — every spec cell maps to a cross cell, and the spec's forbidden cells become pruning.
SPEC TABLE 7-2: supported burst shapes (DMA controller)
burst type │ len 1 │ len 2-8 │ len 9-16 │ unaligned addr
───────────┼───────┼─────────┼──────────┼────────────────
INCR │ yes │ yes │ yes │ yes
WRAP │ NO* │ yes │ pow2 │ NO*
FIXED │ yes │ yes │ NO* │ yes
(*) = forbidden by spec section 7.2 → illegal, not ignored
MAPPING
spec column "burst type" → cp_btype (3 bins)
spec column "len" → cp_len (3 bins)
spec column "unaligned" → cp_align (2 bins)
full product 3×3×2 = 18 cells
spec-forbidden cells → illegal_bins (runtime check)
pow2-only WRAP lengths → handled in cp_len bin shapingcovergroup dma_cg @(posedge clk iff desc_done);
cp_btype : coverpoint btype { bins incr = {INCR}; bins wrap = {WRAP};
bins fixed = {FIXED}; }
cp_len : coverpoint blen { bins l1 = {1}; bins l2_8 = {[2:8]};
bins l9_16 = {[9:16]}; }
cp_align : coverpoint addr[1:0] { bins aligned = {0}; bins unalign = {[1:3]}; }
x_shape : cross cp_btype, cp_len, cp_align {
// Spec 7.2 forbidden cells -> runtime checks
illegal_bins wrap_len1 = binsof(cp_btype.wrap) && binsof(cp_len.l1);
illegal_bins wrap_unal = binsof(cp_btype.wrap) && binsof(cp_align.unalign);
illegal_bins fixed_long = binsof(cp_btype.fixed) && binsof(cp_len.l9_16);
}
endgroupWhy this transcription discipline pays
Reviewability — a reviewer can hold the spec table next to the cross and verify cell-for-cell.
Traceability — each illegal_bins comment cites the spec section; sign-off audits become mechanical.
Hole triage speed — any empty cell maps straight to a spec row, so 'is it reachable?' is answered by the table.
Change resilience — when the spec table gains a row, the diff to the covergroup is obvious and local.
Interview angle: "Design a coverage model for this burst table" is a common whiteboard task. The winning move is to map columns to coverpoints, state the product size out loud (3×3×2 = 18), convert the spec's 'NO' cells into illegal_bins, and say which remaining cells you would name explicitly because the plan ranks them highest. That demonstrates pattern fluency, not just syntax.
Key takeaways
Most useful crosses are one of four patterns: op×corner, shape×alignment, state×event, error×recovery.
Transcribe spec tables cell-for-cell — columns become coverpoints, forbidden cells become illegal_bins.
Name the plan-critical cells as explicit cross bins so reports surface them by name.
A cross a reviewer can check against the spec in one sitting is worth more than an exhaustive one nobody audits.
Common pitfalls
Inventing crosses bottom-up from available signals instead of top-down from spec tables.
Translating a spec 'NO' cell into ignore_bins — a forbidden behavior deserves a runtime check, not silence.
Burying the one plan-critical combination inside an anonymous auto product — name it.
Letting the coverage model drift after a spec table changes — re-diff the table against the cross every spec revision.