Your regression is green: ten thousand
The declaration mirrors the assertion machinery: you write what matters, the simulator tallies it. A covergroup samples signals at an event (usually a clock edge); each coverpoint watches one expression; its bins partition the values into the cases you care about:
Each bin is a little odometer: "how many times did a subtraction happen?", "how many times was an
operand zero?". An illegal_bins is a tripwire — sampling it fails the test outright.
And the cross is where the real power lives: it counts
combinations — did we ever subtract from zero? AND with a big operand? Bugs
overwhelmingly hide at the intersections of features ("the FIFO was full while an error
arrived during a flush"), which no single coverpoint can see. Crossing an
Coverage turns verification into a feedback loop with a name — coverage closure: run the regression; read the coverage report; find the holes (bins at zero); write or steer tests to hit them (new constraints, new directed tests, new seeds); repeat until every bin is hit or consciously waived. The curve it produces is one of the most recognisable shapes in the industry:
Random stimulus sprints through the easy scenarios — the first hundred tests buy more coverage than the next ten thousand — then stalls: some bins are simply too improbable to hit by luck (the FIFO-full-during-error cross might need a one-in-a-billion coincidence). Those last bins are hit by aiming: tightening constraints around the hole, or writing an old-fashioned directed test. The plateau is not failure; it is the report telling you where imagination must take over from dice.
A coverage collector is honestly just a map of counters. Watch one discover a hole — and watch the hole persist until the stimulus is steered:
Five thousand aimless tests lose to two hundred aimed ones — the closure loop in miniature. The report told us which scenarios were missing; the fix was a constraint making zero operands likely; the holes closed.
Tools also report code coverage for free: which RTL lines executed, which branches both ways, which signal bits toggled. It is necessary — an unexecuted line is untested by definition — but shallow: code coverage measures the design as written, not the intent. Every line of a FIFO can execute without ever testing "full and empty in the same microsecond" — a scenario, not a line. Functional coverage measures scenarios; code coverage catches the parts of the design your scenario list forgot even to mention. You need both, and neither is sufficient.
So when is verification done? Here is the uncomfortable truth this course will repeat at
tape-out: it is never done — it is risk management. There is no proof at the end
of simulation, only evidence: functional coverage closed, code coverage explained, regressions
clean across thousands of seeds,
illegal_bins tripwires);Functional coverage quietly revolutionised how chip projects are run. Before it, verification status was vibes: "we feel good about the cache". After it, a project has a coverage dashboard — thousands of bins rolled up into percentages per block, trending week by week — and tape-out reviews walk the numbers: which holes remain, which are waived and why, whose signature is on each waiver. The waiver list is the fascinating part: a hole can be legitimately unhittable ("this error type cannot occur with this bus configuration"), and writing that sentence down forces someone to prove it, which has itself found bugs. The dashboard also produces verification's best-known career wisdom: the engineer who closes the last 2% of coverage learns more about the design than the person who wrote it.
Coverage measures your tests against your coverage model — the bins you chose to declare. It cannot see scenarios you never wrote down: forget a coverpoint for back-to-back writes and the report gleams at 100% while that scenario goes untested into silicon; nobody counts a bin that doesn't exist. And coverage says nothing about checking: a bench with a broken scoreboard can hit every bin — every scenario exercised, none of them actually verified — and a green 100% dashboard crowns the whole illusion. Coverage measures the completeness of your test plan's execution, never the correctness of the design. The mature reading of "100% coverage, zero failures" is precisely: "every scenario we thought of was exercised, and our checkers — as good as they are — stayed quiet". Both italicised clauses are load-bearing, and both are exactly where the escaped bugs will have lived.