Functional Coverage
Measuring whether you actually tested enough
Random tests throw inputs at the design - but did they actually hit the situations that matter? Coverage answers that. It is a scoreboard of "which interesting cases have we seen?" Without it, you are testing blind and only guessing when to stop.
Two kinds of coverage
| Type | Question it answers | Who writes it |
|---|---|---|
| Code coverage | Did our tests execute every line and branch of the RTL? | Tool, automatically |
| Functional coverage | Did we hit the scenarios the spec cares about? | You, on purpose |
Code coverage is free but shallow - running a line is not the same as testing it meaningfully. Functional coverage is the one verification engineers craft by hand, because only a human knows which scenarios are worth checking.
A covergroup - your scenario checklist
class Packet;
rand bit [7:0] addr;
rand bit [1:0] kind; // 0=read 1=write 2=burst
covergroup cg;
// Did we see low, middle, and high addresses?
coverpoint addr {
bins low = {[0:63]};
bins mid = {[64:191]};
bins high = {[192:255]};
}
// Did we see every kind of transaction?
coverpoint kind {
bins read = {0};
bins write = {1};
bins burst = {2};
}
endgroup
function new(); cg = new(); endfunction
endclass
// Coverage is only recorded when you ASK for it. After each new packet,
// call p.cg.sample() to capture the current addr/kind into the bins:
// p.randomize();
// p.cg.sample(); // <- without this, every bin stays at 0%Each bin is a box to tick. The key step beginners miss: a covergroup records nothing on its own - you must call sample() after each new packet (see the comment above). Do that for thousands of randomized packets and the tool reports which bins were hit. If "high addresses" or "burst" stayed at zero, you know a whole scenario went untested - even though the tests ran without error.
Coverage closes the loop. Run random tests, read the coverage report, find the empty bins, then add or tighten constraints to steer the randomizer into those cases. This loop - randomize, measure, steer - is the daily rhythm of a verification engineer, and the honest answer to "are we done yet?"
100% coverage does not mean zero bugs. It means you exercised the scenarios you thought to write down. If you never wrote a bin for a scenario, full coverage will still happily ignore it. Coverage is only as good as the cover plan behind it.