首先要注意的是 disable iff (rst) 子句是异步的。因此,它不遵守常规的断言采样规则。
来自 LRM:
禁用 iff 的表达式称为禁用条件。disable iff 子句允许指定抢先式重置。对于 property_spec 的评估,存在对基础 property_expr 的评估。如果禁用条件在已观察区域中的尝试开始(含)和评估尝试结束(含)之间的任何时间为真,则属性的整体评估将导致禁用。如果属性由于禁用 iff 条件而被抢占,则该属性已禁用评估。禁用条件中使用的变量值是当前仿真周期中的变量值,即未采样。
在您的情况下,对于重置之前的每个周期,都会为您的断言生成一个新线程。一旦重置出现,所有这些实例都被禁用并且它们的属性评估被暂停。任何新的评估只会在重置被取消断言后开始。因此,我看不出这如何成为您的问题的原因。
但是,我可以提出两个可能导致您的问题的问题: 1. 在您的 sim Signal_ia 的开头是 'X. 在 20 个周期后,如果尚未断言复位,则前面的序列 $stable(Signal_ia) 将评估为真,并且断言将立即转移到评估后续序列 Signal_oq==Signal_ia (在同一个周期中,因为非重叠暗示是用过的)。如果这两个信号都是'X,则 1'X == 1'X 评估为 1'X,因此断言将失败。2. 您提到您希望在第 21 个周期进行检查。然而,这个断言实际上会在第 20 个周期检查。如果有 20 次触发器,此时输出仍将是 'X,即使输入已 0 持续 20 个周期。
我怀疑选项 1. 更有可能,因为 2. 可能很明显。
为了解决这两个问题,我建议您更改断言以在输入更改时触发以解决此问题。
CHECK_OUTPUT: assert property(@(posedge ClkRs_ix.clk)
disable iff (ClkRs_ix.reset) $changed(Signal_ia) |=>
$stable(Signal_ia)[*20] ##0 (Signal_oq==Signal_ia));
正如所指出的,您还可以有选择地启用断言。$asserton 和 $assetkill (assertoff) 可以帮助你做到这一点:
$asserton[(levels[, list])] 等价于 $assertcontrol(3, 15, 7, levels [,list]) — $assertoff[(levels[, list])] 等价于 $assertcontrol(4, 15 , 7, levels [,list]) — $assertkill[(levels[, list])] 等价于 $assertcontrol(5, 15, 7, levels [,list])
assertkill 将杀死任何已经在运行的线程(与 asseroff 相反,它只会阻止未来的线程)。在我看来,你会在 assertkill 之后。然后,您可以通过 asserton 重新启用您的断言。
正如所指出的,在正式场景中,这自然需要通过断言中的控制信号和 FSM 来生成它来实现。