Tutorials

Protocols

Learn More

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

  1. 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.
  2. 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

  1. Code coverage
  2. 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:

    1. 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.
    2. Verification engineers aim to achieve 100% code coverage.
    3. 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

    1. Data intended coverage – To check the occurrence of data value combinations.
      Example: Writing different data patterns in a register. 
    2. 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.
    In simple words, it answers:
    “Did our tests try all the cases that we planned to verify?”
     
    Functional coverage does not prove that the design is correct. It helps us find missing tests and untested corner cases.
     

    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:

    1. Stimulus to create scenarios
    2. Scoreboards or reference models to check data
    3. Assertions to check rules and timing
    4. Functional coverage to measure planned behavior
    5. 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

    1. A set of coverage points
    2. Cross coverage between coverage points
    3. A clocking event that synchronizes coverage points sampling
    4. Coverage options
    5. 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