Part 5 · Functional Coverage · Intermediate
Weights, Goals & at_least
option.weight in the parent percentage math, option.goal, at_least hit thresholds, and type_option vs option.
option.weight — what the rollup percentage means
A covergroup's percentage is a weighted average of its coverpoints and crosses; a scope's percentage is a weighted average of its covergroups. option.weight (default 1) sets each element's share. Weighting lets the rollup reflect plan priority — and lets you remove bookkeeping coverpoints from the math entirely with weight 0.
covergroup proto_cg @(posedge clk iff txn_done);
cp_dir : coverpoint is_write { option.weight = 1;
bins rd = {0}; bins wr = {1}; }
cp_resp : coverpoint resp { option.weight = 3; // plan-critical
bins okay = {0}; bins exok = {1};
bins slverr = {2}; bins decerr = {3}; }
cp_id : coverpoint txn_id { option.weight = 0; // exists only to feed
bins ids[4] = {[0:15]}; } // the cross below
x_id_resp : cross cp_id, cp_resp { option.weight = 2; }
endgroupWorked rollup calculation
ELEMENT coverage weight contribution
─────────────────────────────────────────────────
cp_dir 100% 1 100 × 1 = 100
cp_resp 50% 3 50 × 3 = 150
cp_id 100% 0 excluded (w=0)
x_id_resp 25% 2 25 × 2 = 50
─────────────────────────────────────────────────
weight sum (counted) = 1 + 3 + 2 = 6
covergroup % = (100 + 150 + 50) / 6 = 50.0%
Unweighted (all w=1) the same numbers give:
(100 + 50 + 100 + 25) / 4 = 68.8%
Same simulation. 18.8 points apart. Weights ARE the policy.option.goal and option.at_least
option.goal (default 100) declares the target percentage at which an element is considered done — reports flag elements below their goal, and get_coverage() style queries can be compared against it. option.at_least (default 1) sets how many hits a bin needs before it counts as covered. One hit can be noise — a single accidental sample landing in a corner cell proves very little about whether the design handles that corner robustly.
covergroup err_cg @(posedge clk iff txn_done);
option.goal = 90; // plan accepts 90% on this group
cp_err : coverpoint err_kind {
option.at_least = 4; // a bin needs 4 hits to count
bins parity = {ERR_PARITY};
bins timeout = {ERR_TIMEOUT};
bins crc = {ERR_CRC};
}
endgroup
// With at_least = 4: parity hit twice -> bin still UNCOVERED.
// Forces stimulus to exercise each error repeatedly, not by luck.Why 1 hit may be noise
A corner cell hit once may have been hit on the only cycle where checking was masked — repeated hits make the evidence statistical.
Transition-heavy logic (FIFO full, arbitration loss) often misbehaves only on the Nth occurrence; at_least > 1 forces N occurrences.
at_least raises the closure bar — apply it to plan-critical points, not globally, or regressions stretch for little gain.
type_option vs option
Every knob so far was option.* — per-instance state, settable at runtime via the instance handle. type_option.* is the type-scoped sibling: one value shared by all instances of the covergroup type, settable only with constant expressions (elaboration time), controlling the type-level rollup.
PROPERTY option.* type_option.*
───────────────────────────────────────────────────────────────────
scope one instance the covergroup type
set when runtime OK elaboration constants
affects instance coverage type-level coverage
weight / goal / comment yes yes
at_least yes no (instance only)
per_instance yes no (meaningless)
merge_instances no yes (tool rollup mode)
typical use per-port name/weight type rollup policycovergroup cg @(posedge clk);
type_option.weight = 2; // this TYPE counts double in scope rollup
type_option.comment = "vplan section 4";
option.per_instance = 1; // instance-level knob
cp : coverpoint mode { bins m[] = {[0:3]}; }
endgroupInterview angle: "What is the difference between option and type_option?" is a stock question; the crisp answer is instance-scope-runtime vs type-scope-elaboration. The follow-up that separates candidates: "your group shows 100% inst coverage but the type number is lower — why?" (other instances of the same type are dragging the merged type view down, or type_option.merge_instances policy differs from what you assumed).
Key takeaways
weight sets each element's share of the parent percentage; weight 0 removes bookkeeping points from the math.
goal declares the done-threshold per element; at_least declares how many hits make a bin trustworthy.
One hit is weak evidence for corner behavior — raise at_least on plan-critical coverpoints.
option.* is instance-scope and runtime-settable; type_option.* is type-scope and elaboration-constant.
Common pitfalls
Leaving every weight at 1 — the rollup says all elements matter equally, which is almost never the plan's view.
Setting weight 0 on a coverpoint and forgetting it feeds a cross — the cross still works, but reviewers misread the report.
Global at_least = 10 on every point — closure time balloons with no added confidence on non-corner bins.
Trying to set type_option from a runtime variable — it requires constant expressions and fails at compile.