Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Quick Start: Your First Green Build
  • Part 1: How Chips Get Made6
  • Part 2: Your Workstation5
  • Part 3: Specify and Architect3
  • Part 4: The Design Loop6
  • Part 5: The Verification Ladder6
    • Tests That Can Fail
    • Self-Checking and Golden Model
    • Random Stimulus and Seeds
    • Assertions
    • Coverage
    • Formal in One Lesson
  • Part 6: Automation and Reproducibility5
  • Part 7: Hand-Off to the Back-End3
  • Part 8: When Things Go Wrong3
  • Part 9: Project and Next Steps3
  • Reference4
Loading lesson

‹Part 5: The Verification Ladder
  1. Topics
  2. Start Here: RTL and Verification
  3. Part 5: The Verification Ladder
  4. Coverage

Part 5 · The Verification Ladder · Working (W)

Coverage

Your tests pass, but what did they never try? Count the situations each run reached, name the holes, and close the rare corners with directed cases.

On this page

    Note

    Level: Working (W) · Answers: Your tests pass. How do you know what they never tried?

    Before this: Assertions

    Your tests pass. How do you know what they never tried?

    Your testbench is green. Every check you wrote agrees with the design. That feels like the end of the story, and part of you wants to move on.

    But a green run tries only the inputs it contains. Tests That Can Fail showed a passing test on a broken design: the inputs that would have exposed the bug were never driven. This lesson counts what your tests actually reached, so the untried inputs stop hiding.

    Coverage counts reached situations, not correct behavior

    Functional coverage counts the situations your tests reached. For the course counter the situations are eight input combinations of reset, clear and event, plus four events from the spec: the count reaching 15, the wrap from 15 to 0, reset arriving while the count is nonzero, and holding a nonzero count through an idle cycle.

    A hole is a situation no test reached. Holes matter because an untried situation can hide any bug. If reset never arrives while the count is nonzero, a broken reset priority passes every run, which is exactly the blind spot lesson 5.1 measured.

    Code coverage is the other kind. It counts lines and branches the simulator executed, and it appears in this lesson only in words. It answers a weaker question: every line of a small counter runs within a few cycles, yet the wrap from 15 to 0 may never happen. The lines ran; the situation that matters did not.

    Three runs leave different holes

    The figure below puts all three runs of this lesson side by side, measured on macOS, Icarus Verilog 13.0. Columns are the runs: directed only, with 400 random cycles added, and with reset and clear made rarer. Rows are the twelve situations: the eight input combinations written as {reset, clear, valid}, then the four counter events. Each cell shows how many times the run reached that situation, and a cell marked none is a hole.

    What each run reached, measured on macOS, Icarus Verilog 13.0. Read the directed column first, then watch random cycles fill the common rows while 010 and 011 stay empty.

    Two patterns already show. Random cycles fill the common combinations and leave the rare corners. The last two rows move only when reset stays away long enough for the count to climb.

    A testbench that counts what it reaches

    The listing below is the complete experiment: the course counter followed by a testbench that counts reached situations instead of only checking outputs. The testbench drives seven directed cycles, then adds 400 random cycles when the run flag +random is present, and makes reset and clear rarer when +rare is present.

    mini_controller.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    `timescale 1ns/1ps
    // Counts accepted events, 4 bits, wraps 15 -> 0.
    // Priority: reset > clear > count > hold. Reset is synchronous, active low.
    module mini_controller (
        input  logic       clk,
        input  logic       rst_n,
        input  logic       event_valid,
        input  logic       clear_count,
        output logic [3:0] count
    );
        always_ff @(posedge clk) begin
            if (!rst_n)
                count <= 4'd0;
            else if (clear_count)
                count <= 4'd0;
            else if (event_valid)
                count <= count + 4'd1;
        end
    endmodule
    
    `timescale 1ns/1ps

    This listing is the design under test (DUT), the hardware, plus the testbench that drives it and counts. The counters sit beside the stimulus: one counter per input combination, and one flag per counter event.

    Diagram
    # captured terminal output
    $ iverilog -g2012 -s tb_coverage -o build/cov.vvp rtl/mini_controller.sv tb/tb_coverage.sv && vvp build/cov.vvp | grep -v -E 'VCD|finish'
    input combination {rst_n,clear,valid}: hits
      000 : 1                      
      001 : 0   <-- never exercised
      010 : 0   <-- never exercised
      011 : 0   <-- never exercised
      100 : 1                      
      101 : 4                      
      110 : 0   <-- never exercised
      111 : 1                      
    count reached 15:           0   <-- never exercised
    wrapped 15 -> 0:            0   <-- never exercised
    reset while count nonzero:  0   <-- never exercised
    held a nonzero count:       1                      
    PASS: coverage report printed

    The first command compiles the pair and runs the directed sequence. Measured on macOS, Icarus Verilog 13.0, the seven directed cycles reach four of the eight combinations: 000, 100, 101 and 111. The combinations 001, 010, 011 and 110 never occur. The count never reaches 15, never wraps, and reset never arrives while the count is nonzero; only the nonzero hold is reached, once.

    Diagram
    # captured terminal output
    $ vvp build/cov.vvp +random | grep -v -E 'VCD|finish'
    input combination {rst_n,clear,valid}: hits
      000 : 20                      
      001 : 20                      
      010 : 4                      
      011 : 1                      
      100 : 155                      
      101 : 159                      
      110 : 22                      
      111 : 26                      
    count reached 15:           0   <-- never exercised
    wrapped 15 -> 0:            0   <-- never exercised
    reset while count nonzero:  29                      
    held a nonzero count:       101                      
    PASS: coverage report printed

    The second command replays the same binary with +random, which adds 400 random cycles. Measured on the same platform and versions, every combination is now reached at least once, reset arrives while the count is nonzero 29 times, and nonzero holds reach 101. But the count still never reaches 15 and never wraps: reset is asserted in 45 of the 407 cycles, and each reset returns the count to 0, so long counting runs keep getting cut short.

    Predict first The third run makes reset and clear rarer, so the count should finally climb to 15. Before you read it: which input combinations do you expect to stay empty, and why?

    010 and 011: reset and clear together, with and without a valid event. Each input is rare alone, and the testbench draws them independently, so the pair is rare squared. Random stimulus fills common holes and leaves the rare corners, which need directed cycles instead.

    Diagram
    # captured terminal output
    $ vvp build/cov.vvp +random +rare | grep -v -E 'VCD|finish'
    input combination {rst_n,clear,valid}: hits
      000 : 3                      
      001 : 6                      
      010 : 0   <-- never exercised
      011 : 0   <-- never exercised
      100 : 192                      
      101 : 197                      
      110 : 6                      
      111 : 3                      
    count reached 15:           6                      
    wrapped 15 -> 0:            4                      
    reset while count nonzero:  6                      
    held a nonzero count:       176                      
    PASS: coverage report printed

    The third command adds +rare, which makes reset and clear rarer. Measured on the same platform and versions, the count reaches 15 six times and wraps four times, and holds climb to 176. But the combinations 010 and 011 are still never exercised: reset and clear together, with and without a valid event. Two rare inputs coincide so seldom that random cycles keep missing the pair, so a directed case is needed. The strong testbench of Self-Checking and Golden Model carries exactly such a case: reset together with clear and valid.

    Your turn: close the last two holes

    Random stimulus left 010 and 011 empty: reset and clear together, without and with a valid event. A directed cycle fills a hole that chance cannot. In tb/tb_coverage.sv, add two cycles just before the line that starts if ($test$plusargs("random")), then run the third command again.

    Diagram
    // snippet: two new directed cycles, in the order (rst_n, clear, valid)
    cycle(0, 1, 0);   // 010: reset and clear together, no event
    cycle(0, 1, 1);   // 011: reset and clear together, with an event

    Run it and check the grid: the two rows that said never exercised should now show 1.

    Diagram
    # captured terminal output
    $ iverilog -g2012 -s tb_coverage -o build/cov.vvp rtl/mini_controller.sv tb/tb_coverage.sv && vvp build/cov.vvp +random +rare | grep -v -E 'VCD|finish'
    input combination {rst_n,clear,valid}: hits
      000 : 3                      
      001 : 6                      
      010 : 1                      
      011 : 1                      
      100 : 192                      
      101 : 197                      
      110 : 6                      
      111 : 3                      
    count reached 15:           6                      
    wrapped 15 -> 0:            4                      
    reset while count nonzero:  6                      
    held a nonzero count:       176                      
    PASS: coverage report printed

    All eight combinations are now reached. The other numbers moved a little, because the new cycles change the count the random cycles start from; coverage numbers depend on the whole stimulus. Remember what the report does and does not say: this testbench only counts what it reaches and checks no answers. Reaching a situation is not the same as verifying it, which is why the strong testbench from lesson 5.2 checks every cycle against the model.

    Three ways a coverage report misleads you

    • Treating 100 percent as proof of correctness. A full report says every situation you listed was reached. It says nothing about whether the checks were strong: lesson 5.1 showed green tests on broken designs. Pair the report with tests that can fail.

    • Chasing the number instead of the situations. Adding random cycles raises most counts while the rare corners sit at none. Read the named rows, especially 010 and 011 here, and close each hole with directed stimulus.

    • Writing covergroups before knowing which situations matter. List the situations from the spec first, as this lesson does with its eight combinations and four events, then encode them. SystemVerilog covergroups are the language feature that automates this counting; Covergroup Basics teaches the syntax.

    Rule: coverage tells you what your tests reached, never whether the design is right.

    Check yourself After the +random +rare run, which input combinations are still uncovered, and what directed stimulus reaches them?

    010 and 011: reset asserted with clear high, without and with a valid event. Add directed cycles that drive those exact combinations, for example edges with rst_n low and clear high in both valid states, then check the count is 0. Random runs keep missing the pair because two rare inputs coincide so seldom; a directed case costs two cycles and closes the hole.

    Check yourself The directed-only run never reaches 15. What is the cheapest directed addition that reaches it, and why does +random miss it?

    Hold reset and clear away while the event input stays high for sixteen edges: after the opening reset, repeat the counting cycle sixteen times and the count walks from 0 to 15 and wraps. The +random run misses it because reset arrives in about one cycle in eight and returns the count to 0, so long uninterrupted counting runs almost never survive.

    Check yourself Every line of the counter runs in the directed test, yet the wrap never happens. What does that say about line coverage?

    That line coverage answers a weaker question. The increment line runs on every counting edge, so a line report looks complete while the one situation that separates wrapping from sticking at 15, the 15 to 0 step, stays untried. Count situations from the spec, not lines from the code.

    Interview

    Asked: "Coverage is 100 percent. Is the design verified?"

    Weak answer: Yes. Every case ran, so the design is correct.

    Strong answer: No. Coverage answers what the tests reached, not whether the design is right. All of my situations can show 100 percent on a broken design if the checks are weak, and lesson 5.1 showed exactly that. I also need tests that fail on mutants, and I need confidence that my list of situations is the right one.

    Follow-ups: (1) What would you add after reaching 100 percent? (2) Who decides which situations belong on the list?

    Key takeaways

    • Coverage counts the situations your tests reached; a hole is a situation no test reached.

    • Random stimulus fills common holes and leaves rare corners; directed cases close the corners.

    • A full report with weak checks still passes broken code, so pair coverage with tests that can fail.

    Keep going

    Next: Lesson 5.6, Formal in One Lesson. Coverage shows what simulation reached. The next lesson reasons about every input sequence without running them.

    Related topics

    • SystemVerilog: Covergroup Basics

    • SystemVerilog course

    • Random Stimulus and Seeds

    • Assertions

    Previous

    28 / 47

    Next: Formal in One Lesson

    Up next

    Up nextFormal in One Lesson

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Tests That Can Fail
    • Self-Checking and Golden Model
    • Random Stimulus and Seeds