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

时间:2017-10-30 08:32:29

标签: 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个周期输出必须与输入具有相同的值。

这个有效,但前提是我确保在复位期间Signal_ia的状态没有变化。如果我断言复位,改变Signal_ia的状态,然后释放复位,这种情况总是失败。这通常发生在我使用Signal_ia ='X'开始模拟时,并且在复位期间它变为'0'。

有什么方法可以更好地写出来吗? RESP。是否有一种方法可以在复位后忽略第一个事件,因为它可能因重置时发生的情况而跳闸?如果我理解得很好,iff保证在复位期间忽略该断言。我试图描述的效果有一些延迟,理想情况下我不仅要在复位时忽略这个条件,而且还要在复位状态无效后的20个周期内忽略这个条件。

感谢 .D。

2 个答案:

答案 0 :(得分:1)

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

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)

换句话说,在A发生之前,请不要检查B |-> C

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

答案 1 :(得分:1)

首先要注意的是,禁用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,则X == 1' X评估为1' X,因此断言将失败。 你提到你想要在第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(断言)可以帮助你做到这一点:

   $ asserton [(levels [,list])]相当于$ assertcontrol(3,15,   7,level [,list]) - $ assertoff [(levels [,list])]相当于   $ assertcontrol(4,1​​5,7,levels [,list]) - $ assertkill [(levels [,   list])]相当于$ assertcontrol(5,15,7,levels [,list])

assertkill会杀死任何已经运行的线程(而不是asseroff,这只会阻止将来的线程)。对我来说,你会在断言之后。然后,您可以通过asserton重新启用断言。

正如所指出的那样,在正式场景中,自然需要通过断言中的控制信号和生成它的FSM来实现。