关于逻辑值变化的事件

时间:2015-02-27 05:36:17

标签: verilog system-verilog

我通常使用@运算符来等待特定信号的任何逻辑值更改。例如,等待信号a的任何变化,我通常会

wire a;
//...
@(a); // wait any value change 0->1 or 1->0, or x->1 etc

但现在我意识到上述代码并不总是按预期工作,特别是当我们引入信号强度时,如下面的代码所示:

module test;
  wire a;
  logic sweak1 = 0;
  logic spull1 = 0;

  assign (weak0,weak1) a = sweak1 ? 1'b1 : 1'bz;
  assign (pull0,pull1) a = spull1 ? 1'b1 : 1'bz;

  task wait_a_change();
    @(a);
  endtask

  initial forever begin
    $display("Value: a = %b %v @%0t", a, a, $time);
    wait_a_change();
    end
  initial begin
    sweak1 = 1;
    #10; spull1 = 1;
    #10; spull1 = 0;
    #10; spull1 = 1;
    #10;
   end 
endmodule

即使@(a)的逻辑值没有变化,事件a也会触发。 所以我的第一个解决方案就是:

task wait_a_change();
  if (a) @(negedge a);
  else   @(posedge a);
endtask

该解决方案需要额外检查(也行)。 有没有更好的解决方案?

2 个答案:

答案 0 :(得分:1)

试试@(!a)。通过布尔表达式,它失去了力量。你唯一松动的是x-> z转换。 (你的解决方案也不会抓到它)。如果你需要,你最好更好地解释你想要完成的事情,这可能是一个完全不同的方法。

答案 1 :(得分:0)

如果您想获得4状态值(1/0 / X / Z),您可以@(posedge a, negedge a)@(posedge a or negedge a)。我已经看到至少一个带有错误的模拟器,它将这些与@(a)相同。如果您的模拟器支持IEEE1800-2009(SystemVerilog 2009)或更高版本,则可以使用@(edge a)。如果所有其他方法都失败了,您可以随时使用另一条线来对该值进行采样。

wire a_val = a; // <-- 4-state value w/o preserving the strength
task wait_a_change();
  @(a_val);
endtask