Part 4 · Assertions (SVA) · Intermediate

Advanced SVA: Local Variables, Multiclock & More

Hub — sequence local variables, multi-clock properties, expect, the checker construct, and assertion control system tasks.

Beyond single-clock pattern matching

Everything so far assumed one clock, fixed latencies, and checks that only observe signals. Real designs break all three assumptions: a pipeline returns data with a tag after a variable number of cycles, a handshake crosses from a 200 MHz domain to a 100 MHz domain, and a senior DV engineer wants one reusable checker dropped onto twenty FIFO instances. This topic covers the SVA machinery for each of those: local variables carry data through a sequence, multiclocked sequences stitch domains together, expect lets procedural testbench code block on a property, checker packages assertions plus modeling code into a reusable unit, and the assertion control system tasks silence the whole suite during reset.

These are the constructs that separate "I can write req |-> ##[1:3] ack" candidates from "I have verified a real pipeline" candidates. Interviewers reach for local variables in particular — the data-integrity question ("check that the data out of this FIFO matches what went in") is unanswerable without them.

Sub-topics

  1. Local Variables in Sequences — per-thread data capture, the canonical tag/data integrity check, FIFO data checking.

  2. Multi-Clock Assertions — explicit clocking events per subsequence, clock-crossing ## semantics, CDC handshake checks.

  3. expect & Procedural Concurrent Assertions — blocking property waits in tasks, assertions inside always blocks.

  4. The checker Construct — encapsulating assertions plus modeling code, free variables, bind-friendly reuse.

  5. Assertion Control & System Functions — $assertoff/$asserton/$assertkill, $assertcontrol, assertion coverage, $global_clock.

diagram
Legend: [DATA] [CLOCK] [TB] [REUSE] [CTRL]

┌────────────────────────────────────────────────────────────────────────┐
│  ADVANCED SVA — topic map                                              │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│  1. LOCAL VARIABLES [DATA]                                             │
│     (valid, x = tag)  ##[1:20]  (done && rtag == x)                    │
│     per-thread copies │ capture at request │ compare at response       │
│                                                                        │
│  2. MULTICLOCK [CLOCK]                                                 │
│     @(posedge clkA) req  ##1  @(posedge clkB) ack                      │
│     clock-change ## rules │ CDC handshakes │ when NOT to cross         │
│                                                                        │
│  3. expect / PROCEDURAL [TB]                                           │
│     task body: expect (@(posedge clk) gnt ##1 done) ...                │
│     blocking wait on a property │ assert property inside always        │
│                                                                        │
│  4. checker CONSTRUCT [REUSE]                                          │
│     checker fifo_chk(...) — assertions + aux modeling + free vars      │
│     instantiate or bind │ library-of-checkers pattern                  │
│                                                                        │
│  5. ASSERTION CONTROL [CTRL]                                           │
│     $assertoff at reset │ $asserton after init │ $assertkill           │
│     $assertcontrol levels │ cover-of-assertions │ $global_clock        │
│                                                                        │
└────────────────────────────────────────────────────────────────────────┘

Key takeaways

  • Local variables are the only way to check data integrity across variable latency — $past needs a fixed delay.

  • Multiclocked sequences glue subsequences with ##1/##0 at clock changes; most sequence operators are single-clock only.

  • expect is a blocking procedural wait on a property — testbench code, not a checker.

  • checker packages assertions, modeling code, and default clocking into one bindable, reusable unit.

  • $assertoff/$asserton around reset is standard methodology — assertions on X-state logic produce noise, not information.