Tutorials
Protocols
Learn More
Functional Coverage
Before we start with functional coverage, it is required to understand the term coverage. The coverage provides a set of metrics that are used to measure verification progress.
Need for Coverage
- As you are aware that verification is a long-lasting process and we never know what type of input stimulus can capture the bug. Hence, it is essential to have a set of metrics that decide the endpoint for verification of the design once all metrics are satisfied.
- It is also essential to see whether we verified all kinds of features supported by the design and cover every line from the design code.
Types of Coverage
There are two types of coverage supported
- Code coverage
- Functional coverage
-
Code Coverage
Code coverage measures which RTL constructs were activated during simulation. It is useful for locating untested logic, but it does not prove that the observed behavior was correct. A faulty result can still receive coverage if the related code was executed.
Code coverage deals with covering design code metrics. It tells how many lines of code have been exercised w.r.t. block, expression, FSM, signal toggling.
Note:
- Code coverage does not specify that the code behavior is correct or not. It is simply used to identify uncovered lines, expressions, state transitions, dead code, etc. in the design. Hence, it does not indicate design quality.
- Verification engineers aim to achieve 100% code coverage.
- There are industry tools available that show covered and missing code in code coverage.
Common Code Coverage Metrics
Metric | What it measures | What an uncovered item may indicate |
Statement or block | Whether executable RTL statements or blocks ran. | Missing stimulus, disabled logic, or unreachable code. |
Branch | Whether every decision outcome, such as true and false, ran. | Only one side of an if, case, or conditional was selected. |
Condition or expression | Whether individual terms and meaningful expression results were exercised. | Input combinations needed to control the decision are missing. |
Toggle | Whether monitored bits changed from 0 to 1 and from 1 to 0. | A bit is constant, uninitialized, unused, or insufficiently stimulated. |
FSM | Whether states and recognized state transitions were visited. | A mode or legal transition was not exercised, or the path is unreachable. |
Understanding a Code Coverage Percentage
A percentage is calculated from covered items divided by eligible items for a selected metric and scope. A high total can hide a small but critical uncovered block, so engineers should review individual gaps instead of relying only on the overall number.
A target of 100% is useful only when every remaining gap is understood. Unreachable logic, unused configurations, defensive code, and deliberately excluded structures require documented review. Excluding a difficult item only to improve the percentage weakens the coverage result.
How to Investigate an Uncovered Item
- Confirm that the item belongs to the enabled design configuration.
- Trace the conditions required to reach or toggle it.
- Add directed or constrained-random stimulus when the behavior is legal.
- Review unreachable or dead code with the designer before excluding it.
Functional Coverage
Functional coverage deals with covering design functionality or feature metrics. It is a user-defined metric that tells about how much design specification or functionality has been exercised. The functional coverage can be classified into two types
- Data intended coverage – To check the occurrence of data value combinations.
Example: Writing different data patterns in a register. - Control intended coverage – To check the occurrence of sequences in the intended fashion.
Example: Reading a register to retrieve reset values after releasing a system reset.
Note:
Since it is user-defined metrics, it is up to the verification engineer to consider all features because if some features are missed to add in functional coverage and remaining features are covered then functional coverage will show up 100% even though some cover points are missed to add.
Coverage Does Not Check Correctness
Suppose a test writes every possible value to a register. The write-data coverpoint may reach 100%. If the testbench never checks the value stored by the register, the design can still contain a bug.
A good verification environment combines:
- Stimulus to create scenarios
- Scoreboards or reference models to check data
- Assertions to check rules and timing
- Functional coverage to measure planned behavior
- Code coverage to find unexercised RTL
Define a coverage model: covergroup
The covergroup is a user-defined construct that encapsulates coverage model specification. The covergroup construct can be instantiated multiple times in various contexts using the new() operator. A covergroup can be defined in a program, class, module, or interface.
The covergroup includes
- A set of coverage points
- Cross coverage between coverage points
- A clocking event that synchronizes coverage points sampling
- Coverage options
- Optional formal arguments
Basic covergroup syntax
covergroup <coverage model name>;
...
...
endgroup
<coverage model name> <covergroup inst> = new(); covergroup syntax with clocking event
covergroup <coverage model name> @(<clocking event>)
...
...
endgroup
<coverage model name> <covergroup inst> = new(); List of arguments in a covergroup
A covergroup can have an optional list of arguments and that has to be specified in the new operator too.
covergroup cg (<list of arguments>);
...
endcovergroup Functional Coverage