Part 5 · Functional Coverage · Intermediate
From Spec to Coverage Plan
Extracting coverable features from a spec, plan table structure, traceability naming conventions, and plan review before coding.
Extraction: reading a spec for coverable features
A coverage plan is a systematic transcription of the spec into measurable scenarios. Walk the spec with four extraction questions and a feature list falls out: what values can each field take (coverpoints), what combinations does logic act on together (crosses), what sequences must occur in order (transition bins or assertions), and what boundaries does the text call out — min, max, full, empty, wrap, timeout (corner bins).
SPEC SENTENCE COVERABLE FEATURE
─────────────────────────────────────────────────────────────────────
"Transfers of 1 to 16 beats cp_len bins: 1, [2:15], 16
are supported" (both boundaries named)
"WRAP bursts must be 2,4,8,16" illegal_bins for other lens
"A timeout aborts the transfer cp_state transition:
and returns the FSM to IDLE" (XFER => IDLE) on timeout
"QoS affects arbitration only cross cp_qos x cp_grant
when two masters contend" gated by contention
"The FIFO asserts full at 64" cp_occupancy bins: 0,63,64
(the boundary, both sides)Numbers in spec prose are coverage gold: every explicit constant is a boundary the design team special-cased, and boundaries are where bugs live.
The plan table
The plan is a table, one row per feature, written before the covergroups. Each row carries enough to implement the measurement and enough to audit it later.
COVERAGE PLAN TABLE (excerpt)
ID │ feature (spec ref) │ coverpoint/cross │ bins │ pri
───────┼───────────────────────────┼──────────────────┼─────────────────┼────
CV_LEN │ burst lengths (s7.2) │ cp_len │ 1,[2:15],16 │ P1
CV_WRP │ wrap legality (s7.2.1) │ cp_btype x cp_len│ illegal: wrap×1 │ P1
CV_TMO │ timeout recovery (s9.4) │ cp_fsm trans │ XFER=>IDLE │ P1
CV_QOS │ qos under contention(s8.1)│ x_qos_grant │ 8 named cells │ P2
CV_OCC │ fifo boundaries (s5.3) │ cp_occ │ 0,63,64 │ P1
CV_RSV │ reserved encodings (s3.9) │ cp_op │ ignore: [12:15] │ P3
columns: ID — stable handle, referenced from code comments and reports
feature — one sentence plus the spec section it transcribes
coverpoint/cross — the implementing construct, by name
bins — the buckets, including planned illegal/ignore
priority — drives weights, closing order, and waiver scrutinyTraceability naming conventions
Plan IDs are stable and boring: CV_<AREA>_<NN> or F-042 style — never renumber, only append.
Covergroup elements carry the ID in a comment on the same line as the bin they implement.
option.comment on the covergroup names the plan section it serves — the report then self-documents.
Bin names echo the feature, not the value: bins timeout_recovery, not bins b3 — reports are read by people who did not write the code.
covergroup dma_cg @(posedge clk iff desc_done);
option.comment = "coverage plan CV_LEN, CV_WRP — spec s7.2";
cp_len : coverpoint blen { // CV_LEN
bins one = {1}; // CV_LEN: lower boundary
bins mid = {[2:15]}; // CV_LEN: interior
bins max_len = {16}; // CV_LEN: upper boundary
}
x_wrap : cross cp_btype, cp_len {
illegal_bins wrap_bad = binsof(cp_btype.wrap) &&
binsof(cp_len.one); // CV_WRP: spec s7.2.1
}
endgroupPlan review — before any covergroup is coded
The plan is reviewed as a document, with the spec open, before implementation. Reviewing a finished covergroup conflates two questions — is the intent right, and is the code right — and intent mistakes found late invalidate regression data already collected.
Plan review checklist
Walk the spec section by section: does every must/shall/only sentence have a plan row or a written reason it does not?
Are boundary values from spec prose present as named bins (not buried in ranges)?
Is every cross justified by logic that actually examines the fields together?
Are priorities assigned, and do P1 rows cover the features whose failure is unshippable?
Are planned illegal/ignore bins listed in the plan — pruning decided up front, not improvised at 87%?
Can each row be measured from observable signals, or does it need DUT instrumentation that must be requested now?
Interview angle: "How do you build a coverage model for a new block?" is screening for process, not syntax. The senior shape: read the spec extracting values/combinations/sequences/boundaries, write the plan table with IDs and priorities, review the table against the spec with the designer present, then implement with IDs traced in comments. Starting the answer with covergroup syntax is the junior tell.
Key takeaways
Extract features by asking four questions of the spec: values, combinations, sequences, boundaries.
The plan is a table — ID, feature with spec reference, implementing construct, bins, priority — written before code.
Traceability is mechanical: stable IDs in plan, echoed as comments at the implementing bins, named for humans.
Review the plan as a document against the spec before coding; intent bugs found late cost regression data.
Common pitfalls
Writing covergroups first and reverse-engineering a plan for the review — the model covers what was easy, not what matters.
Plan rows without spec references — unverifiable during review, unauditable at sign-off.
Burying spec-named constants inside range bins — the boundary the designer special-cased gets no dedicated evidence.
Skipping designer involvement in the plan review — designers know which combinations share logic, which is exactly the cross list.