以下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的延迟版本,但事实并非如此。 似乎#如果新事件在延迟到期之前到达,则#不工作。 我编写了代码来处理这个问题,但有没有办法让#按预期工作? 谢谢,
答案 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