非阻止和阻止分配不会按预期工作

时间:2015-05-08 13:52:14

标签: concurrency verilog simulation blocking assign

我在理解这样一个简单的事情时遇到了问题:阻塞和非阻塞分配。

我创建了一个小型测试平台,只是为了模拟这段代码的行为:

module ATest(clk, out);
    input wire clk;
    output reg [7:0] out;
    reg [7:0] A;

    initial begin
        A <= 8'b0;
    end

    always @(posedge clk) begin
        A = A + 1;
        out = A;
    end
endmodule

模拟之后,我得到了这个浪潮: What is that red line(8'hxx)?

我期望Aout下的值相同,因为我按顺序为它们分配值。为什么out&#34;不关心&#34;在第一个时钟?

然后我尝试使用非阻塞分配。我将部分代码更改为:

always @(posedge clk) begin
        A <= A + 1;
        out <= A;
end

我得到了这个浪潮: Why is everything set to "don't care" now?

我在这里没有任何期待,因为非阻塞性陈述对我来说是个谜。为什么Aout都设置为&#34;不关心&#34;?

另外,我在每个页面上都找到了不同的名字,所以请帮助我: 阻塞和非阻塞是否可以与顺序和并发作为术语互换?哪一个是正确的:非阻塞语句并发语句

谢谢。

3 个答案:

答案 0 :(得分:2)

如果不深入Verilog Simulators使用的模拟周期,您可以将非阻塞与阻塞分配视为:

阻止分配在执行给定分配时内联发生,这意味着如果我有A = A + 1这样的行,则表示我们采用A的当前值,添加1并分配{ {1}}新的价值。因此,赋值“阻止”执行直到完成。

非阻挡分配(NBA)的发生时间略早于执行线路时。您可以将非阻塞分配视为告诉模拟器稍后安排此分配的行(注意,稍后仍然使用相同的模拟时间步,因此所有这些仍然在simtime t中发生)。因此,如果你有类似A的内容,这意味着在执行此行时获取A <= A + 1的值,添加1并安排A稍微更新为该值位,但继续沿着那一行继续前进。因此,如果后面的下一行是A,则此行将使用旧值out = (A == 1) ? 1 : 0执行,而不是递增的值。一旦模拟器完成了活动代码,它就可以继续执行所有非阻塞分配。现在,A将获得递增的值,所有其他非阻塞分配将生效。

那么,对你的例子。在第一种情况下,我们看到了NBA的延迟效应。在A块中,initial被赋值为0,这意味着A将稍后取值0(仍然在sim时间0内记住);即,分配计划在所有阻塞分配运行后进行(不严格为真,但在这种情况下有效)。此外,你有时钟的发生,所以A块运行。在这里,always采用值A,但请记住,A + 1的分配没有发生,因此A的初始值仍为A 。所以,8'bx也是A + 1。由于这是一个阻止任务,它立即发生。所以,8'bx并没有因为不关心而改变。继续,A获取out的当前值,即A。所以,我们不关心8'bx。在完成这些和其他阻塞分配之后,现在我们完成了NBA,在这种情况下,out变为0.因此,仍然在sim时间0内,A变为0并且我们完成了。在时钟的下一个位置,A为0,A无关紧,您的out块按预期运行,递增always和赋值{{1}相同的值。

如果你改变A区块以使用NBA(如果它被认为是一个注册表就应该这样),情况就会略有改变。 out区块仍会导致NBA计划always成为0.但是现在,initial区块会有所不同。现在,A而不是将always分配给不关心,它会将A <= A + 1安排成A(请记住,右边的表达式代表什么值assign是内联计算的,因此A仍然使用8'bx,因为不像以前那样关心;什么是更改是A + 1采用这个新值时)并且这是在{{1因此,A的两个NBAs都已设置,但是A为0的那个NBA首先发生,并且被后来的A赋值消失了AA同样安排A,但现在,8'bx永远不会变为0.因此,out8'bx都会被A卡住}。

您可以通过Verilog或SystemVerilog LRM来更好地了解SIM卡周期以及真正发生的事情,但我希望这有助于您更好地理解其中的差异!

答案 1 :(得分:1)

您的问题来自于initial块中使用非阻止分配。请改用initial A = 8'b0;

这可能是两个分配处理方式的原因。 =分配以递增方式完成,任何新值都可用于后续分配。通过<=分配所做的更改仅在处理完所有分配后才可用。

因为您的第一个边缘位于t = 0(处理初始块时),所以在第一个示例A中分配了0,但0不可用到out之前,直到它被处理完毕。第一个周期看起来很奇怪,但其他一切都没问题。在第二个中,A分配了0A+1,因此模拟器使用always块而不是initial,与A+1一起使用当A仍然是未知值时。因此,Aout的值永远不会知道。

答案 2 :(得分:0)

条款相同。 &#34;阻止&#34;与&#34;顺序&#34;相同因为&#34;阻止&#34;表示必须在模拟器移动到下一行(按顺序)之前完成分配。 &#34;非阻断&#34;意味着可以一次完成所有行。作为Verilog的一切,它有助于想象硬件的意图,所以你可能会认为它是&#34; parallel&#34; vs.&#34; serial&#34;有时。

模拟中0时刻是否有正时钟边沿?