如何在SystemVerilog中中断未完成的延迟

How to interrupt an uncompleted delay in SystemVerilog

提问人:Du mmyTransistor 提问时间:11/14/2023 最后编辑:Du mmyTransistor 更新时间:11/15/2023 访问量:56

问:

我想使用以下代码对信号应用不同的上升和下降延迟:

  timeunit            1ns;
  timeprecision       1ps;
  parameter   real    delay_en_rising_us  = 100.0;    // means 100us
  parameter   real    delay_en_falling_us = 300.0;    // means 300us
  logic en;
  logic en_delayed;
  
  always_comb
    if ($realtime == 0)
      en_delayed = en;
    else if (en)
      en_delayed <= #(delay_en_rising_us*1us) en;
    else
      en_delayed <= #(delay_en_falling_us*1us) en;

方案 1 显示了看起来不错的结果。

enter image description here

但是,如果我像这样更改延迟:

parameter   real    delay_en_rising_us  = 100.0;      // means 1000us
parameter   real    delay_en_falling_us = 1500.0;     // means 1500us

然后结果如场景 2 所示,这不是我所期望和试图实现的。

enter image description here

实际上,如果信号“en”变高,则应立即取消或中断信号“en_delayed”处的 1500us 下降延迟。请参阅下图,其中显示了预期的行为。

enter image description here

总之,如果存在尚未完成的延迟,并且信号“en”突然改变,则应立即中断未完成的延迟。

非常感谢您的任何建议。

下面是仿真代码。

module top;
  
  timeunit            1ns;
  timeprecision       1ps;

  //--------------------------------------------------------  
  // This is working fine
  parameter   real    delay_en_rising_us  = 100.0;    // means 100us
  parameter   real    delay_en_falling_us = 300.0;    // means 300us

  // This is not working fine or as expected
  //parameter   real    delay_en_rising_us  = 100.0;      // means 1000us
  //parameter   real    delay_en_falling_us = 1500.0;     // means 1500us
  
  logic en;
  logic en_delayed;
  
  //--------------------------------------------------------    
  always_comb
    if ($realtime == 0)
      en_delayed = en;
    else if (en)
      en_delayed <= #(delay_en_rising_us*1us) en;
    else
      en_delayed <= #(delay_en_falling_us*1us) en;
  
  //--------------------------------------------------------    
  //initial begin
  initial fork
    $dumpfile("dump.vcd"); $dumpvars;
    
    //en = 0;
    //#100us  en = 1;       
    //#1000us en = 0; 
    //#3000us en = 1; 

    en = 1;
    #1000us en = 0;
    #2000us en = 1;
    
    #5000us $finish;

  join

 //------------------------------------------------------------------------------------------------ 

endmodule
Verilog 延迟 系统-Verilog 取消 中断

评论

0赞 Serge 11/14/2023
在延迟 1500 完成之前,您不应该有上升沿。否则,行为是未定义的。然而,我看到,在大多数情况下,上升沿只是被仿真吞噬了。这可能也是一种硬件行为。
0赞 Du mmyTransistor 11/15/2023
@ Serge:“en”信号是输入信号,即它可以随时更改。这个想法是,如果“en”像 1500 延迟完成之前所示的那样变高,那么该延迟应该立即中断。
0赞 Serge 11/15/2023
那么你需要一个不同的算法。

答:

0赞 Parth Pandya 11/15/2023 #1

我认为您需要如下所示的代码。en_delayed 在 0ns 时间为 1'b0。

always@(posedge en)
  begin   
     en_delayed <=0;
     en_delayed <= #(delay_en_rising_us*1us) 1'b1;
  end   
  always@(negedge en)
  begin
     en_delayed <= 1;
     en_delayed <= #(delay_en_falling_us*1us) 1'b0;
  end