SystemVerilog Assertions Basics
SystemVerilog Assertions Basics
VERILOG
SSERTIONS
BASICS
SystemVerilog Assertions Basics
Introduction
An assertion is a statement about your design that you expect to be true always.
For example, let's assume your design specification has the following 2 rules:
1. Every time the request req goes high, ack arrives exactly 3 clocks later
2. Every time the valid signal vld is high, the cnt is incremented
This is how you would express the above statements using SVA.
Now, when you run a functional simulation, these assertions are monitored by the
simulator and if the RTL violates an assertion the simulator reports an error. This is how
easy and concise it is to write checkers using SVA.
Let's begin with the types of assertions - there are two of them.
Immediate Assertions
As the simulation test runs, the simulator continuously checks the expression
within assert(). If it returns false, the error message is printed. I usually skip the error
message because the simulator prints a default message with the assertion name in the
absence of a custom error message.
Concurrent Assertions
Concurrent assertions let you describe more complex expressions that span time and are
triggered relative to a clock edge.
The keyword property distinguishes an immediate from a concurrent assertion. There are
two formats
if (rst) begin
end else begin
if (assertion expression)
// do nothing;
else
$error("fail");
end
end
end
As you write assertions for your design, you'll find yourself using concurrent assertions a lot
more frequently than immediate assertions.
Implication Operator
When you look at examples of concurrent assertions, you'll see |-> and |=> operators
frequently used. These are called implication operators and the LHS of the operator is
called the antecedent and the RHS is called the consequent.
Consider the following example waveform. The code below shows how to express this
waveform with |-> and |=>.
To keep code readable and consistent, you could just stick to using the |-> operator.
System Functions & Operators
Examples from the previous sections briefly introduce the implication operator
and $past() system function. The tables below list some more useful tools that let you
write assertion expressions.
Function Use
$rose returns true if the LSB of the expression changed to 1. Otherwise,
it returns false.
$fell returns true if the LSB of the expression changFunctioned to 0.
Otherwise, it returns false.
$stable returns true if the value of the expression did not change.
Otherwise, it returns false.
$past(expression, Returns value of expression from num_cycles ago
num_cycles)
$countones Returns the number of 1s in an expression
$onehot Returns true if exactly one bit is 1. if no bits or more than one bit
is 1, it returns false.
$onehot0 Returns true is no bits or just 1 bit in the expression is 1
$isunknown Returns true if any bit in the expression is 'X' or 'Z'
SVA operators
Operator Use
##n ##[m:n] Delay operators - Fixed time interval and Time inteval range
!, ||, && Boolean operators
|-> Overlapping implication
|=> Nonoverlapping implication
not, or, and Property operators
Repetition operators
Operator Use
[*n] [*m:n] Continuous repetition operator. The expression repeats continuously for
the specified range of cycles.
[->n] [- Go to repetition operator. Indicates there's one or more delay cycles
>m:n] between each repetition of the expression. a[->3] is equivalent to (!a[*0:$] ##1
a) [*3]
[=n] [=m:n] Non-consecutive implication. a[=3] is equivalent to (!a[*0:$] ##1 a ##1 !a[*0:$])
[*3]
Assertion Examples
Here is a set of commonly used code patterns which represent how assertions
can be used.
In SVA, cover points are written exactly the same way as assertion expressions.
By replacing the assert keyword with cover, you ask the simulator tool to update the
coverage database if that expression is true.
Apart from the implication operators, |-> & |=>, all other system functions and
Boolean operators from Tables 1 & 2 can be used in cover property expressions.
Cover Examples
// Use generate statement to cover all combinations of vld inputs
generate
for (i=0; i < 16; i++) begin: CVR
CovVld: cover property (@(posedge clk) {vld3, vld2, vld1, vld0} ==
i);
end
endgenerate
property CovRepeat1;
@(posedge clk) disable iff (rst)
(a[*2] ##2 b[->3:4] ##1 c ##1 d[=3] ##1 e);
endproperty
CovRepeat1_C: cover property (CovRepeat1);
property CovSimpleKey;
@(posedge clk) disable iff (rst)
(key == 512'd0 & key_valid == 1'd0) ##16 (key == fixed_key1 & key_valid
== 1'd1) ##1
(key == 512'd0 & key_valid == 1'd0) ##64 (key == fixed_key2 & key_valid
== 1'd0);
endproperty
CovSimpleKey_W: cover property (CovSimpleKey);
Using `include
Place assertions in a separate file and `include that file at the end of your design
module.
/* File name : bus_arbiter.sv */
// Design module
module bus_arbiter (
input logic clk,
input logic rst,
input logic [7:0] a,
input logic a_vld,
input logic [7:0] b,
input logic b_vld,
output logic [7:0] c);
endmodule: bus_arbiter
property valid_state;
@(posedge clk) disable iff (rst)
$onehot0(current_state);
endproperty
prop_valid_state: assert property (valid_state);
Using bind
But, there's a more powerful way to insert assertions into your design -- using the
SystemVerilog bind directive.
Place assertions and cover properties in a separate module, then bind this
assertions module to one instance or all instances of a design module. This is my
favorite method and I use it a lot.
The bind syntax works as follows:
within
module design_module;
endmodule
The added advantage with bind is that, you can link your assertions to a specific instance
of the module using XMR (cross-module reference). If you `include the assertions as in
#2 above, the assertions will be run against all instances of that module. Which may not
be your intention.
Here's the example from #1 written once again, but using bind
/* File name : bus_arbiter.sv */
// Design module
module bus_arbiter (
input logic clk,
input logic rst,
input logic [7:0] a,
input logic a_vld,
input logic [7:0] b,
input logic b_vld,
output logic [7:0] c);
property valid_state;
@(posedge clk) disable iff (rst)
$onehot0(current_state);
endproperty
prop_valid_state: assert property (valid_state);
endmodule: bus_arb_assertions
...
bus_arbiter bus_arb_inst();
...
endmodule: tb_top