系统verilog 2012中的错误有关always_comb中的非阻塞的参考指南?和延迟断言属性标记?

时间:2016-12-21 04:35:15

标签: system-verilog system-verilog-assertions

2个问题

  1. 在系统verilog 2012参考指南中提到了对always_comb中的顺序逻辑进行编码,这是可能的,因为always_comb块没有时钟参考 - 如此处所示 - &gt ; [always_comb]
  2. 中的顺序逻辑

    enter image description here

    1. 在Synopsys Verdi中使用系统verilog断言时,是否有可能在满足属性后半个或一个时钟周期之后触发绿色箭头(表示声明属性已满足)
    2. 谢谢:D

1 个答案:

答案 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

这意味着,只要ab更改,就会计算cd的值。因为我们对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尚未更新。然后,cd会在同一时间段内更新。稍后,我们会更改b,但这不会触发cd上的任何更改。然后,我们再次更改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,但cd尚未更新。其次,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.这是特定于工具的,这不是此论坛。你应该在供应商的网站上问这个。