Functional Coverage
covergroups, coverpoints, bins and crosses: measuring whether the tests exercised what the verification plan requires.
Random tests raise a question: what did they actually test? Functional coverage answers it. You describe the interesting values and combinations (from the verification plan) in a covergroup; the simulator counts which ones occurred. Verification is 'done' when the coverage goals are met and all tests pass.
A covergroup
bins short_len = {[1:4]} counts any length from 1 to 4 as one bin.
illegal_bins bad = {3} reports an error if kind ever takes the reserved value 3.
cross cp_kind, cp_len creates one bin per combination: 3 kinds x 4 length classes = 12.
cg.sample() records the current values; get_coverage() returns the percentage of bins hit.
Reading coverage (worked out by hand)
coverpoint data; // 32-bit field, automatic bins coverpoint data { bins zero = {0}; bins max = {'1}; bins others = default; }
Automatic bins on a wide field create up to 64 bins of huge ranges that say little. Define bins that match the verification plan.
What is the difference between code coverage and functional coverage?
Code coverage measures which parts of the RTL were executed and is collected automatically. Functional coverage measures whether the specified scenarios happened, using covergroups written by the verification engineer.
Why add cross coverage?
Individual coverpoints can be full while important combinations never occurred (e.g. every opcode and every operand type seen, but never a SUB with the maximum operand). Crosses count the combinations.