2个问题
答案 0 :(得分:4)
关于问题1.非阻塞分配不一定意味着顺序行为。阻塞/非阻塞分配是模拟构造。让我们看一个小例子来更好地理解它:
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
会更新。
必须指定灵敏度列表有点多余,因为如果我们知道我们需要组合逻辑,那么只要赋值右侧的某些内容发生变化,我们就应该重新触发该过程。这是always_comb
的用途。
我们可以使用always_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
现在是有趣的部分。我们可以使用always_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 = 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
请注意,在第一个步骤中,我们有3个打印,而不是一个。让我们仔细看看这里发生的事情。首先,我们更改a
,但c
和d
尚未更新。其次,c
会更新,但d
保持不变。这是因为c
上的非阻止分配,导致d
“看到”c
的“旧”值。第三,在c
正式更新后,该工具会在d
上安排更新,我们会看到第一次打印的最后一次打印。其余部分与之前的情况相同。
请记住,从上一段开始,只要作业右侧的某些内容发生变化,always_comb
就会重新触发。这里的诀窍是这个always_comb
实际上表现得像:
always @(a or b or c) begin
c <= a || b;
d <= a && c;
end
这是非标准的Verilog,但仍然会模拟相同的逻辑。请注意,c
已明确添加到敏感度列表中。如果我们省略这个,那么我们将描述一个锁存器。不鼓励这种风格,因为它很容易出错(即忘记将中间逻辑节点添加到灵敏度列表中)。
这里的关键点是阻塞或非阻塞分配既不描述顺序逻辑也不描述组合逻辑。它是整个上下文(即确定何时执行的敏感性列表),用于控制从代码中推断出的逻辑电路。
EDAPlayground上提供了完整的代码示例。
关于问题2.这是特定于工具的,这不是此论坛。你应该在供应商的网站上问这个。