【问题标题】:Why do we use Blocking statement in Combinatorial Circuits designed using Always Block in Verilog/Systemverilog ? Why not Nonblocking?为什么我们在使用 Verilog/Systemverilog 中的 Always Block 设计的组合电路中使用 Blocking 语句?为什么不是非阻塞?
【发布时间】:2016-03-30 12:06:48
【问题描述】:

到处都提到了这一点作为指导方针,但经过深思熟虑后,我想知道如果我们在 Always Block for Combinatorial 中也使用非阻塞语句会造成什么危害。我不会把两者混在一起。但是我的感觉是,当我们在 Always Block 中使用 Nonblocking for Combinatorial 语句时,它更准确地代表了硬件。难道不是……?

例如,如果我们采用以下电路:

在此图中,当提供输入 a、b、c 时,输出 x1 和 x 将不会立即可用。会有登机口延迟。第一个 x1 可用,然后 x 可用。如果我们使用阻塞语句,两者都可以立即使用。如果我们使用非阻塞,它更准确地类似于硬件。

例如,如果我们根据上图取下面的代码

module block_nonblock(output logic x,x1,y,y1,input logic a,b,c);

always@* begin : BLOCKING
    x1 = a & b;
    x  = x1 & c; 
end

always@* begin : NONBLOCKING
    y1 <= a & b;
    y  <= y1 & c; 
end

endmodule

这综合为:

两者都被合成为与门,并给出相同的模拟结果,但是当我们检查增量时间输出的变化时,我觉得与阻塞相比,非阻塞更准确地匹配硬件。

我还经历了:IEEE P1364.1 / D1.6 Verilog® 寄存器传输级综合标准草案, 它指定对顺序建模使用非阻塞,但没有具体指定使用 Always 对组合建模使用阻塞 堵塞。它说不要在组合语句中混合使用两者(阻塞和非阻塞)。

所以,我们不应该在处理纯组合逻辑(非顺序/不涉及时钟)的 always 块中对组合语句使用非阻塞

【问题讨论】:

标签: verilog fpga system-verilog synthesis register-transfer-level


【解决方案1】:

危害在于模拟;在性能和竞争条件下。

NONBLOCKING 代码会针对 a 或 b 中的每次更改执行两次。非阻塞分配更新被安排到稍后的事件队列中,这会导致块被重复执行的更大的涟漪效应。

当您模拟 RTL 代码时,您是在没有物理延迟的情况下进行的,并且综合工具了解将如何实现逻辑。但仿真工具无法做到这一点,还需要使用不可综合的代码。他们必须完全按照编写的方式执行代码。他们还必须在具有单个或有限数量线程的处理器上处理大量并发执行代码。因此,模拟在软件中引入了真实硬件中不存在的竞争条件。在编写顺序逻辑时,非阻塞分配可以防止这些竞争条件。但如果在组合逻辑中使用它们会产生相反的效果,尤其是在与时钟生成相关的组合逻辑中使用时。

【讨论】:

  • 我了解顺序语句中非阻塞的重要性(即涉及时钟)。在上述电路(开头的那个)中,如果我们同时提供所有输入,那么实际上我们不会同时在 X1 和 X 处获得预期的正确值(因为门延迟)。首先我们得到 X1,如果我们检查 X,那一瞬间它就会有其他东西(不是预期的正确值)。在 nxt 步骤中,即在第二个与门的门延迟之后,我们在 X 处得到正确的期望值。那么,这不是用非阻塞来最好地描述的吗?只是试图找到一个可以说服我的答案。 :-)
  • 当你编写 RTL 代码时,你应该着眼于你试图指定的功能方面,而不是它的门级表示。您不能总是假设您编写的 RTL 语句总是与门级表示一一对应。因此,期望 RTL​​ 以它在门级的确切方式产生涟漪是不合适的。
【解决方案2】:

您问“那么,我们不应该对 Sequential 中的组合语句使用非阻塞吗?”答案是否。

如果您在时钟始终块中对组合逻辑使用非阻塞分配,您将获得比预期更多的触发器。基本上,时钟控制的 always 块中的非阻塞分配在您模拟时表现得像触发器,而在您综合时推断触发器。

所以,

1 - 对门使用阻塞分配和

2 - 对触发器使用非阻塞赋值。

【讨论】:

  • 抱歉.. 我的意思是“所以,我们不应该在处理纯组合逻辑(非顺序/不涉及时钟)的 always 块中对组合语句使用非阻塞”
【解决方案3】:

您自己对电路行为的描述实际上建议使用阻塞操作。

你说:(强调我的)

在此图中,当输入 a、b、c 被提供时,输出 x1 和 x 不会立即可用。会有登机口延迟。 第一个 x1 将可用,然后 x 将可用。如果我们使用阻塞 两种报表都可以立即使用。如果我们使用非阻塞,它 更准确地类似于硬件。

所以你需要x1 在x 之前可用。所以你的 always 阻塞必须使用阻塞赋值,所以...

always@* begin : BLOCKING
    x1 = a & b;
    x  = x1 & c; 
end

x1 首先会有一个已知值,然后,只有这样,x 才会有一个值。如果你使用非阻塞...

always@* begin : NON BLOCKING
    x1 <= a & b;
    x  <= x1 & c; 
end

您是在告诉模拟器x1 和x 将同时被评估。

虽然对于综合来说这可能有效,但在模拟中却不行,而且您要确保您的模拟电路在进入综合阶段之前按预期工作。

【讨论】:

  • 我明白你在说什么,但我的目的是编写一个最能描述上述电路的代码。如果我使用阻塞语句,它是否更准确地类似于硬件(因为首先确定 X1 的正确值,然后再确定 X 的值)。或。如果使用非阻塞语句,它不会等待 X1 具有正确的值然后分配 X。它直接给我原样的值(好像我们在门之间连接了实际的电线)。我只是想找到一个能让我信服的答案。
【解决方案4】:

我找到了一个满意的答案,需要输入。我觉得我们应该对组合语句和顺序语句使用非阻塞语句。

对于顺序,我们应该使用非常清楚的 y。

我将描述 Combi Blocks 的原因。 对于组合段,我们将使用非阻塞语句,因为当我们使用阻塞或非阻塞语句时,即使它最终为我们提供了相同的硬件或 RTL;正是非阻塞语句向我们展示了模拟中的故障。这些故障也将存在于硬件中(由于门延迟),因此我们可以在仿真中看到它们时对其进行纠正,以便它们在设计/开发周期的后期阶段造成的危害更小。

在我最初在问题中提到的电路中,如果我们将输入一起作为 (A = 1,B = 1,C = 0),然后在 10ns 之后将它们一起更改为 (A=1,B=0, C=1) 那么我们可以看到有一个小故障。这个故障也将存在于实际硬件中。但这仅在模拟中通过非阻塞语句输出 (Y) 而不是阻塞语句输出 (X) 显示。一旦我们看到一个小故障,我们就会采取额外的措施来防止这种情况发生,这样它就不会发生在硬件中。

因此我觉得可以肯定地得出结论,我们必须对组合块使用非阻塞语句。

【讨论】:

    【解决方案5】:

    我们不应该在组合块中使用非阻塞分配,因为如果我们使用非阻塞它会推断出设计中的传输延迟,因此我们的结果永远不会达到我们的预期,但是如果我们使用阻塞,这阻塞将能够抑制设计中的传输延迟,我们可以有把握地说,波形中没有毛刺。所以建议我们在组合设计中使用阻塞语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 2023-04-01
      • 2019-06-18
      • 2019-06-27
      • 2018-04-11
      • 2020-12-28
      相关资源
      最近更新 更多