1.compile添加选项-assert enable_diag之后对应的下列run的选项才能使用:
对应dump_fsdb_vcs.tcl需要加上fsdbDumpSVA来加入对断言波形的dump。
加上fsdbDumpSVA这样我们可以在波形中直接拉出assert的波形,此波形上会显示断言开始和失败的位置,我们也可以使用ASSERTION DEUBG mode查看断言的相关统计。比如下图中的assert1:
4.关于-assert hier选项的使用:
A.-assert hier后面需要跟一个文件,文件里面写上对于各个断言的使能控制。如果不使用这个选项,默认所有断言是使能的,这样可能打印出来信息较多,不利于我们debug。那么我们就可以使用此选项来disable某些断言。比如下面代码:
B.上面代码中申明有两个断言,那如果我们只希望debug其中as_inst1,那么我们可以在makefile中加上-assert hier选项:
assert.txt中这样写(注意层次要写到断言,不能只到断言所在的module。除了+/-assert方式写之外,也能按照+/- module(比如在assert.txt写-module as,则两个断言都会disable),+/- tree(比如在assert.txt写-tree test.as_inst2,则断言2会被disable,注意这里是写到断言所在module)方式写,另外可以用//来注释):
make之后log如下,看到只会打印as_inst2断言:
C.注意如果assert.txt中,只写+as_inst1的控制不对as_inst2做控制,那么默认as_inst2是关闭的。如下:
log:
D.注意如果assert.txt中,只写-as_inst1的控制不对as_inst2做控制,那么默认as_inst2是打开的。如下:
E.但是如果assert.txt文件是空的(没有内容)那么会报错:
F.如果想把所有assert都加上,又不想assert.txt又不能为空,那么可以在assert.txt中只写一句对不存在assert的控制。如下:inst4是不存在的(对其+/-都可以达到目的)
log:
G.也可以通过tree来跨层次整个控制一个module中assert。
比如我们将testbenchd代码改为,具有多层次的assert:testbench下有as_in_as_in_as,里面包含有一个断言as_inst5,并且还包含一个as_in_as,as_in_as中又有一个assert as_inst4:
assert.txt:
log:可以看到module as_in_as_in_as下所有assert都打开了。
即使断言没有名字,使用tree的方式也可以控制,比如在as_in_as_in_as中增加一个always控制的断言(assert.txt不变):
log中也会显示这个没有name的断言的结果:
5.注意断言的采样是采的之前的时刻,但是注意clk和disable iff是实时的。比如下面这个例子。
波形:
如下面的log,clk和disable iff是实时的,所以断言的起始点,clk都是上升沿,且sig0都是1,不用往前一个time看,但是sig1采样是往前看的,比如20000ps时,断言被触发,此时sig1为上沿,但是往前此时刻之前看sig1为0,所以断言失败。比如50000ps是断言被触发,此时sig1为0,但是往此时刻之前看,前一个时刻后面部分sig1也为0,所以断言失败。但是在60000ps时,断言被触发,此时sig0为下降沿1->0,往前此时刻之前看,sig1为1,所以断言成功。
由此可以看出断言的采样是采的之前的时刻,但是注意clk和disable iff是实时的。
6.使用disable iff和蕴含符|->,|=>可以减少比必要的报错,但是disable if是实时的,这里指的是如果disable if后面有延时,在延时后如果disable iff条件不满足,断言仍然不会执行disable iff后面的语句。比如,我们在上面代码的断言中加一个##1的延时:
断言波形会是这样:
如下log,在0和20000这里按照常理iff(~sig0)=0断言虽然会触发,但是##1延时一个周期后也就是在10000和30000时iff(~sig0)=1,此时断言由被disabable,所以断言最终是被disable的:
但是如果把disable if改为蕴含语句,那么则不会出现这种情况,比如:
波形:
如下log,0时刻没有断言触发,这个可能是因为往前采样0时刻之前状态不确定(但是disable iff是实时的,所以上面那种情况可以从0时刻开始)。比如10000ps时刻采样此时往前看sig0(注意由于没有使用disable iff,所以sig0往前采样,不再看实时的)为1,所以断言触发,一个周期后采样sig1为0(sig1也是往前看),所以断言失败。50000时刻没有断言也是因为sig0往前采样为0,所以断言没有触发:
7.断言中的延时##1这个是按照断言中所使用的时钟实时变动的。
比如下面有两个clk:
两个##1,用的时钟不同,即使其中一个clk比如clk1整个仿真过程中会变化,比如周期是变化的,那么对应##1也会跟着变化。
8.断言中采样函数。
$rose是判断时钟采样信号前后是否存在0->1/x->1/z->1的变化。
$fell是判断时钟采样信号前后是否存在1->/x->0/z->0的变化。
$stable当表达式在连续两个采样时钟周期保持不变时返回真。
$past用于检查当前表达式前一个时钟周期(注意不指定number_of_ticks,默认指向前一个时钟)值是否为真,如果为真则$past返回为真。格式$past(expression[,number_of_ticks]);
例1 $rose
波形:
如下log,在10000ps时断言触发,在此时刻$rose往前看,存在0时刻sig0从不定态到1的变化,所断言触发,或者如果在0-10000ps中存在到1的变化也会触发,见下面一个波形图。30000ps,$rose往前看,20000ps时存在sig0从0到1的变化,所以断言触发,同样60000ps也一样:
9.$assertoff,$assertkill,$asserton。
10.比较大的断言,可以拆分成小断言分别check。