SV-04
SystemVerilog
Functional Coverage
Coverage Types — From Coarse to Fine
Code Coverage vs Functional Coverage
| Aspect | Code Coverage | Functional Coverage |
|---|---|---|
| Generated by | Tool automatically (EDA) | Engineer (manual) |
| Measures | Which lines/branches ran | Which design behaviors exercised |
| Defined in | RTL source | Verification plan + covergroups |
| 100% means | All RTL paths executed | All scenarios from spec tested |
| Can be misleading? | Yes — no assertion means no bug found | Yes — wrong plan misses real scenarios |
1. Covergroup and Coverpoint Basics
SystemVerilog — Basic covergroup
// Standalone covergroup — sampled at posedge clk covergroup cg_axi_txn @(posedge clk); // Coverpoint: tracks all values of 'size' cp_size: coverpoint size { bins byte_tx = {3'b000}; bins half_tx = {3'b001}; bins word_tx = {3'b010}; bins dword_tx = {3'b011}; illegal_bins rsvd = {[4:7]}; // values 4-7 must NEVER occur } // Coverpoint: tracks write vs read cp_rw: coverpoint write { bins rd = {0}; bins wr = {1}; } // Coverpoint with ranges cp_burst: coverpoint len { bins single = {0}; bins short = {[1:15]}; bins medium = {[16:63]}; bins long_b = {[64:255]}; } endgroup // Instantiate and sample cg_axi_txn cov = new(); // auto-samples at posedge clk // Or sample manually: cov.sample(); $display("Coverage: %.1f%%", cov.get_coverage());
2. Inside a Class — Sampling from Monitor
SystemVerilog — Class-based covergroup
class AXICoverage; AXITxn txn; // current transaction being sampled covergroup cg_axi; // Use txn.field syntax inside class covergroup cp_size: coverpoint txn.size { bins sizes[] = {[0:3]}; // auto-name: sizes[0], sizes[1], ... } cp_write: coverpoint txn.write; cp_len: coverpoint txn.len { bins lo = {[0:15]}; bins hi = {[16:255]}; } // Cross: all size × write combinations must be seen cx_size_rw: cross cp_size, cp_write; endgroup function new(); cg_axi = new(); endfunction function void sample(AXITxn t); txn = t; cg_axi.sample(); // manually triggered endfunction function void report(); $display("AXI Coverage: %.1f%%", cg_axi.get_coverage()); endfunction endclass
3. Cross Coverage
Cross coverage checks that every combination of two (or more) coverpoints was exercised. It's essential for protocols where behavior depends on multiple simultaneous conditions:
SystemVerilog — Cross coverage
covergroup cg_apb @(posedge clk); cp_state: coverpoint apb_state { bins idle = {IDLE}; bins setup = {SETUP}; bins access = {ACCESS}; } cp_rw: coverpoint PWRITE { bins rd = {0}; bins wr = {1}; } cp_err: coverpoint PSLVERR { bins ok = {0}; bins err = {1}; } // 3-way cross: every state × direction × error combination // 3 × 2 × 2 = 12 cross bins must all be hit cx_all: cross cp_state, cp_rw, cp_err; // Selective cross: only some combinations matter cx_rw_err: cross cp_rw, cp_err { ignore_bins no_rd_err = binsof(cp_rw.rd) && binsof(cp_err.err); } endgroup
4. Wildcard Bins
SystemVerilog — Wildcard bins
covergroup cg_opcode @(posedge clk); cp_op: coverpoint opcode { // wildcard: ? matches any bit value wildcard bins arith = {8'b000?????}; // any opcode starting 000 wildcard bins logic_ = {8'b001?????}; wildcard bins mem = {8'b01??????}; wildcard bins branch = {8'b1???????}; // Anything not matched goes to default bin bins others = default; } endgroup
5. ignore_bins and illegal_bins
| Keyword | Effect | Use When |
|---|---|---|
| ignore_bins | Excluded from coverage report — not counted as covered or uncovered | Don't-care scenarios, reset states |
| illegal_bins | Causes a coverage error if the value occurs | Reserved encodings, protocol violations |
SystemVerilog
covergroup cg_fifo @(posedge clk); cp_fill: coverpoint fill_level { bins empty = {0}; bins low = {[1:7]}; bins mid = {[8:24]}; bins hi = {[25:31]}; bins full = {32}; // Ignore values during reset (X propagation) ignore_bins x_val = {[33:63]}; // Should NEVER go above 32 — flag as error if seen illegal_bins overflow = {[33:63]}; } endgroup
6. Complete AXI-Stream Coverage Model
SystemVerilog — Full coverage class
class AXISCoverage; bit tvalid, tready, tlast; bit [7:0] tdata; bit [7:0] burst_len; // tracked externally covergroup cg_axis; // Handshake states cp_hs: coverpoint {tvalid, tready} { bins idle = {2'b00}; bins valid_wait = {2'b10}; bins xfer = {2'b11}; bins ready_early = {2'b01}; } // Data value ranges cp_data: coverpoint tdata { bins zero = {8'h00}; bins ff = {8'hFF}; bins mid = {[8'h01:8'hFE]}; } // Burst length buckets cp_burst: coverpoint burst_len { bins single = {1}; bins short_ = {[2:8]}; bins long_ = {[9:255]}; } // Cross: xfer × burst — did we do long transfers? cx_xfer_burst: cross cp_hs, cp_burst { ignore_bins no_xfer = binsof(cp_hs.idle); } // TLAST hit with every burst length cp_last: coverpoint tlast; cx_last_burst: cross cp_last, cp_burst { ignore_bins no_last = binsof(cp_last) intersect {0}; } endgroup function new(); cg_axis = new(); endfunction function void sample_hs(bit v, r, l, [7:0] d, [7:0] blen); tvalid=v; tready=r; tlast=l; tdata=d; burst_len=blen; cg_axis.sample(); endfunction function void report(); $display("AXIS Coverage = %.2f%%", cg_axis.get_coverage()); $display(" Handshake: %.2f%%", cg_axis.cp_hs.get_coverage()); $display(" Burst len: %.2f%%", cg_axis.cp_burst.get_coverage()); $display(" Cross xfer: %.2f%%", cg_axis.cx_xfer_burst.get_coverage()); endfunction endclass
Coverage Closure Workflow
- Define coverage plan — list all behaviors from the spec that need to be tested
- Write covergroups — translate each behavior into coverpoints and bins
- Run constrained-random tests — let the simulator generate stimulus
- Check coverage report — identify uncovered bins
- Add targeted directed tests or tighten constraints — drive toward 100%
- Merge coverage databases — aggregate across multiple simulation runs for full closure
Next: UVM Basics (SV-05) — learn how assertions, classes, randomization, and coverage fit together inside the Universal Verification Methodology framework.