System verilog 系统verilog 2012参考指南中关于always_comb中非阻塞的错误?和延迟断言属性标记?
2个问题System verilog 系统verilog 2012参考指南中关于always_comb中非阻塞的错误?和延迟断言属性标记?,system-verilog,system-verilog-assertions,System Verilog,System Verilog Assertions,2个问题 在system verilog 2012参考指南中,有一个参考文件提到在始终梳中对顺序逻辑进行编码,这是可能的,因为始终梳块没有时钟参考文件-如这里所示->[在始终梳中的顺序逻辑] 在Synopsys Verdi中使用系统verilog断言时,是否可能在满足属性后,在半个或一个时钟周期后触发绿色箭头(表示已满足断言的属性) 谢谢:关于问题1,D。非阻塞分配不一定意味着顺序行为。阻塞/非阻塞分配是一种模拟构造。让我们看一个小例子来更好地理解它: module some_gate(
始终梳
中对顺序逻辑进行编码,这是可能的,因为始终梳
块没有时钟参考文件-如这里所示->[在始终梳
中的顺序逻辑]谢谢:关于问题1,D。非阻塞分配不一定意味着顺序行为。阻塞/非阻塞分配是一种模拟构造。让我们看一个小例子来更好地理解它:
module some_gate(
input logic a,
input logic b,
output logic c,
output logic d
);
// c is 'a or b'
// d is 'a and c'
endmodule
我们有两个输入信号和两个输出信号。我们想模拟一个复合浇口
在经典的Verilog风格中,我们将编写以下内容:
always @(a or b) begin
c = a || b;
d = a && c;
end
这意味着,每当a
或b
发生变化时,计算c
和d
的值。因为我们对c
使用了阻塞赋值,所以我们在这里计算的值会“传播”到d
的计算中。这本质上意味着我们将d
描述的逻辑链接到c
的逻辑之后
我们可以使用一个小测试台来测试这一点:
module test;
logic a, b, c, d;
some_gate dut(.*);
always @(a or b or c or d)
$display("[%0d] a = %b, b = %b, c = %b, d = %b", $time(), a, b, c, d);
initial begin
#1 a = 1;
#1 b = 1;
#1 a = 0;
#1 $finish();
end
endmodule
如果我们对此进行模拟,我们将得到:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
这是因为变量的每次更改都会触发一次显示过程<代码>a从x
更改为1
,但c
尚未更新。然后c
和d
在同一时间步中得到更新。稍后,我们更改b
,但这不会触发c
或d
上的任何更改。然后,我们再次更改a
,稍后在同一时间片中,d
得到更新
必须指定敏感度列表有点多余,因为如果我们知道我们需要组合逻辑,我们应该在赋值右侧的某些内容发生变化时重新触发该过程。这就是始终\u comb
的用途
我们可以使用always\u comb
重新编写代码,只需去掉敏感度列表:
always_comb begin
c = a || b;
d = a && c;
end
运行此代码将导致相同的打印:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
现在是有趣的部分。我们可以使用始终\u comb
和非阻塞分配对完全相同的电路进行建模:
always_comb begin
c <= a || b;
d <= a && c;
end
请注意,在第一个时间步骤中,我们有3个打印,而不是一个。让我们仔细看看这里发生了什么。首先,我们更改了a
,但是c
和d
尚未更新。其次,c
得到更新,但d
保持不变。这是因为c
上的非阻塞赋值导致d
看到c
的“旧”值。第三,在c
正式更新后,该工具计划在d
上进行更新,我们第一次看到最后一次打印。其余情况与前面的情况相同
请记住上一段中的内容,总是_comb
在任务右侧的内容发生变化时重新触发。这里的诀窍是,这个总是\u comb
实际上表现为:
always @(a or b or c) begin
c <= a || b;
d <= a && c;
end
始终@(a、b或c)开始
关于问题1,c。非阻塞分配不一定意味着顺序行为。阻塞/非阻塞分配是一种模拟构造。让我们看一个小例子来更好地理解它:
module some_gate(
input logic a,
input logic b,
output logic c,
output logic d
);
// c is 'a or b'
// d is 'a and c'
endmodule
我们有两个输入信号和两个输出信号。我们想模拟一个复合浇口
在经典的Verilog风格中,我们将编写以下内容:
always @(a or b) begin
c = a || b;
d = a && c;
end
这意味着,每当a
或b
发生变化时,计算c
和d
的值。因为我们对c
使用了阻塞赋值,所以我们在这里计算的值会“传播”到d
的计算中。这本质上意味着我们将d
描述的逻辑链接到c
的逻辑之后
我们可以使用一个小测试台来测试这一点:
module test;
logic a, b, c, d;
some_gate dut(.*);
always @(a or b or c or d)
$display("[%0d] a = %b, b = %b, c = %b, d = %b", $time(), a, b, c, d);
initial begin
#1 a = 1;
#1 b = 1;
#1 a = 0;
#1 $finish();
end
endmodule
如果我们对此进行模拟,我们将得到:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
这是因为变量的每次更改都会触发一次显示过程<代码>a
从x
更改为1
,但c
尚未更新。然后c
和d
在同一时间步中得到更新。稍后,我们更改b
,但这不会触发c
或d
上的任何更改。然后,我们再次更改a
,稍后在同一时间片中,d
得到更新
必须指定敏感度列表有点多余,因为如果我们知道我们需要组合逻辑,我们应该在赋值右侧的某些内容发生变化时重新触发该过程。这就是始终\u comb
的用途
我们可以使用always\u comb
重新编写代码,只需去掉敏感度列表:
always_comb begin
c = a || b;
d = a && c;
end
运行此代码将导致相同的打印:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
现在是有趣的部分。我们可以使用始终\u comb
和非阻塞分配对完全相同的电路进行建模:
always_comb begin
c <= a || b;
d <= a && c;
end
请注意,在第一个时间步骤中,我们有3个打印,而不是一个。让我们仔细看看这里发生了什么。首先,我们更改了a
,但是c
和d
尚未更新。其次,c
得到更新,但d
保持不变。这是因为c
上的非阻塞赋值导致d
看到c
的“旧”值。第三,在c
正式更新后,该工具计划在d
上进行更新,我们第一次看到最后一次打印。其余内容与上一个ca中的内容相同