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
    • SVA Fundamentals
    • Sequences: Temporal Building Blocks
      • Cycle Delays: ##N and ##[M:N]
      • Repetition: [*], [->], [=]
      • Composition: and, or, intersect, throughout, within
      • first_match() & Sequence Endpoints
    • Implication and Property Operators
    • Sampled Value Functions
    • Protocol Assertion Cookbook
    • Advanced SVA: Local Variables, Multiclock & More
    • Assertion Debug & Methodology
    • SVA Interview Drills
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Sequences: Temporal Building Blocks
  1. Topics
  2. SystemVerilog
  3. SystemVerilog Assertions — Interview-Critical Deep Dive
  4. Sequences: Temporal Building Blocks
  5. Repetition: [*], [->], [=]

Part 4 · Assertions (SVA) · Intermediate

Repetition: [*], [->], [=]

Consecutive repetition with star counts plus goto and non-consecutive counting on one shared stimulus.

On this page

    Why this matters

    A burst-length check passed for weeks while bursts with a one-cycle gap went through. On the simulator in use, the compact repetition missed a drop on the second beat.

    After this lesson you can: write consecutive, goto and non-consecutive repetition, and place an endpoint on the right tick.

    Runs without gaps

    a [*3] means a holds for three consecutive ticks. It is shorthand for a ##1 a ##1 a, and the repeated item can be a whole sequence: (a ##1 b)[*2] expands to a ##1 b ##1 a ##1 b.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // snippet
    sequence s_busy4;
      start ##1 busy [*4] ##1 done;
    endsequence
    // Expansion: start ##1 busy ##1 busy ##1 busy ##1 busy ##1 done
    
    // 0 to 2 wait states allowed: ready may come immediately
    sequence s_opt_waits;
      sel ##1 wait_n [*0:2] ##1 ready;
    endsequence

    Form

    Meaning

    Note

    a [*N]

    a for N consecutive ticks

    Works on whole sequences

    a [*M:N]

    A run of M to N ticks

    One thread per length

    a [*0]

    Empty match, zero ticks

    Only glued between neighbors

    a [*0:N]

    Optional run, possibly absent

    The honest way to say maybe

    a [*1:$]

    Unbounded run

    Weak, like ##[1:$]

    Common pitfall

    busy [*4] checks that busy is present for four ticks. It never checks the trailing edge, so add ##1 !busy when the drop is part of the rule.

    Check yourself start ##1 busy [*4] ##1 done spans how many ticks from start to done?

    Six ticks inclusive: start, four busy ticks, then done. So done lands 5 ticks after start.

    Check yourself Why is a standalone assert property (wait_n [*0]) illegal?

    An empty match consumes zero ticks, so there is no tick at which anything is observed.

    Counted events with gaps

    Goto [->N] and non-consecutive [=N] both count N scattered occurrences of a boolean. Gaps between occurrences are free in both forms.

    They differ in exactly one thing. Goto must end on the tick of the Nth occurrence, while non-consecutive may extend past it through an occurrence-free gap.

    design.sv
    // snippet
    // LRM expansions: b [->N] === (!b [*0:$] ##1 b) [*N]
    //                 b [=N]   === b [->N] ##1 !b [*0:$]

    The sequences below are not run in this course's checks. Verilator 5.048 stopped with an internal error on [=N], with or without a default clocking block, and it rejects a named sequence with ## after its first item.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    // not-run: Verilator 5.048 stops with an internal error on [=N] and rejects these named sequences
    sequence s_third_ack_goto;
      start ##1 ack [->3];        // ends exactly on the 3rd ack
    endsequence
    
    sequence s_third_ack_eq;
      start ##1 ack [=3];         // 3 acks total, trailing gap allowed
    endsequence

    [->N] goto

    [=N] non-consecutive

    Counts

    N scattered occurrences

    N scattered occurrences

    Endpoint

    Locked to the Nth occurrence

    May drift past it through !b ticks

    Killed by

    Nothing after the Nth tick matters

    A further occurrence during the gap

    Default choice

    Yes, for protocol timing

    Only when the gap is specified

    Check yourself A fourth ack fires during the trailing gap of an [=3] match. What happens to the extended threads?

    They die. The gap must be occurrence-free, not merely idle time.

    Endpoints decide

    One stimulus shows the whole difference. Three ack ticks arrive scattered, and done arrives two ticks after the third one.

    The goto endpoint is locked to slot 5, so done at slot 7 misses it. The non-consecutive endpoint drifts to slot 6, so the same done matches.

    • Slot 0: idle, start, ack, and done all 0.

    • Slot 1: start rises, and the count begins.

    • Slot 2: first ack.

    • Slot 3: second ack.

    • Slot 4: quiet tick, and both forms tolerate it.

    • Slot 5: third ack, where the goto endpoint locks.

    • Slot 6: quiet tick, where only the non-consecutive endpoint may sit.

    • Slot 7: done rises, one tick past the goto deadline and exactly after the drifted endpoint.

    Endpoint alignment is also a placement rule. Time a follow-on off the Nth event with goto, and reach for [=N] only when the follow-on is genuinely decoupled from that cycle.

    Interview

    Likely task: “Draw a stimulus where [->3] ##1 done fails and [=3] ##1 done passes.”

    • Scatter three occurrences, then place done two or more ticks after the third.

    • Quote the expansions: goto is repeated gap-then-event, and [=N] adds a trailing occurrence-free gap.

    • State the default: goto for protocol timing, [=N] only when the gap is specified.

    Check yourself The fourth beat itself must carry beat_last. Which operator and join express that?

    beat_valid [->4] ##0 beat_last. Goto pins the endpoint to the fourth beat, and fusion tests the flag on that very tick.

    Testbench

    The bench runs each rule twice as a real assertion. The burst rule is written compact, busy [*4] ##1 done, and written out tick by tick. The counted rule is written with goto, ack [->3] ##1 fin, and with a two-bit counter as modeling code plus a one-step property. Planted bugs: bursts one tick short, bursts where busy drops on the second tick, and a late fin.

    Predict first 10 of the 20 bursts are bad. How many failures should each burst check report?

    10 each. On Verilator 5.048 the compact form reports 5: it catches the short bursts and misses every burst whose busy dropped on the second tick. The written-out form catches all 10.

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    module tb_repetition;
      logic clk = 0, start = 0, busy = 0, done = 0;       // burst signals
      logic go = 0, ack = 0, fin = 0;                      // counted-event signals
      always #5 clk = ~clk;
      int compact_fails = 0, spelled_fails = 0, goto_fails = 0, counted_fails = 0;
    
      // The burst rule twice: compact, and written out tick by tick.
      ap_compact: assert property (@(posedge clk) $rose(start) |=> busy [*4] ##1 done) else compact_fails++;
      ap_spelled: assert property (@(posedge clk) $rose(start) |=> busy ##1 busy ##1 busy ##1 busy ##1 done) else spelled_fails++;
    
      // The counted rule twice: fin the tick after the third ack.
      ap_goto: assert property (@(posedge clk) $rose(go) |=> ack [->3] ##1 fin) else goto_fails++;
      // Modeling code counts the acks; a one-step property checks fin.
      logic [1:0] n_ack = 0;
      always @(posedge clk)
        if ($rose(go)) n_ack <= 0;
        else if (ack && n_ack != 3) n_ack <= n_ack + 1;
      wire third_ack = ack && n_ack == 2;
      ap_counted: assert property (@(posedge clk) third_ack |=> fin) else counted_fails++;
    
      task automatic burst(int len, int drop_at = -1);
        @(negedge clk) start = 1;
        @(negedge clk) start = 0;
        for (int i = 0; i < len; i++) begin busy = (i != drop_at); @(negedge clk); end
        busy = 0; done = 1;
        @(negedge clk) done = 0;
        repeat (4) @(negedge clk);
      endtask
    
      task automatic three_acks(int g1, int g2, int g3, int late);
        @(negedge clk) go = 1;
        @(negedge clk) go = 0;
        repeat (g1) @(negedge clk); ack = 1; @(negedge clk) ack = 0;
        repeat (g2) @(negedge clk); ack = 1; @(negedge clk) ack = 0;
        repeat (g3) @(negedge clk); ack = 1; @(negedge clk) ack = 0;
        repeat (late) @(negedge clk);
        fin = 1; @(negedge clk) fin = 0;
        repeat (4) @(negedge clk);
      endtask
    
      initial begin
        repeat (2) @(negedge clk);
        for (int i = 0; i < 10; i++) burst(4);           // clean
        for (int i = 0; i < 5; i++)  burst(3);           // planted: one busy tick short
        for (int i = 0; i < 5; i++)  burst(4, 1);        // planted: busy drops on the 2nd tick
        $display("bursts (10 clean, 10 bad): compact busy [*4] %0d failures, written out %0d", compact_fails, spelled_fails);
        for (int i = 0; i < 10; i++) three_acks(0, 2, 3, 0);   // fin right after the third ack
        for (int i = 0; i < 5; i++)  three_acks(1, 1, 1, 1);   // planted: fin one tick late
        $display("acks (10 on time, 5 late): ack [->3] ##1 fin %0d failures, counter version %0d", goto_fails, counted_fails);
        if (spelled_fails != 10 || counted_fails != 5) $fatal(1, "FAIL: spelled %0d counted %0d", spelled_fails, counted_fails);
        $display("PASS: the written-out run and the counter caught every planted bug; compare the compact forms' counts above");
        $finish;
      end
    endmodule
    Terminal
    bursts (10 clean, 10 bad): compact busy [*4] 5 failures, written out 10
    acks (10 on time, 5 late): ack [->3] ##1 fin 0 failures, counter version 5
    PASS: the written-out run and the counter caught every planted bug; compare the compact forms' counts above

    Read the output as two lessons. The standard forms are right, and on a commercial simulator they catch every planted bug. On this open simulator the compact forms miss some, and the written-out run and the counter do not. When a check must be trusted on the tool at hand, write it in a form whose verdicts you have tested.

    Remember

    • a [*N] is a ##1 a ... N times; [->N] ends on the Nth event.

    • [=N] may end after the Nth event, through an event-free gap.

    • Test the verdicts of compact forms on your simulator.

    Rule of thumb: a check you rely on must fail on a planted bug before you trust it.

    How this was checked

    Run with Verilator 5.048 (--binary --timing --assert, plus --coverage when a listing has a cover property) on 2026-10-18; every bench printed the PASS line shown. Verilator stops at the first $error or failing assertion without an action block, so the benches count failures in the action block. Icarus 13 has no concurrent assertions.

    busy [*4] in a consequent caught 5 of 10 bad bursts (it missed every drop on the second tick); the written-out form caught 10. ack [->3] ##1 fin caught 0 of 5 late fins; a counter plus fin check caught 5. [=N] stopped Verilator with an internal error.

    Related topics

    • Sequence pattern drills

    • Composition: and, or, intersect, throughout, within

    Previous

    107 / 259

    Next: Composition: and, or, intersect, throughout, within

    Up next

    Up nextComposition: and, or, intersect, throughout, within

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • first_match() & Sequence Endpoints
    clkstartackdone
    Three scattered acks with a late done: goto misses, non-consecutive matches