Day 103: Functional coverage: crosses and coverage options
Functional coverage: crosses and options
Single coverpoints miss *interactions*. A cross of two coverpoints tracks their combinations — e.g. every ALU op × every operand-sign combination, or every burst length × every alignment. Crosses are where subtle bugs hide (an op that works for positives but not negatives). Coverage options (option.weight, illegal_bins, ignore_bins) refine what counts and flag combinations that must never occur.
covergroup cg_alu @(posedge clk);
cp_op: coverpoint op { bins ops[] = {[0:9]}; } // all 10 ALU ops
cp_sa: coverpoint a[31] { bins pos = {0}; bins neg = {1}; } // sign of a
cp_sb: coverpoint b[31] { bins pos = {0}; bins neg = {1}; }
x_op_signs: cross cp_op, cp_sa, cp_sb; // every op x every sign combo
// e.g. mark an impossible/uninteresting combination
// ignore_bins skip = binsof(cp_op) intersect {reserved_op};
endgroupillegal_bins are assertions in disguise
An `illegal_bins` entry *fails the simulation* if that combination is ever sampled — a coverage-flavored assertion for 'this must never happen'. `ignore_bins` simply excludes impossible combinations from the coverage denominator so your closure target is achievable. Using both keeps your coverage number honest and meaningful.
Key terms
- Cross coverage
- Tracking the combinations of two or more coverpoints, exposing interaction bugs.
- illegal_bins
- A bin whose sampling flags an error — a must-never-happen combination.
- ignore_bins
- A bin excluded from coverage (impossible/uninteresting), keeping closure achievable.
- Coverage option
- Settings (weight, at_least, goal) tuning how coverage is scored.
Before moving on, you should be able to
Why is cross coverage important beyond individual coverpoints?