System Verilog Assertion Binding (SVA Bind)
Nowadays we use to deal with modules of Verilog or VHDL or a combination of both. Mostly verification engineers are not allowed to modify these modules. But still, SVA addition to these modules is required, and easy to verify a lot of RTL functionality. How can you add SVA to these modules? Let’s find out !!
Here is where System Verilog ‘bind’ comes into the picture. Generally, you create an SVA bind file and instantiate sva module with the RTL module.SVA bind file requires assertions to be wrapped in a module that includes the port declaration, So now let’s understand this with a small example to understand basic things on how to use SVA bind
module DUT_dummy (output logic [7:0] out,
output logic x,
input logic wr, rd, clk, rst,
input logic [7:0] in);
//DUT Logic
...
...
...
endmodule : DUT_dummy
module SVA_dummy (input [7:0] out, in,
input x,
input wr, rd, clk, rst_n);
ASSERTION1_NAME:
`assert_async_rst(!rst_n |-> ...
ASSERTION2_NAME:
`assert_clk (x > 1 |-> out);
...
endmodule : SVA_dummy
module TB();
logic [7:0] out;
logic x;
logic wr, rd, clk, rst;
logic [7:0] in;
//Instantiation
DUT_dummy DUT_U1 (.*);
//Binding with SVA using implicit port connection
bind DUT_dummy : DUT_U1 SVA_dummy sva (.*);
...
...
endmodule : TB
Here, you can see that there is a DUT instantiation created DUT_u1 instance of DUT_dummy. Now the point of interest for us would be, how to bind the DUT instance to the SVA module.
To understand this take a look at an example where you could see the ‘bind’ keyword used with the DUT_dummy module and SVA_dummy. This is the place where we are binding the DUT module with the SVA module. Thus passing DUT signal information to the SVA module. With this, we could play around with the DUT signal and can check assertion properties using DUT signals available through this instantiation. If the assertion module uses the same signal names as the target module, the bind file port declarations are still required but the bind-instantiation can be done using the SystemVerilog (.*) implicit port connections that you can see in the example. If signal names are not exactly matching between target and bind file module then we need to expand the instantiation with respected port names.
Binding assertions to both modules and interfaces: Let’s say you have an interface called Initiator
and a module called Target
. You want to write an assertion that ensures that the Initiator
interface always sends a request before sending a response. You can write this assertion in a separate file called assertions.sv
. Then, you can bind the assertion to both the Initiator
interface and the Target
module using the following code:
module Initiator;
...
bind assertions.sv Initiator;
...
endmodule
module Target;
...
bind assertions.sv Target;
...
endmodule
This way, the assertion will be checked for both the Initiator
interface and the Target
module.
Binding assertions to specific instances of modules and interfaces: Let’s say you have a design that has two instances of the Target
module. You want to write an assertion that ensures that the first instance of the Target
module always sends a request before sending a response, but the second instance of the Target
module does not need to follow this rule. You can write this assertion in a separate file called assertions.sv
. Then, you can bind the assertion to the first instance of the Target
module using the following code:
module Target1;
...
bind assertions.sv Target1;
...
endmodule
module Target2;
...
// No binding needed for Target2
...
endmodule
This way, the assertion will only be checked for the first instance of the Target
module.
Binding assertions to multiple signals in a module or interface: Let’s say you have a module called Counter
that has two signals called count
and reset
. You want to write an assertion that ensures that the count
signal is always incremented by 1 when the reset
signal is low. You can write this assertion in a separate file called assertions.sv
. Then, you can bind the assertion to the count
and reset
signals using the following code:
module Counter;
...
bind assertions.sv count, reset;
...
endmodule
This way, the assertion will be checked for the count
and reset
signals whenever they are accessed in the Counter
module.
Binding assertions to variables in a module or interface: Let’s say you have a module called StateMachine
that has a variable called state
. You want to write an assertion that ensures that the state
variable always changes to a specific value when a certain event occurs. You can write this assertion in a separate file called assertions.sv
. Then, you can bind the assertion to the state
variable using the following code:
module StateMachine;
...
bind assertions.sv state;
...
endmodule
This way, the assertion will be checked for the state
variable whenever it is changed in the StateMachine
module.
I hope these examples help to clarify how SVA Bind can be used to achieve the benefits mentioned above.