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

  • Start Here6
  • SystemVerilog Language Foundations28
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
    • Covergroups & Coverpoints
    • Bins: Explicit, Auto, Illegal & Ignore
    • Cross Coverage
      • Cross Basics
      • binsof & intersect
      • Pruning Crosses: ignore_bins & illegal_bins
      • Managing Cross Explosion
      • Cross Coverage Patterns
    • Coverage Options & Methods
    • Coverage Closure & Sign-Off
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Cross Coverage
  1. Topics
  2. SystemVerilog
  3. Functional Coverage in SystemVerilog
  4. Cross Coverage
  5. binsof & intersect

Part 5 · Functional Coverage · Intermediate

binsof & intersect

Selecting cross cells with binsof, intersect filters, AND-OR-NOT combinations, and named bins.

On this page

    Why this matters

    A reviewer expected binsof(cp_len) intersect {[1:2]} to select one and two-beat bursts. It selected the whole short column too, because 2 lies in the 2-to-4 bin.

    After this lesson you can: select cross cells with binsof, intersect, &&, || and !, and predict the goal a named cross bin leaves.

    Selecting with binsof

    Inside a cross body, binsof selects a slice of the product matrix. binsof(cp.bin_name) picks every cell whose cp coordinate is that bin: a full row or column.

    binsof(cp) intersect {values} picks the cells whose cp bin contains any of the listed values. Selection is by value overlap, not by bin name.

    The listing below is not run in this course's checks: the open simulators do not count covergroups, so the lesson's bench counts it with the bins model.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    covergroup cg @(posedge clk iff valid);
      cp_op  : coverpoint opcode    { bins add = {OP_ADD}; bins sub = {OP_SUB};
                                      bins mul = {OP_MUL}; bins div = {OP_DIV}; }
      cp_len : coverpoint burst_len { bins single = {1};  bins short_b = {[2:4]};
                                      bins long_b = {[5:16]}; }
    
      x_op_len : cross cp_op, cp_len {
        // Select by bin name: the whole div row (3 cells -> 1 named bin)
        bins div_any = binsof(cp_op.div);
    
        // Select by value: any len bin containing 1..2 (single and short_b)
        bins short_ops = binsof(cp_len) intersect {[1:2]};
    
        // AND of selections: exactly the <div, long_b> cell
        bins div_long = binsof(cp_op.div) && binsof(cp_len.long_b);
    
        // OR of selections: union of the mul row and the div row
        bins muldiv = binsof(cp_op.mul) || binsof(cp_op.div);
    
        // Negation: every cell NOT in the add row
        bins not_add = !binsof(cp_op.add);
      }
    endgroup

    Selection

    Cells

    Which

    binsof(cp_op.div)

    3

    The div row

    binsof(cp_len) intersect {[1:2]}

    8

    The single and short_b columns: 2 overlaps short_b, so the whole column joins

    binsof(cp_op.div) && binsof(cp_len.long_b)

    1

    <div,long_b>: && narrows

    binsof(cp_op.mul) || binsof(cp_op.div)

    6

    The mul and div rows: || widens

    !binsof(cp_op.add)

    9

    Every row but add: ! inverts

    Form

    Selects

    Set meaning

    binsof(cp.bin)

    Whole row or column of that bin

    Base selection

    binsof(cp) intersect {vals}

    Every source bin overlapping the values

    Value filter

    A && B

    Cells in both selections

    Narrows

    A || B

    Cells in either selection

    Widens

    !A

    Cells outside the selection

    Inverts

    Named bins absorb the cells they select

    A named cross bin built from a selection is one bin, no matter how many cells it covers. It closes when any cell in its selection is hit.

    A named bin absorbs the auto cells it selects. Every other auto cell stays in the goal. To make the goal exactly the named bins, add an ignore_bins catch-all over the complement.

    The listing below is not run in this course's checks, for the same reason.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // not-run: Verilator 5.048 ignores covergroups (COVERIGN) and Icarus 13 has none; the bins model counts it
    x_op_len : cross cp_op, cp_len {
      // ONE bin: closes when ANY div cell is hit.
      // It absorbs the 3 div cells; the other 9 auto cells stay.
      bins div_any = binsof(cp_op.div);
    }
    // Goal: 1 named bin + 9 auto cells = 10 bins.
    
    x_div_cells : cross cp_op, cp_len {
      // Cross bins have no [] array form. To grade each div cell,
      // name each one:
      bins div_single = binsof(cp_op.div) && binsof(cp_len.single);
      bins div_short  = binsof(cp_op.div) && binsof(cp_len.short_b);
      bins div_long   = binsof(cp_op.div) && binsof(cp_len.long_b);
      // Catch-all: drop every other cell, so the goal is these 3 bins.
      ignore_bins rest = !binsof(cp_op.div);
    }

    Prefer binsof(cp.bin) over value lists when the bin already names the intent. Name selection survives value renumbering inside the bin.

    Interview

    “What does binsof(cp_len) intersect {[1:2]} select when short_b = {[2:4]}?” It selects short_b too, because intersect works on overlap, not containment. The value 2 sits inside short_b, so the whole short_b column joins the selection. Candidates who think intersect filters individual values get this wrong.

    Check yourself A named selection covers 8 cells but closes after a single hit. Why, and how do you grade each cell?

    A named cross bin is one bin, so one hit anywhere closes it. Cross bins have no [] form. Leave those cells to the auto product, which grades each cell, or declare one named bin per cell.

    Check yourself In the 4 x 3 cross, you name one bin over the 3 div cells and say nothing about the rest. What is the goal?

    10 goal bins: the named bin plus the 9 auto cells it does not select. Add an ignore_bins catch-all if the goal should be the named bin alone.

    Testbench

    The bench builds each selection from this lesson with the bins model and counts its cells, then sends one <div,long_b> sample through three crosses: one with all five selections as named bins, one with div_any alone, and one with a named bin per div cell plus the catch-all.

    Predict first How many cells does binsof(cp_len) intersect {[1:2]} select, and what goal does div_any alone leave?

    8 cells, because intersect selects every bin that overlaps the values, and 2 lies in short_b. div_any alone leaves a goal of 10: itself plus the 9 auto cells it does not select. The one sample also hits 4 of the 5 overlapping named bins at once.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    // uses: covmodel
    // binsof selections over the 4 x 3 cross: how many cells each one picks, and the goal they leave.
    module tb_binsof;
      cm_point cp_op = new("cp_op"), cp_len = new("cp_len");
      cm_cross x_sel, x_any, x_cells;
      initial begin
        int n_hit = 0;
        cp_op.add("add", 0, 0); cp_op.add("sub", 1, 1); cp_op.add("mul", 2, 2); cp_op.add("div", 3, 3);
        cp_len.add("single", 1, 1); cp_len.add("short_b", 2, 4); cp_len.add("long_b", 5, 16);
        x_sel = new("x_op_len", cp_op, cp_len);
        x_sel.add_bin("div_any",   x_sel.sel("div", ""));                                           // binsof(cp_op.div)
        x_sel.add_bin("short_ops", x_sel.sel_values('{1, 2}, 1));                                   // binsof(cp_len) intersect {[1:2]}
        x_sel.add_bin("div_long",  x_sel.sel_and(x_sel.sel("div", ""), x_sel.sel("", "long_b")));   // &&
        x_sel.add_bin("muldiv",    x_sel.sel_or(x_sel.sel("mul", ""), x_sel.sel("div", "")));       // ||
        x_sel.add_bin("not_add",   x_sel.sel_not(x_sel.sel("add", "")));                            // !
        foreach (x_sel.nb_name[n]) $display("  %-10s cells: %0d", x_sel.nb_name[n], x_sel.count(x_sel.nb_cells[n]));
        // One named bin and nothing else: the 9 cells it does not select stay as auto bins.
        x_any = new("x_any", cp_op, cp_len);
        x_any.add_bin("div_any", x_any.sel("div", ""));
        // One named bin per div cell, and an ignore_bins catch-all for the rest.
        x_cells = new("x_div_cells", cp_op, cp_len);
        x_cells.add_bin("div_single", x_cells.sel("div", "single"));
        x_cells.add_bin("div_short",  x_cells.sel("div", "short_b"));
        x_cells.add_bin("div_long",   x_cells.sel("div", "long_b"));
        x_cells.ignore(x_cells.sel_not(x_cells.sel("div", "")));                                    // ignore_bins rest = !binsof(cp_op.div);
        // A single sample: div with a 9-beat burst.
        cp_op.sample(3); cp_len.sample(9); x_sel.sample(); x_any.sample(); x_cells.sample();
        foreach (x_sel.nb_hits[n]) if (x_sel.nb_hits[n] != 0) n_hit++;
        $display("  one <div,long_b> sample hit %0d of the overlapping named bins", n_hit);
        x_any.report(); x_cells.report();
        if (x_sel.count(x_sel.nb_cells[1]) != 8 || n_hit != 4 || x_any.n_bins() != 10 || x_cells.n_bins() != 3 || x_any.nb_hits[0] != 1)
          $fatal(1, "FAIL: selection math");
        $display("PASS: intersect took whole columns (8 cells), div_any left a 10-bin goal, the catch-all left 3");
        $finish;
      end
    endmodule
    Terminal
      div_any    cells: 3
      short_ops  cells: 8
      div_long   cells: 1
      muldiv     cells: 6
      not_add    cells: 9
      one <div,long_b> sample hit 4 of the overlapping named bins
      cross x_any: 10.00% (1 of 10 bins)
        div_any        1
        hole: <add, single>
        hole: <add, short_b>
        hole: <add, long_b>
        hole: <sub, single>
        hole: <sub, short_b>
        hole: <sub, long_b>
        hole: <mul, single>
        hole: <mul, short_b>
        hole: <mul, long_b>
      cross x_div_cells: 33.33% (1 of 3 bins)
        div_single     0     <- hole
        div_short      0     <- hole
        div_long       1
    PASS: intersect took whole columns (8 cells), div_any left a 10-bin goal, the catch-all left 3

    Common pitfall

    Reading && as “both values true” misleads: it intersects selections of cells, a set operation. Expecting intersect to trim values out of a bin misleads the same way: it selects whole overlapping bins. And overlapping named selections let one sample hit several bins at once, which skews hit counts.

    Remember

    • intersect selects whole bins that overlap the values.

    • A named cross bin is one bin; it absorbs the cells it selects.

    • Unselected auto cells stay in the goal without a catch-all.

    Rule of thumb: count the cells a selection takes before trusting it.

    How this was checked

    Counted with the course's bins model (rich/coverage/cov_model.sv, listed on the Coverage hub) on Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown. Verilator 5.048 parses covergroups with a COVERIGN warning and ignores their bins, and Icarus 13 has none, so each covergroup listing is marked not run and its bench counts the same bins with the model.

    intersect {[1:2]} took 8 cells, div_any alone left a 10-bin goal, the ignore_bins catch-all left 3, and one sample hit 4 overlapping named bins at once.

    Related topics

    • Cross Basics

    • Pruning Crosses: ignore_bins & illegal_bins

    Previous

    150 / 259

    Next: Pruning Crosses: ignore_bins & illegal_bins

    Up next

    Up nextPruning Crosses: ignore_bins & illegal_bins

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Managing Cross Explosion
    • Cross Coverage Patterns