2个问题
- 在系统 verilog 2012 参考指南中,有一个参考在 中编码时序逻辑
always_comb
,这可能吗,因为没有always_comb
块的时钟参考 - 如此处所示 -> [在中的时序逻辑always_comb
]
- 在 Synopsys Verdi 中使用系统 verilog 断言时,是否有可能在满足属性后半个或一个时钟周期后触发绿色箭头(表示满足断言的属性)
感谢:D
2个问题
always_comb
,这可能吗,因为没有always_comb
块的时钟参考 - 如此处所示 -> [在中的时序逻辑always_comb
]感谢:D
关于问题 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
到了 for 的逻辑之后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
or的任何更改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。这是特定于工具的,这不是论坛。你应该在供应商的网站上问这个。