SVA的动态控制

SVA中提供了一些系统函数,可以在RTL设计代码或者仿真环境中用于控制断言的执行,常用的断言控制函数有:$assertoff,$asserton,$assertkill,这些函数可以指定参数,如果不指定参数那么这些函数的作用域将默认为整个设计。这些函数的使用个数如下:

$assert_task[(level[,list_of_modules_or_assertions])];

其中

assert_task可以是assertiononassertoffassertkill中的任何一个;

Level用于指定层以下哪几层设计受到函数的影响,如果level0,函数将影响指定层以下所有的设计;

list_of_modules_or_assertions指定该函数作用于哪些模块或者断言(不能指向序列,但是可以指向属性);

这几个函数的具体意义如下:

$assertoff暂时关闭所有断言的执行,如果该函数执行时断言正在执行,正在执行的断言不会被终止;

$asserton重新启动断言执行;

$assertkill将会终止设计中所有的断言,包括已经执行的断言。当遇到下一个断言需要开始执行时,该断言不会启动,除非使用$asserton启动;

【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end 
// p1 stimulus
initial begin
       sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    $assertoff;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    $asserton;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb

module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
    else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test
【仿真结果】

示例中,第一次断言在3ns处触发开始,虽然$assertoff发生6ns处,在该断言检查的过程中,但是第一次断言的执行并没有受到$assertoff影响。但是15ns处第二次断言触发,但是在第一次断言执行的过程中已经执行了$assertoff,所以第二次断言被关闭,不会执行;22ns$asserton执行,重新启动断言检查,所以之后的27ns开始的第三次断言被有效触发执行。因为$assertoff$asserton中都没有指定任何参数,所以他们的作用域是当前函数调用执行域及其以下所有层次。

【示例】

`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end 
// p1 stimulus
initial begin
       sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    $assertkill;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    $asserton;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb

module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
    else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test
【仿真结果】

该示例中,6ns$assertkill执行,虽然这时候3ns开始的断言还在执行中,但是会立即被终止其执行,即当前正在执行的断言会被$assertkill终止,而不管其是否正在执行。如果后续的断言还要继续执行,那么需要使用$asserton重新开启断言检查。

【示例】

`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end 
// p1 stimulus
initial begin
       sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    $assertoff(1,test);
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    $asserton;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb

module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
    else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test
【仿真结果】

示例中,$assertoff(1,test)表示所有例化自test的实例中的断言从6ns开始关闭,此时如果有断言正在执行将不会受到$assertoff(1,test)的影响,之后新的例化自test的实例中的断言将不再执行,直到后续$asserton重新开启断言检查。

【示例】

`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end 
// p1 stimulus
initial begin
       sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    $assertoff(0,u_dut0);
    $assertoff(1,u_dut1);
    $assertoff(1,top_tb);
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    $asserton(0,u_dut0);
    #4 sig0 = 1'b1;  // new
    #2 sig0 = 1'b0;sig1 = 1'b1;
    #2 sig1 = 1'b0;
    #2 sig2 = 1'b0;
    #2 sig2 = 1'b1;
    #6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
    else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb

module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
    $rose(sig1) ##2 $fell(sig2);
endsequence  // s
// property
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty  // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
    else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test
【仿真结果】

示例中,$assertoff(0,u_dut0);/$assertoff(1,u_dut1);/$assertoff(1,top_tb);分别将:u_dut0及其以下所有层次断言关闭;u_dut1模块内的所有断言关闭;top_tb模块内的所有断言关闭,但是不包含其下所有层次。因为u_dut2未受到影响,所以其断言检查一直有效;$asserton(0,u_dut0)重新开启了u_dut0的断言检查,所以开启后仅u_dut0的断言重新使能,而之前关闭的u_dut1top_tb断言检查并未重新启动。所以在具体设计时,一定要分清楚需要关闭的断言的层次要求,以免关闭需要的检查。




全部评论
还的是大佬,就是厉害
点赞 回复 分享
发布于 2022-09-29 17:39 河南

相关推荐

梦倩倩:同学,瞅瞅我司,医疗独角兽,校招刚开,名额有限,先到先得,****最新动态,绿灯直达,免笔试~
我的秋招日记
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务