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

时间:2016-07-27 21:40:23

标签: system-verilog

以下systemverilog中的代码失败:

module test_dly;
  reg clk = 0;
  wire w_clk_d;

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

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

2 个答案:

答案 0 :(得分:5)

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

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

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

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

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

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

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)

答案 1 :(得分:3)

这里的问题是连续的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