RTL & verification

assertion

Picture a smoke detector wired into your design. You state a rule once — "this alarm must never go off" or "every request must get an answer within three clock ticks" — and from then on a little watcher sits there, eyes open, checking that rule on every cycle. The moment reality breaks the rule, it shrieks and points right at the spot. An assertion is exactly that: a check baked into the design that fires the instant a stated property is violated, so instead of staring at thousands of waveform cycles wondering where things went wrong, the simulator drops you at the exact time and signal where the rule first broke.

More precisely, an assertion is a statement of intent about how your hardware must behave, written so a tool can watch it continuously. The most common flavour, SystemVerilog Assertions (SVA), comes in two styles. An immediate assertion checks a plain condition at one moment in procedural code, like a guard clause. A concurrent assertion describes a relationship that unfolds over time against a clock — "if grant goes high, then within two cycles busy must follow" — and it is evaluated on every clock edge, sampling its signals just before the edge so it reads stable values rather than racing them. Because the rule lives right next to the RTL, it documents the designer's assumptions in a form that can never silently drift out of date: if the design stops honouring the assumption, the assertion fails.

The payoff is twofold. In simulation, assertions turn silent, far-downstream corruption into a loud failure caught at the source — the difference between "the output was wrong" and "the bug is here, on this signal, at this cycle." And because they are precise mathematical statements of intent, the very same assertions can be handed to a formal tool that tries to prove them true for all legal inputs, not just the stimulus your testbench happened to try. Coverage tools can also track how often each assertion's interesting cases were actually exercised, so you learn not just that nothing broke, but whether you ever really tested the rule at all.

// If req is asserted, ack must arrive within 1 to 3 cycles.
property p_req_ack;
  @(posedge clk) req |-> ##[1:3] ack;
endproperty
assert property (p_req_ack);

A concurrent assertion: after each `req`, the tool checks that `ack` follows within one to three clock cycles — and complains the moment it does not.

"Assert" here is a promise the design makes, not a debug `print`. A passing assertion stays invisibly silent for the entire run; you only ever hear from it when something is wrong — which is exactly why a thorough set of them is one of the cheapest forms of insurance in hardware design.

Also called
SystemVerilog AssertionsSVAimmediate assertionconcurrent assertion断言斷言