周期信号的意外 SVA 断言行为
Unexpected SVA assertion behavior for a periodic signal
引自一本书 "Systemverilog Assertions and Functional Coverage",Ashok Mehta 第 42 页,
@ (posedge clk) a |=> !a;
In the above sequence, let us say that variable ‘a’ changes to ‘1’ the same time
that the sampling edge clock goes posedge clk (and assume ‘a’ was ‘0’ before it
went to a ‘1’). Will there be a match of the antecedent ‘a’? No! Since a’ went from ‘0’ to ‘1’ the same time that clock went posedge clk, the value of ‘a’ sampled by clock will be ‘0’ (preponed region) and not ‘1’. This will not cause the property to trigger because the antecedent is not evaluated to be true. This will confuse you
during debug. You would expect ‘1’ to be sampled and the property triggered
thereof. However, you will get just the opposite result.
This is a very important point to understand because in a simulation waveform
(or for that matter with Verilog $monitor or $strobe) you will see a ‘1’ on ‘a’ with
posedge clk and would not understand why the property did not fire or why it
failed (or passed for that matter). Always remember that at the sampling edge, the
‘previous’ value (i.e. a delta before the sampling edge in the preponed region) of
the sampled variable is used.
我试图通过这个测试平台来测试这个场景。但是我预计断言会在模拟时间 #10、#50、#90
module assert_immediate();
reg a,b,clk;
initial
begin
clk = 0;
forever #10 clk = !clk;
end
initial
begin
a = 0;
b = 0;
repeat (10) @(posedge clk) a = ~a;
end
// always@(posedge clk) $display("a = %d at time %t \n", a, $time);
property p1;
@(posedge clk) a |=> !a;
endproperty
initial #100 $finish;
assert property (p1) $display("Entered assert at %t \n", $time); else $display("FAIL at %t \n", $time);
cover property (p1) $display("PASS at %t \n", $time);
endmodule
但是当我 运行 在 EDAPlayground 上使用 VCS 时,我得到了不同的行为
# KERNEL: Entered assert at 10
# KERNEL:
# KERNEL: PASS at 10
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: PASS at 90
# KERNEL:
# KERNEL: PASS at 90
为什么你认为你的断言会失败?您指示您的测试平台在 initial
块中每隔 posedge
更改 a
,这样您的断言将在触发时通过(您将有一个 a, !a, a, !a
的序列)所以我期望 2 个断言通过。
我不明白的是,根据您的日志,断言通过@时间10
。你的第一个posedge
是@时间10
,所以a
的采样值是0
(因为采样是在posedge
和你的初始值a
是 0
根据 initial
块)。 a
的值不会触发断言(不符合断言的前身,即断言的左侧)。
我认为那里有 2 个问题。
- 我认为蕴涵运算符存在误解。在你的情况下断言不应该失败。蕴涵允许右边的表达式最终为真。所以,如果
a
上升,它最终会下降。因此,在 #50,它在 #30 采样高后下降,这导致断言通过,并进入下一个评估周期:#70 -> #90。
For each successful match of the antecedent sequence_expr, the consequent property_expr isseparately evaluated. The end point of the match of the antecedent sequence_expr is the start pointof the evaluation of the consequent property_expr.
- 您使用的编译器存在错误。在时间#10 不应有断言消息。我用 vcs 2017.03 试过了,它工作正常。
您也可以将此行添加到您的代码中以获得一些调试打印:
always @(posedge clk) $display("%0t a = %b", $time, $sampled(a));
我在模拟过程中得到了这些结果:
10 a = 0
30 a = 1
50 a = 0
Entered assert at 50
PASS at 50
70 a = 1
90 a = 0
Entered assert at 90
PASS at 90
引自一本书 "Systemverilog Assertions and Functional Coverage",Ashok Mehta 第 42 页,
@ (posedge clk) a |=> !a; In the above sequence, let us say that variable ‘a’ changes to ‘1’ the same time that the sampling edge clock goes posedge clk (and assume ‘a’ was ‘0’ before it went to a ‘1’). Will there be a match of the antecedent ‘a’? No! Since a’ went from ‘0’ to ‘1’ the same time that clock went posedge clk, the value of ‘a’ sampled by clock will be ‘0’ (preponed region) and not ‘1’. This will not cause the property to trigger because the antecedent is not evaluated to be true. This will confuse you during debug. You would expect ‘1’ to be sampled and the property triggered thereof. However, you will get just the opposite result. This is a very important point to understand because in a simulation waveform (or for that matter with Verilog $monitor or $strobe) you will see a ‘1’ on ‘a’ with posedge clk and would not understand why the property did not fire or why it failed (or passed for that matter). Always remember that at the sampling edge, the ‘previous’ value (i.e. a delta before the sampling edge in the preponed region) of the sampled variable is used.
我试图通过这个测试平台来测试这个场景。但是我预计断言会在模拟时间 #10、#50、#90
module assert_immediate();
reg a,b,clk;
initial
begin
clk = 0;
forever #10 clk = !clk;
end
initial
begin
a = 0;
b = 0;
repeat (10) @(posedge clk) a = ~a;
end
// always@(posedge clk) $display("a = %d at time %t \n", a, $time);
property p1;
@(posedge clk) a |=> !a;
endproperty
initial #100 $finish;
assert property (p1) $display("Entered assert at %t \n", $time); else $display("FAIL at %t \n", $time);
cover property (p1) $display("PASS at %t \n", $time);
endmodule
但是当我 运行 在 EDAPlayground 上使用 VCS 时,我得到了不同的行为
# KERNEL: Entered assert at 10
# KERNEL:
# KERNEL: PASS at 10
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: PASS at 90
# KERNEL:
# KERNEL: PASS at 90
为什么你认为你的断言会失败?您指示您的测试平台在 initial
块中每隔 posedge
更改 a
,这样您的断言将在触发时通过(您将有一个 a, !a, a, !a
的序列)所以我期望 2 个断言通过。
我不明白的是,根据您的日志,断言通过@时间10
。你的第一个posedge
是@时间10
,所以a
的采样值是0
(因为采样是在posedge
和你的初始值a
是 0
根据 initial
块)。 a
的值不会触发断言(不符合断言的前身,即断言的左侧)。
我认为那里有 2 个问题。
- 我认为蕴涵运算符存在误解。在你的情况下断言不应该失败。蕴涵允许右边的表达式最终为真。所以,如果
a
上升,它最终会下降。因此,在 #50,它在 #30 采样高后下降,这导致断言通过,并进入下一个评估周期:#70 -> #90。
For each successful match of the antecedent sequence_expr, the consequent property_expr isseparately evaluated. The end point of the match of the antecedent sequence_expr is the start pointof the evaluation of the consequent property_expr.
- 您使用的编译器存在错误。在时间#10 不应有断言消息。我用 vcs 2017.03 试过了,它工作正常。
您也可以将此行添加到您的代码中以获得一些调试打印:
always @(posedge clk) $display("%0t a = %b", $time, $sampled(a));
我在模拟过程中得到了这些结果:
10 a = 0
30 a = 1
50 a = 0
Entered assert at 50
PASS at 50
70 a = 1
90 a = 0
Entered assert at 90
PASS at 90