System verilog systemverilog断言-如何在重置后忽略第一个事件

System verilog systemverilog断言-如何在重置后忽略第一个事件,system-verilog,system-verilog-assertions,System Verilog,System Verilog Assertions,我写了以下断言: assert property(@(posedge ClkRs_ix.clk) disable iff (ClkRs_ix.reset) $stable(Signal_ia)[*20] |-> (Signal_oq==Signal_ia)); 我想表达20个时钟周期,输入信号是稳定的,在第21个周期,输出必须与输入具有相同的值 这一个工作,但只有当我保证在复位期间信号_ia的状态没有变化时。如果我断言重置,更改信号_ia的状态

我写了以下断言:

    assert property(@(posedge ClkRs_ix.clk) 
        disable iff (ClkRs_ix.reset) $stable(Signal_ia)[*20] |-> 
        (Signal_oq==Signal_ia));
我想表达20个时钟周期,输入信号是稳定的,在第21个周期,输出必须与输入具有相同的值

这一个工作,但只有当我保证在复位期间信号_ia的状态没有变化时。如果我断言重置,更改信号_ia的状态,然后释放重置,此条件总是失败。这通常发生在我用信号_ia='X'启动模拟时,在重置过程中它变为'0'

有没有办法写得更好?分别。有没有一种方法可以忽略重置后的第一个事件,因为它可能会因重置时发生的情况而跳闸?如果我理解得很好,iff保证,重置过程中会忽略此断言。我试图描述的效果有一些延迟,理想情况下,我需要忽略这种情况,不仅在重置中,而且在重置状态解除评估后的20个周期中

谢谢 .d.

一种方法是使用级联蕴涵运算符:

assert property(@(posedge ClkRs_ix.clk) 
    disable iff (ClkRs_ix.reset) $stable(Signal_ia)[*20] |-> 
    $stable(Signal_ia)[*20] |-> (Signal_oq==Signal_ia));
蕴涵算子是右联想算子

相当于

A |-> (B |-> C)
换句话说,在A出现之前不要检查
B |->C


实现这一点的另一种方法是使用卫星代码。附属代码是用宿主语言编写的代码,有助于断言。所以,您可以编写一个FSM来检测第一个“事件”的首次出现,然后启用断言。如果希望能够在正式工具中检查断言,请确保卫星代码是可合成的。

首先要注意的是,disable-iff(rst)子句是异步的。因此,它不遵守常规断言采样规则

来自LRM:

禁用iff的表达式称为禁用条件。这个 disable iff子句允许指定抢占式重置。为了 属性的评估\u spec,有一个 基础属性_expr。如果禁用条件在任何时候为真 在观察区域内开始尝试之间,包括, 以及评估尝试的结束,包括在内,然后是总体评估 对属性的评估将导致禁用。一处房产已被出售 如果由于禁用iff而被抢占,则禁用评估 条件 禁用条件中使用的变量值为 当前模拟周期,即未采样

在您的情况下,对于重置之前的每个周期,都会为您的断言生成一个新线程。一旦发生重置,所有这些实例都将被禁用,其属性评估将被挂起。只有在重置被取消断言后,才会开始任何新的评估。因此,我不明白这怎么会是你的问题的原因

但是,我可以提出两个可能导致您出现问题的问题: 1.在sim卡信号开始时,信号_ia为“X”。在20个周期后,如果重置未被断言,则先前序列$stable(信号_ia)将计算为true,断言将立即移动到计算后续序列信号_oq==信号_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[(级别[,列表])相当于$assertcontrol(3,15, 7,级别[,列表]-$assertoff[(级别[,列表])相当于 $assertcontrol(4,15,7,级别[,列表])-$assertkill[(级别[,列表]), 列表]]相当于$assertcontrol(5、15、7、级别[,列表])

assertkill将杀死所有已经运行的线程(与asseroff相反,asseroff只会阻止未来的线程)。我觉得你是在追求assertkill。然后可以通过asserton重新启用断言


如前所述,在正式场景中,这自然需要通过断言中的控制信号和FSM来实现。

在整个模拟中,该断言将等待20个信号时钟,然后再次等待20个信号时钟,然后比较信号。我相信它将检查40个时钟的稳定性。正如您所提到的,编写一些粘合逻辑可能是更好的选择。@sharvill111我的想法与您不同。我认为这个断言将等待20个时钟的信号_ia,然后每隔20个时钟的信号_ia,比较信号。我想提问者需要实现它并尝试一下。然而,多亏了你的评论,我现在确实看到了我狡猾的计划中的一个缺陷:在每20个信号时钟之后,就会有一个新线程启动,因此在模拟结束时,将会有无数并发线程运行。所以,在这种情况下,正如您所说,编写一些粘合逻辑可能是更好的选择,因为如果没有其他选择的话。
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));