General Questions on Coverage:
In short: This is a set of the most common coverage interview questions with clear, LRM-correct answers: code vs functional coverage, the code-coverage types, what high-one-low-other numbers mean, covergroups vs cover properties, coverpoints and bins, ignore vs illegal bins, transition and wildcard bins, cross coverage, and the two ways to sample a covergroup.
Coverage comes up in almost every verification interview. These questions, drawn from functional coverage practice, test whether you understand not just the syntax but what the numbers actually mean. Each answer includes a short example you can reason about.
A simple way to picture it
Think of coverage like grading a school syllabus. Code coverage is the automatic attendance sheet: which pages of the textbook were opened. Functional coverage is the teacher’s exam plan: which topics were actually tested. Bins are the individual questions, cross coverage is checking that two topics were tested together, and ignore or illegal bins are questions you deliberately skip or forbid. High attendance with a thin exam means little was truly assessed.
Code coverage vs functional coverage
Code coverage measures how much of the HDL was exercised by the tests and is extracted automatically by the simulator. Functional coverage is a user-defined metric that measures how much of the specification, as captured in the test plan, was exercised. Code coverage depends on the RTL; functional coverage depends on the spec.
Types of code coverage
- Statement / line: how many lines ran; usually targeted at 100 percent for closure.
- Block: whether each group of statements (begin-end, if, else, case, loop body) ran.
- Branch / decision: whether both true and false outcomes of each decision happened.
- Condition / expression: whether the meaningful rows of a Boolean expression truth table were seen.
- Toggle: whether each signal switched both 0 to 1 and 1 to 0.
- FSM: whether every state and every legal transition was covered.
What high one, low other tells you
High functional, low code often means there is dead code not used by the implemented features, or the functional coverage or test plan is missing scenarios that map to the untested code, or there are bugs in the coverage monitors reporting false hits.
High code, low functional often means not all specified functionality is implemented, or the functional coverage monitors have bugs so they never register, or tests for those features exist but are failing and excluded from the measurement.
Covergroups vs cover properties
SystemVerilog offers two constructs. A covergroup measures how often a value or set of values occurs for a signal or expression, and can measure combinations through cross coverage. Like a class, it is defined once and instantiated with new(), and can live in a package, module, program, interface, checker, or class. A cover property measures occurrences of a sequence of events over time, using the same temporal syntax as assertions.
// A covergroup sampled on a clock
covergroup cg_req @(posedge clk);
cp_type: coverpoint req_type;
endgroup
// A cover property over time
c_btb: cover property (@(posedge clk) req ##1 req);Coverpoints and bins
A coverpoint specifies an integral expression to be covered. A covergroup can have many coverpoints. Each coverpoint holds a set of bins, which are the sampled values being tracked. Bins can be defined explicitly by you or created automatically by the language.
bit [2:0] x;
bit [3:0] y;
covergroup cg @(posedge clk);
cp_x: coverpoint x {
bins values_x = {0, 1, 3, 5, 7}; // explicit bins
}
cp_y: coverpoint y; // automatic bins
endgroupHere cp_x uses an explicit bin set, while cp_y lets the tool create bins automatically for every value of y.
How many bins? a classic question
Given the coverpoint below, how many bins are created?
bit [3:0] var_x;
covergroup test_cg @(posedge clk);
cp_x: coverpoint var_x {
bins low_bins[] = {[0:3]}; // array of bins
bins med_bins = {[4:12]}; // single bin
}
endgroupThe low_bins[] array form makes a separate bin for each value 0, 1, 2, 3, so four bins. The med_bins form makes one bin that hits on any value from 4 to 12. Total: five bins.
ignore_bins vs illegal_bins
ignore_bins excludes a set of values or transitions from coverage; they simply do not count. illegal_bins marks values or transitions as illegal, and hitting one causes a runtime error. Illegal bins take precedence, so a value marked illegal errors even if it also appears in another bin.
coverpoint x {
ignore_bins ig = {7, 8}; // excluded from coverage
}
coverpoint y {
illegal_bins bad = {1, 2, 3}; // runtime error if hit
}Transition and wildcard bins
Transition coverage is written as value1 => value2, checking two successive sampled values. A shorthand across a set expands to every combination.
coverpoint v_x {
bins sa = (4 => 5 => 6); // one specific path
}
coverpoint my_var {
bins t[] = (a, b, c => x, y); // expands to a=>x, a=>y, b=>x, b=>y, c=>x, c=>y
}A wildcard bin treats X, Z, or ? as a wildcard for 0 or 1, so one bin can match a range of bit patterns.
coverpoint a[3:0] {
wildcard bins hi = {4'b11??}; // matches 1100, 1101, 1110, 1111
}The consecutive repetition inside a bin, such as {3[*4]}, covers the value 3 seen on four successive sample points.
Cross coverage
Cross coverage measures combinations of two or more coverpoints, the Cartesian product of their bins. It is how you confirm that events happened together, not just individually. Cross is only allowed between coverpoints in the same covergroup.
bit [31:0] a_var;
bit [3:0] b_var;
covergroup cov3 @(posedge clk);
cp_a: coverpoint a_var { bins yy[] = {[0:9]}; } // 10 bins
cp_b: coverpoint b_var; // 16 bins
cc_ab: cross cp_a, cp_b; // 10 x 16 = 160 bins
endgroupTwo ways to sample a covergroup
First, attach a clocking event to the covergroup, so all its coverpoints sample when that event fires. Second, call the built-in sample() method explicitly, which suits covergroups inside classes where you sample only when a new transaction arrives rather than on every clock edge.
class packet;
byte dest_addr [4];
covergroup pkt_cg;
coverpoint dest_addr[0];
endgroup
function new();
pkt_cg = new();
endfunction
endclass
// ... later, when a packet is built:
// pkt.pkt_cg.sample();Per instance vs per type
By default SystemVerilog reports a covergroup cumulatively across all its instances, which is coverage per type. Set option.per_instance = 1 inside the covergroup to report each instance separately. For the full set of reporting controls, see functional coverage options.
Expected output, in plain words
Each covergroup reports how many of its bins were hit versus the total, per instance or per type; illegal bins raise a runtime error when hit, and ignored bins never count. Note: this describes intended behaviour from the IEEE 1800 rules, not a captured simulator run, and report formats vary by tool. Confirm on your own simulator.
For related reading see types of coverage metrics, the writing functional coverage guidelines, and functional coverage options. More in the interview questions, functional coverage, and SystemVerilog categories.
Frequently asked questions
What is the difference between code coverage and functional coverage?
Code coverage measures how much of the HDL was exercised by tests and is extracted automatically by the simulator. Functional coverage is a user-defined metric that measures how much of the specification, captured in the test plan, was exercised. Code coverage depends on the RTL, functional coverage on the spec.
What are covergroups and cover properties?
A covergroup measures how often a value or set of values occurs for a signal or expression and supports cross coverage. A cover property measures occurrences of a sequence of events over time using the same temporal syntax as assertions.
What is the difference between ignore_bins and illegal_bins?
ignore_bins excludes values or transitions from coverage so they do not count. illegal_bins marks values or transitions as illegal, and hitting one causes a runtime error. Illegal bins take precedence over any other bin.
How many bins does bins low_bins[] = {[0:3]} create?
The array form bins low_bins[] = {[0:3]} creates a separate bin for each value 0, 1, 2, and 3, so four bins. A non-array bin like bins med_bins = {[4:12]} creates one bin for the whole range.
What is cross coverage and when is it useful?
Cross coverage measures combinations of two or more coverpoints, the Cartesian product of their bins. It confirms that events happened together, not just individually, and is only allowed between coverpoints in the same covergroup.
What are the two ways to sample a covergroup?
You can attach a clocking event to the covergroup so it samples when the event fires, or you can call the built-in sample() method explicitly. The explicit method suits covergroups in classes, sampled when a new transaction arrives.



nicely explained. Good luck!!
Thanks Hitesh π