Functional Coverage Interview Questions
Master SystemVerilog coverage: covergroups, coverpoints, bins, cross coverage, transitions, and coverage analysis.
Beginner Level
Fundamentals| Aspect | Code Coverage | Functional Coverage |
|---|---|---|
| What it measures | Lines/branches/expressions executed | Features/scenarios exercised |
| Generation | Automatic (tool extracts from RTL) | Manual (engineer writes covergroups) |
| Question answered | "Did I execute this code?" | "Did I test this feature?" |
Key Insight: 100% code coverage ≠ full verification. You can execute all lines without testing all scenarios (e.g., corner cases, protocol combinations).
1. Coverpoint: The variable or expression to track.
coverpoint addr; // Track all values of 'addr'
2. Bins: Value ranges or categories within a coverpoint.
coverpoint size {
bins small = {[1:10]};
bins medium = {[11:100]};
bins large = {[101:$]};
}
3. Cross: Combinations of multiple coverpoints.
cross cp_size, cp_type; // All combinations of size × type
Manual Sampling:
covergroup cg;
coverpoint data;
endgroup
cg cg_inst = new();
// ...
cg_inst.sample(); // Explicit call
Auto-Sampling:
covergroup cg @(posedge clk); // Samples every posedge clk
coverpoint data;
endgroup
cg cg_inst = new();
Event-Based Sampling:
covergroup cg @(transaction_complete); // Samples on event trigger
coverpoint txn.addr;
endgroup
Intermediate Level
Industry Standardignore_bins vs illegal_bins. What happens
if an illegal_bins value is hit?ignore_bins: Excluded from coverage percentage. No error if
hit.
coverpoint opcode {
ignore_bins reserved = {[200:255]}; // Don't count these
}
illegal_bins: Should never occur. Generates an
ERROR if hit.
coverpoint state {
illegal_bins bad_state = {4'b1111}; // Error if ever seen!
}
When illegal_bins is hit:
- Simulation continues (not $fatal).
- Error message is logged.
- Useful for detecting spec violations.
opcode with named bins for NOP,
READ_OPS, WRITE_OPS, and ignore all others.covergroup op_coverage @(posedge clk);
coverpoint opcode {
bins NOP = {8'h00};
bins READ_OPS = {[8'h01:8'h10]}; // 1-16
bins WRITE_OPS = {[8'h11:8'h20]}; // 17-32
ignore_bins OTHERS = default; // Everything else
}
endgroup
Note: default catches all values not explicitly binned.
Transition Coverage: Tracks sequences of values, not just individual values.
typedef enum {IDLE, RUN, DONE, ERROR} state_e;
covergroup fsm_coverage @(posedge clk);
coverpoint state {
// Individual state bins (optional)
bins idle = {IDLE};
bins run = {RUN};
bins done = {DONE};
// Transition bins (key!)
bins idle_to_run = (IDLE => RUN);
bins run_to_done = (RUN => DONE);
bins done_to_idle = (DONE => IDLE);
// Multi-hop transition
bins full_cycle = (IDLE => RUN => DONE => IDLE);
// Illegal transitions
illegal_bins bad_trans = (IDLE => DONE); // Skipping RUN is illegal
}
endgroup
Advanced Level
Expertcp_size (SMALL,
MEDIUM, LARGE) and cp_type (READ, WRITE, RMW). Exclude the (LARGE, RMW)
combination.covergroup transaction_coverage;
cp_size: coverpoint size {
bins SMALL = {[1:10]};
bins MEDIUM = {[11:100]};
bins LARGE = {[101:$]};
}
cp_type: coverpoint txn_type {
bins READ = {0};
bins WRITE = {1};
bins RMW = {2};
}
size_type_cross: cross cp_size, cp_type {
// Exclude LARGE × RMW combination
ignore_bins no_large_rmw = binsof(cp_size.LARGE) && binsof(cp_type.RMW);
}
endgroup
Result: 3×3 = 9 combinations, minus 1 ignored = 8 valid cross bins.
with clause in cross coverage. Write a cross that
only samples when is_valid is true.with Clause: Filters which samples are counted based on a
condition.
covergroup filtered_coverage @(posedge clk);
cp_addr: coverpoint addr;
cp_data: coverpoint data;
// Only count cross when transaction is valid
valid_cross: cross cp_addr, cp_data {
option.weight = 1;
} iff (is_valid); // Alternative: iff clause
// Using 'with' for more complex filtering
cp_size: coverpoint size {
bins valid_sizes[] = {[1:100]} with (item % 4 == 0); // Only multiples of 4
}
endgroup
Note: iff at covergroup or coverpoint level filters sampling.
with filters bin creation.
Strategy: Cover "interesting" ranges, not all values.
covergroup addr_coverage;
coverpoint addr {
// Boundary values
bins zero = {32'h0};
bins max = {32'hFFFF_FFFF};
// First and last 1KB
bins first_1k = {[32'h0:32'h3FF]};
bins last_1k = {[32'hFFFF_FC00:32'hFFFF_FFFF]};
// Powers of 2 (alignment boundaries)
bins power_of_2[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
// 4KB aligned addresses (common page boundaries)
bins kb_aligned = {[0:$]} with (item[11:0] == 0);
// Range buckets for middle values
bins low_range = {[32'h1000:32'h0FFF_FFFF]};
bins mid_range = {[32'h1000_0000:32'h7FFF_FFFF]};
bins high_range = {[32'h8000_0000:32'hFFFF_FBFF]};
}
endgroup
Key Approach: Focus on boundaries, alignments, and protocol-specific "hot spots."
Coverage Merge Flow:
+---------+ +---------+ +---------+
| Sim 1 | | Sim 2 | | Sim N |
| seed=1 | | seed=2 | | seed=N |
+----┬----+ +----┬----+ +----┬----+
| | |
▼ ▼ ▼
cov1.db cov2.db covN.db
| | |
+-----------------------------┼-----------------------------+
▼
+-----------------------------+
| Merge Tool |
+------┬------+
▼
merged_cov.db
|
▼
+-----------------------------+
| Report Gen |
+-----------------------------+
Common Formats:
| Vendor | Format | Merge Command |
|---|---|---|
| Synopsys VCS | .vdb |
urg -dir *.vdb -dbname merged.vdb
|
| Cadence Xcelium | .ucd |
imc -load *.ucd -merge merged.ucd
|
| Mentor Questa | .ucdb |
vcover merge -out merged.ucdb *.ucdb
|