我一直认为,对于非阻塞语句,它们都在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块使用Nonblocking分配,这意味着值1从r_Test_1传播到r_Test_3需要3个时钟周期。”
那没有任何意义。如果该值传播需要3个时钟周期,那么是否肯定也是串行发生而不是并行发生?
答案 0 :(得分:0)
非阻塞语句在每次Always块运行时都并行运行。但是,每个分配在分配时都使用右侧的先前值。如果我们模拟设计,则可以看到以下行为:
最初,所有信号的值为0,但是在第一个上升沿r_Test_1
的值为1,而其他两个寄存器保持为0。这是因为r_Test_2
为在时钟边沿之前 分配了r_Test_1
的值,而在上升沿之前r_Test_1
为0。
类似的行为发生在第二个上升沿,这次是r_Test_2
和r_Test_3
。 r_Test_2
在第二个上升沿变为1,因为这次r_Test_1
在时钟沿之前为1,但是由于r_Test_2
在该沿之前仍为0,因此{{1} }保持为0。
我们将此与代码的行为进行对比:
r_Test_3
因为我在这里使用了阻塞分配,所以每个寄存器都立即分配了值,而不是将分配推迟到Always块的末尾。因此,在分配always @(posedge i_clock)
begin
r_Test_1 = 1'b1;
r_Test_2 = r_Test_1;
r_Test_3 = r_Test_2;
end
时,r_Test_2
的值已经为1,并且对于r_Test_1
和r_Test_3
同样,因此所有3个信号的值都为1在第一个周期。
现在我正在使用阻止分配,顺序变得很重要。因此,如果我重新排列代码,使其看起来像这样:
r_Test_2
挑战:为什么会这样?
完整的测试平台:
always @(posedge i_clock)
begin
r_Test_1 = 1'b1;
r_Test_3 = r_Test_2;
r_Test_2 = r_Test_1;
end