I am faced with the following situation:
I have RTL written entirely in Verilog and the test environment for it is in SystemVerilog. The RTL has a FIFO component which is instantiated multiple times in the design at different levels of hierarchy. For example:
One FIFO instance : dut_top_level.sub_component.fifo
Other FIFO instance: dut_top_level.sub_component.sub_sub_component.fifo
And many such instances of FIFO at different hierarchical levels.
I want to write assertions for this FIFO but I don’t want them to be in-line i.e. embedded in the Verilog RTL code. I want to keep the Verilog code and SystemVerilog code separated. In such case, I will have to access the the FIFO signals, on which I have to write assertions, hierarchically. However, this approach will mean that I will have to write same set of assertions for each FIFO instance which is not quite feasible.
I was therefore, looking for a way to write the assertions only once and apply them to each of the instances of the FIFO. Is there a way I could do this?
Thanks for your response Dave. Yes, I actually thought about using the ‘bind’ construct. However, as per my 1st example above for FIFO instance (dut_top_level.sub_component.fifo), I will have to use the bind construct inside module sub_component. In this case, module sub_component is in Verilog. As I have mentioned, I want to keep SystemVerilog code separate from Verilog. Since ‘bind’ is a SystemVerilog specific construct, I won’t be able to use it inside the Verilog code.
Why do you think the bind construct must be inside the module sub_component? You can use bind to instantiate an assertion in all instances of FIFO from any SystemVerilog module.
Thanks aming, but including the file having SV assertions inside a Verilog RTL file doesn’t serve the purpose. As I have mentioned, I want to keep the Verilog and SV codes separate and not mix them.
May be I have not understood the bind construct that well. Could you please show me through an example (possibly using the FIFO example I have used above) as to how I could do this?
Please note that in my example above, dut_top_level, sub_component, sub_sub_component and fifo are all Verilog modules. There is a top level SystemVerilog testbench module named top_level_tb which instantiates dut_top_level and where I would want to instantiate the module containing assertions for FIFO named fifo_assertions. So, the hierarchy in terms of top level testbench would be something like this:
top_level_tb.dut_top_level
top_level_tb.fifo_assertions
Thus, the FIFO signals are not directly accessible in the top level testbench. In such case, to access the FIFO signals in top level testbench (for each of the FIFO instances), won’t I have to use the hierarchical paths? Please correct me if I am wrong.
I would really appreciate if you provide me with an example.
Maybe you need to show an example of what the design looks like without the bind. I don’t understand why you want to instantiate the module fifo_assertions inside the top level testbench. I thought you only wanted to instantiate the fifo_assertions inside the module FIFO. Also, once you have started using SystemVerilog, there is no longer a distinction between Verilog and SystemVerilog modules; it’s all one language. The bind construct can target any module regardless of whether it was originally coded for Verilog, and regardless of where in the hierarchy it is.
Thanks Dave for your elaborate explanation; I really appreciate it. I have one question:
In which module exactly should I be writing the statement bind FIFO fifo_assertions fa_1(Full,Empty);?
Although you can place them in any module as long as there is no module instance recursion, the best place to put bind statements is an another top-level module.
If you are going to have a large number of bind statements, you could break the statements up into several `included files, or create a nested set of module instances with bind statements.
In reply to sva_user:
Maybe you need to show an example of what the design looks like without the bind. I don’t understand why you want to instantiate the module fifo_assertions inside the top level testbench. I thought you only wanted to instantiate the fifo_assertions inside the module FIFO. Also, once you have started using SystemVerilog, there is no longer a distinction between Verilog and SystemVerilog modules; it’s all one language. The bind construct can target any module regardless of whether it was originally coded for Verilog, and regardless of where in the hierarchy it is.
So if your FIFO is
Now when ever a FIFO is instantiated, another fifo_assertions module is instantiated underneath it.
Hi Dave,
I have followed what you said about bind assertions in the testbench top level, but how do I switch these assertions off in UVM testcase, because $assertoff doesn’t seem able to switch assertions off anymore?
I use following bind statment before:
bind dut.inst_sub_module.inst_sub_sub_module.inst_FIFO FIFO_assertionin inst_bind(.*);
and switch all assertions off in uvm testcase run phase with “$assertoff(0);”
In reply to cw948:
Personally, I would write a systemverilog checker where I define the assertions, and then instance the checker in the fifo. This approach allows you to modify the checker to your heart desire, and the checker is ignored by synthesis.
The checker can be bound (like a module), but there really is no need for this.
Ben Ben@systemverilog.us
how to switch assertions off in UVM testcase class, where assertions are binded in UVM testbench top level and are attached to the DUT.sub_module.sub_sub_modules.
In reply to ben@SystemVerilog.us:
thank for your reply, Ben
how to switch assertions off in UVM testcase class, where assertions are binded in UVM testbench top level and are attached to the DUT.sub_module.sub_sub_modules.
Thanks,
Chao
Below is test code. My preference in approaching this problem are the following:
Design a checker with a declared mode bit (e.g., tmode) that if ==0, the checker with fire an $assertcontrol(OFF);
When your DUT is instantiated (e.g., fifo1, fifo2) you can access the tmode bit form a task through the hierarchical path; that will cause the assertions within that particular checker to be OFF or ON
That concept can be used with instances created with the bind statement.
The model below uses a module, as an example, with the ON/OFF control issued from an initial statement. Again, that can be done from a task or other statements.
import uvm_pkg::*; `include "uvm_macros.svh"
checker ck(bit clk, a, b, c);
let ON = 3; // assertion control type
let OFF = 4; // assertion control type
bit tmode=1;
ap: assert property(@(posedge clk) a);
// $assertcontrol ( control_type [ , [ assertion_type ] [ , [ directive_type ]
// [ , [ levels ] [ , list_of_scopes_or_assertions ] ] ] ] ) ;
always_ff @(posedge clk) if(tmode==0) $assertcontrol(OFF);
else $assertcontrol(ON);
endchecker
module fifo(input bit clk, a, b,
output c);
bit k, w;
ck ck1(clk, a, b, c);
endmodule
module top;
bit clk, a, b, c;
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
fifo fifo1(.*);
initial begin
#500 // fifo1.ck1.mode=0;
fifo1.ck1.tmode=0;
end
initial begin
repeat(200) begin
@(posedge clk);
if (!randomize(a, b) with
{ a dist {1'b1:=1, 1'b0:=3};
b dist {1'b1:=1, 1'b0:=2};
}) `uvm_error("MYERR", "This is a randomize error")
end
$stop;
end
endmodule