【问题标题】:Verilog: wire value not updatedVerilog:线值未更新
【发布时间】:2016-10-11 02:45:51
【问题描述】:

我有以下 MWE:

module test(
    input wire clock,
    input wire start
);

reg [7:0] x = 8'b10101010;
reg processing = 0;
wire [7:0] x_wire0 = x;
wire [7:0] x_wire1 = {4'hf, x};
wire [11:0] x_wire2 = {4'hf, x};

always @(posedge clock) begin
   if (start & ~processing) begin
       x = 8'h0f;
       processing = 1;
   end

   $display("---> x=%h x_wire0=%h x_wire1=%h x_wire2=%h",
       x, x_wire0, x_wire1, x_wire2);
end
endmodule

使用测试台

module test_test();

reg clock = 0;
reg start = 0;

test test(
    .clock(clock),
    .start(start)
);

always #5 clock = ~clock;

initial begin
    $monitor("%b %b", clock, start);

    #20 start = 1;
    #20 start = 0;

    #200 $finish;
end
endmodule

使用 Icarus Verilog 0.9.7 可以得到输出

0 0
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa
1 0
0 0
---> x=aa x_wire0=aa x_wire1=aa x_wire2=faa
1 0
0 1
---> x=0f x_wire0=0f x_wire1=aa x_wire2=f0f
1 1
0 1
---> x=0f x_wire0=0f x_wire1=0f x_wire2=f0f
1 1
0 0
...

我想知道为什么 x_wire1 直到下一个时钟滴答才会更新,以及是否有任何规则(经验法则)来避免这种情况。 如果我在显示命令之前使用“#0”,它会被更新。

【问题讨论】:

  • 在同一个 always 块中存在阻塞分配,它们的 RHS 上有 x_wire1。我没有在示例代码中包含该代码以使其最小化。我曾经读过非阻塞赋值和阻塞赋值不应该混在同一个always块中。
  • 您不应该将阻塞和非阻塞分配混合到 same 变量。

标签: verilog


【解决方案1】:

如果您将$display 更改为$strobe,您将获得所需的结果。如果电线有机会在$display 之前更新,这确实是模拟中的竞争条件。 $strobe 将其输出延迟到线路稳定后的时隙结束。电线的分配本质上是独立的过程。

另一种选择是对x 使用非阻塞赋值。您应该始终对顺序逻辑中的变量使用非块分配,无论如何这些变量将被另一个进程读取。然后你的 $display 总是打印上一个时钟周期的值。

最后,您可以为 $display 语句使用另一个 always 块,该语句使用时钟的下降沿。

【讨论】:

  • 我的问题是我(阻止)分配给x 及以下使用依赖于x 的电线(如x_wire1)。一定有办法知道电线在使用前什么时候稳定?!
  • 也许你需要解释一下为什么你的设计中需要像x_wire0 = x; 这样的声明。也许你可以用函数调用替换这些。在 SystemVerilog 中,您将使用 let 语句。
猜你喜欢
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
相关资源
最近更新 更多