Code Coverage Fundamentals

Code Coverage Fundamentals

Coverage is a metric to assess the progress of functional verification activity. This plays a major role to get a clear picture on how well the design has been verified and also to identify the uncovered areas in verification.

Code coverage and functional coverage are the two types of coverage methods used in functional verification.

Code coverage is a basic coverage type which is collected automatically. It tells you how well your HDL code has been exercised by your test bench. In other words, how thoroughly the design has been executed by the simulator using the tests used in the regression.

Functional coverage measures how well the functionality of the design has been covered by your test bench. In functional coverage user has to define the functionality to be measured through coverage.

There are different categories of code coverage.

  • Statement coverage
  • Block coverage
  • Conditional/Expression coverage
  • Branch/Decision coverage
  • Toggle coverage
  • FSM coverage

Statement Coverage /Line Coverage: This gives an indication of how many statements (lines) are covered in the simulation, by excluding lines like module, endmodule, comments, timescale etc. This is important in all kinds of design and has to be 100% for verification closure. Statement coverage includes procedural statements, continuous assignment statements, conditional statement and Branches for conditional statements etc.

always @(posedge clock) begin if(x == y) begin => Statement 1 out1 = x+y; => Statement 2 out2 = x^2 + y^2; => Statement 3 else => Statement 4 out1 = x; => Statement 5 out2 = y; => Statement 6 end

Block coverage: A group of statements which are in the begin-end or if-else or case or wait or while loop or for loop etc. is called a block. Block coverage gives the indication that whether these blocks are covered in simulation or not. The nature of the block coverage & line coverage looks similar. Block coverage looks for a group of statements called block and line coverage/statement coverage checks whether each statement is covered. The dead-code in design code can be found by analyzing block coverage.

always @(posedge clock) begin => Block 1 [always block] if(x == y) begin => Block 2 [If block] out1 = x+y;
out2 = x^2 + y^2;
else => Block 3 [Else block] out1 = x;
out2 = y;
end

Conditional/Expression Coverage: This gives an indication how well variables and expressions (with logical operators) in conditional statements are evaluated. Conditional coverage is the ratio of number of cases evaluated to the total number of cases present. If an expression has Boolean operations like XOR, AND ,OR as follows, the entries which is given to that expression to the total possibilities are indicated by expression coverage.

out = (x xor y) or (x and z);

In this example, tool analyzes the RHS of the expression and counts how many times it has been executed.All the possible cases would be available as truth table and uncovered expression can be easily identified from the table.

Branch/Decision Coverage : In Branch coverage or Decision coverage reports, conditions like if-else, case and the ternary operator (?: ) statements are evaluated in both true and false cases.

always @(posedge clock) begin
if(x == y) begin => Branch [If branch] out1 = x+y;
out2 = x^2 + y^2;
else => Branch [Else branch] out1 = x;
out2 = y;
end

Toggle Coverage: Toggle coverage gives a report that how many times signals and ports are toggled during a simulation run. It also measures activity in the design, such as unused signals or signals that remain constant or less value changes.

State/FSM Coverage: FSM coverage reports, whether the simulation run could reach all of the states and cover all possible transitions or arcs in a given state machine. This is a complex coverage type as it works on behaviour of the design, that means it interprets the synthesis semantics of the HDL design and monitors the coverage of the FSM representation of control logic blocks.

By default, every tool disables the code coverage and user can do as per the need. Enabling code coverage is overhead for simulation. So it is recommended not to enable code coverage during your test development, and do it during your regression run only.

To enable code coverage in Incisive, give -coverage all option to irun. You can also specify which type is required as follows -coverage block:fsm

Limitations of Code Coverage: Code coverage is an important indication for the verification engineer on how well the design code has been executed by the tests. But it does not know anything about the design and what the design is supposed to do. There is no way to find what is missing in the RTL code, as code coverage can only tell quality of the implemented code.

1. Non-implemented features cannot be identified. Missing feature cannot be identified by code coverage as it only look into design code and does not know the functionality of the design.

2. Not possible to indicate whether all possible values of a feature are tested. For example code coverage cannot report whether all legal combination of states are executed by the tests. Another example is, generate packets using randomization with all possible lengths. code coverage cannot identify whether all possible lengths are evaluated in simulation or not.

3. Unable to say how well the logic has been covered, it can only say whether each statement/block etc has been executed

4. Code coverage does not look into the sequences of events which is happened before, after or during the line of code has been executed.

Hence code coverage does not ensure verification completeness. Both functional coverage and code coverage have to be 100% to make verification closure.

Code coverage and Functional coverage comparison cov_comparison

Which is important - Functional or Code Coverage? Code coverage is a measure of quality of RTL code execution while simulating the test-cases. Functional coverage measure how well the design functionality have been covered by the tests during simulation. That means it is an indicator of design's functional state. Functionality is defined using coverage groups and points. The functional coverage metric is very subjective, so to improve the quality of functional coverage report, quality of functional coverage points and its implementation have to be improved.

So both code coverage and functional coverage are equally important in verification. That means, even if you have 100% code coverage, but functional coverage is not 100%, verification is not complete. If you have 100% functional coverage without 100% code coverage, either you have unnecessary code lying around or functional coverage is measured wrong.

Verification completeness can be achieved with proper functional coverage goals and also with 100% code & functional coverage.