Module 69 min

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

TypeQuestion it answersWho writes it
Code coverageDid our tests execute every line and branch of the RTL?Tool, automatically
Functional coverageDid 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

systemverilog
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.

Pro tip

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?"

Watch out

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.