Verilog-非阻塞语句混淆

Verilog-非阻塞语句混淆,verilog,Verilog,我一直认为,对于非阻塞语句,它们都并行地出现在always块的末尾 但是我觉得这个例子: 始终@(posedge i_时钟) 开始 r_Test_1每次运行always块时,非阻塞语句都会并行运行。但是,每次赋值时都使用右手边的上一个值。如果我们模拟设计,我们可以看到这种行为: 最初,所有信号的值均为0,但在第一个上升沿r_Test_1上的值为1,而其他两个寄存器保持为0。这是因为r\u Test\u 2在时钟边缘之前分配了r\u Test\u 1的值,而r\u Test\u 1在上升边缘之

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

但是我觉得这个例子:

始终@(posedge i_时钟)
开始

r_Test_1每次运行always块时,非阻塞语句都会并行运行。但是,每次赋值时都使用右手边的上一个值。如果我们模拟设计,我们可以看到这种行为:

最初,所有信号的值均为0,但在第一个上升沿
r_Test_1
上的值为1,而其他两个寄存器保持为0。这是因为
r\u Test\u 2
在时钟边缘之前分配了
r\u Test\u 1
的值,而
r\u Test\u 1
在上升边缘之前为0

在第二个上升沿上也会发生类似的行为,这次是
r\u Test\u 2
r\u Test\u 3
r\u Test\u 2
在第二个上升沿变为1,因为此时
r\u Test\u 1
在时钟边缘之前的值为1,但由于
r\u Test\u 2
在该边缘之前仍然为0,
r\u Test\u 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\u Test\u 2
时,
r\u Test\u 1
已经有一个值1,同样地,对于
r\u Test\u 3
r\u Test\u 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
`时间刻度为1ns/1ps
模块测试;
reg i_时钟=0;
reg r_测试_1=0;
reg r_Test_2=0;
reg r_Test_3=0;
初始开始
$dumpfile(“dump.vcd”);
$dumpvars;
#100美元完成;
结束

总是5点没问题。我只是不明白为什么即使我们没有指定延迟,每个语句都要运行一个时钟周期。我是说,这一切不应该在最后一刻同时发生吗?r_测试_3采用r_测试_2的值,r_测试_2采用r_测试_1,r_测试_1采用1'b1。所有这些都需要一个时钟周期。我现在明白了。它需要一个时钟周期才能传播一次,因此需要三个时钟周期才能结束。在我的测试台上,我将它们初始化为0,因为我觉得如果不对解释添加任何值,
X
会更加混乱。Hmm。对,那么-r_Test_1在第一个pos边缘得到1'b1,r_Test_3在程序上被分配了一个r_Test_2当时的值-这是一个未知值-但出于某种原因被分配了一个零???它不应该是一个未知的值吗?然后r_Test_2从r_Test_1得到1'b1值。然后在第二个pos边缘,r_Test_3接受r_Test_2的1'b1。刚才看到您的注释,您将它们初始化为0。完美的我想我现在明白了。非常感谢您的模拟和详细解释!出于好奇-你在使用Icarus Verilog和GTKWave吗?Iverilog和scansion就像我在使用mac一样。
`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