Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In systemverilog # delay fails when RHS signal changes faster than delay

Following code in systemverilog fails:

module test_dly;
  reg clk = 0;
  wire w_clk_d;

  always #1ns  clk <= ~clk;
  assign #1400ps w_clk_d = clk;
endmodule

I expected that w_clk_d will be delayed version of clk, but it is not. Seems that # not working if new event arrived before delay expired. I wrote code to deal with this, but is there way to make # work as expected? Thanks,

like image 341
Albert Waissman Avatar asked Jul 27 '16 21:07

Albert Waissman


1 Answers

assign #1400ps w_clk_d = clk; acts as a delay and filter. When clk changes wait 1400ps then then apply the current value (not original value) to w_clk_d. If the input changes faster than the delay intimidated values are lost. A similar behavior can also be observed with delay cells in physical circuits.

Filtering can be reduced by chaining smaller delays; the same strategy is used with physical delay cells.

wire   #700ps clk_d = clk;
assign #700ps w_clk_d = clk_d;

A delay only without filtering can be achieved with a transport delay, which samples the value of clk when it toggles, then applies the sampled value to w_clk_d 1400ps latter

logic w_clk_d;
always @* w_clk_d <= #1400ps clk;

To keep the assignment in the schedulers active region then extra code is needed

logic w_clk_d;
always @(clk) fork
  begin
    automatic logic sample_clk; // visible only locally with in the fork thread
    sample_clk = clk; // local copy of clk
    #1400ps;
    w_clk_d = sample_clk;
  end
join_none // non-blocking, allows detection of next @(clk)
like image 101
Greg Avatar answered Sep 23 '22 16:09

Greg