在systemverilog#中,当信号快于延迟时,延迟失败

Alb*_*man 4 system-verilog

以下systemverilog中的代码失败:

module test_dly;
  reg clk = 0;
  wire w_clk_d;

  always #1ns  clk <= ~clk;
  assign #1400ps w_clk_d = clk;
endmodule
Run Code Online (Sandbox Code Playgroud)

我预计w_clk_d将是clk的延迟版本,但事实并非如此.似乎#如果新事件在延迟到期之前到达,则#不工作.我编写了代码来处理这个问题,但有没有办法让#按预期工作?谢谢,

Gre*_*reg 5

assign #1400ps w_clk_d = clk;充当延迟和过滤器.当clk更改等待1400ps然后应用当前值(不是原始值)w_clk_d.如果输入变化快于延迟恐吓值丢失.物理电路中的延迟单元也可以观察到类似的行为.

通过链接较小的延迟可以减少过滤; 物理延迟单元使用相同的策略.

wire   #700ps clk_d = clk;
assign #700ps w_clk_d = clk_d;
Run Code Online (Sandbox Code Playgroud)

只有没有滤波的延迟可以通过传输延迟来实现,传输延迟clk对其切换时的值进行采样,然后将采样值应用于w_clk_d1400ps后者

logic w_clk_d;
always @* w_clk_d <= #1400ps clk;
Run Code Online (Sandbox Code Playgroud)

要将分配保留在调度程序活动区域中,则需要额外的代码

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)
Run Code Online (Sandbox Code Playgroud)


dav*_*_59 5

这里的问题是连续assign语句一次只能调度一个活动分配。如果分配的 RHS 变化比连续分配的惯性延迟更快,则 LHS 上的先前分配将被取消或过滤。

您想要的是所谓的传输延迟:RHS 上的每个更改都会传播到 LHS。您可以使用非阻塞赋值 (NBA) 运算符执行此操作。

module test_dly;
  reg clk = 0;
  wire w_clk_d;

  always #1ns  clk = ~clk;
  always @clk  w_clk_d <= #1400ps clk;
endmodule
Run Code Online (Sandbox Code Playgroud)