自触发总是阻止使用延迟

时间:2017-02-20 20:23:47

标签: verilog

我需要实现一个由

触发的块(行为,不是要合成)

a)外部事件eflag,或者b)取决于其状态,内部事件iflag,在dt秒之后安排,以先到者为准。

我使用延迟(#)运算符的试验导致阻塞行为,例如一个长的dt确实阻止了下一个eflag。 如果可能的话,我会避免将dtmax作为长dt的计算开销。

工作和预期,但代码失败:

`timescale 1ns/100fs
`define tick 1.0e-9 

parameter real  dtmax = 1;

initial iflag=1'b0;
initial toggle=1'b0;

always @(eflag, iflag) begin    
    // time step control

    dt = ...;
    iticks = dt/`tick;
    toggle = !toggle;
end

//------------------------------------------------------
/*
a) time step counter - working
always #1 begin
    iticks = iticks - 1;
    if (iticks < 1) begin 
        iflag = !iflag;  
        iticks=dtmax/`tick;
    end
end
*/

// b) intended
always @(toggle) begin
    #(iticks) iflag <= !iflag;          // failing, not changing iflag
 // #(iticks) iflag = !iflag;           // failing, blocking simulation
end

你可以在edaplayground上试试 link

THX

1 个答案:

答案 0 :(得分:0)

我已经对您的代码进行了分支,这个新代码对我来说很好。如果您认为它不起作用,也许您在理解Verilog模拟时错了。非阻塞延迟会在信号上安排事件。如果在分配该调度之前,另一个事件被调度,具有不同的值,则它将覆盖第一个事件。如果新事件具有相同的值,则保留第一个值。

// Verilog
// self-triggered always block
// block should take time steps <= dtmax


`define tick 1.0e-9

module dut(eflag);

  input eflag;
reg   iflag;
reg   toggle;
  integer iticks;
  real    last_time;
  real    now;
  real    dtlast;
  real    dtmax;

  always @(eflag, iflag) begin  

    now    = $time*`tick;
    dtlast = now - last_time;
    dtmax  = iticks*`tick; // from last call

    $display(  "dtlast:  %g",dtlast);
    $display(  "err:     %d",dtlast > dtmax); // giving wrong value in sim?
    $display("\nnow:     %g",now);
    $display(  "dtmax:   %g",dtmax);


    // time step control dummy
    iticks <= 7 + $random % 5; //changed because in previous one eflag and toggle always changed at the same time
    toggle = !toggle;

    last_time = now;
  end

  initial toggle = 0;
  initial iflag = 0;
  always @(toggle) begin
    #(iticks) iflag <= !iflag; 
  end

endmodule