【问题标题】:Verilog - Nonblocking statement confusionVerilog - 非阻塞语句混淆
【发布时间】:2019-02-05 14:04:03
【问题描述】:

我一直认为,对于非阻塞语句,它们都并行出现在 always 块的末尾。

但是考虑一下我发现的这个例子:

https://www.nandland.com/articles/blocking-nonblocking-verilog.html

always @(posedge i_clock)
begin
  r_Test_1 <= 1'b1;
  r_Test_2 <= r_Test_1;
  r_Test_3 <= r_Test_2;
end

上面写着“上面的 Verilog 代码中的 always 块使用非阻塞分配,这意味着值 1 从 r_Test_1 传播到 r_Test_3 需要 3 个时钟周期。”

这没有任何意义。如果值传播需要 3 个时钟周期,那么它肯定也是串联发生的,而不是并行发生的?

【问题讨论】:

  • 好的。我只是不明白为什么每个语句都需要一个时钟周期才能运行,即使我们没有指定延迟。我的意思是,这一切不应该在最后同时发生吗? r_test_3 取 r_test_2 的值,r_test_2 取 r_test_1,r_test_1 取 1'b1。所有这些都需要一个时钟周期。
  • 哦。我现在明白了。它需要一个时钟周期才能传播一次,因此需要 3 个时钟周期才能到达终点。

标签: verilog


【解决方案1】:

每次运行 always 块时,非阻塞语句都会并行运行。但是,每次分配时都使用右侧的先前值。如果我们模拟设计,我们可以看到这种行为:

最初,所有信号的值都是 0,但是在第一个上升沿 r_Test_1 的值是 1,而其他两个寄存器保持 0。这是因为 r_Test_2 的值是r_Test_1 恰好在时钟沿之前,而r_Test_1 在上升沿之前为 0。

类似的行为发生在第二个上升沿,这次是r_Test_2r_Test_3r_Test_2 在第二个上升沿变为 1,因为这次 r_Test_1 在时钟沿之前的值为 1,但因为在此沿之前 r_Test_2 仍为 0,所以 r_Test_3 仍为 0。

让我们对比一下这段代码的行为:

always @(posedge i_clock)
begin
    r_Test_1 = 1'b1;
    r_Test_2 = r_Test_1;
    r_Test_3 = r_Test_2;
end

因为我在这里使用了阻塞赋值,所以每个寄存器都会立即赋值,而不是延迟到always块结束时赋值。因此,在分配r_Test_2 时,r_Test_1 的值已经为 1,r_Test_3r_Test_2 也是如此,因此所有 3 个信号在第一个周期都取值为 1。

现在我使用了阻塞分配,顺序变得很重要。所以如果我重新排列代码看起来像这样:

always @(posedge i_clock)
begin
    r_Test_1 = 1'b1;
    r_Test_3 = r_Test_2;
    r_Test_2 = r_Test_1;
end

然后我从第二次模拟中得到不同的结果:

挑战:为什么会这样?

完整的测试台:

`timescale 1ns/1ps
module test;
    reg i_clock = 0;

    reg r_Test_1 = 0;
    reg r_Test_2 = 0;
    reg r_Test_3 = 0;

    initial begin
        $dumpfile("dump.vcd");
        $dumpvars;
        #100 $finish;
    end

    always #5 i_clock <= ~i_clock;

    always @(posedge i_clock)
    begin
        r_Test_1 <= 1'b1;
        r_Test_2 <= r_Test_1;
        r_Test_3 <= r_Test_2;
    end
endmodule

【讨论】:

  • 在我的测试台上,我将它们初始化为 0,因为我觉得 X 在不增加任何解释价值的情况下会更加混乱。
  • 嗯。就是这样 - r_Test_1 在第一个 pos 边缘得到 1'b1 并且 r_Test_3 被程序分配了一个 r_Test_2 当时的值 - 这是一个未知值 - 但由于某种原因它被分配了一个零???不应该是未知值吗?然后r_Test_2从r_Test_1获取1'b1值。然后在第二个 pos-edge,r_Test_3 接替 r_Test_2 的 1'b1。
  • 刚刚看到您将它们初始化为 0 的评论。完美。我想我现在明白了。非常感谢您的模拟和详细解释!
  • 出于好奇 - 您使用的是 Icarus Verilog 和 GTKWave 吗?
  • Iverilog 和 scansion,因为我使用的是 mac。
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多