You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilog/SystemVerilog动态可中断延迟实现方案问询

解决方案:用disable+动态线程实现可中断的动态延迟

你要的效果是flag变化时立刻打断当前的延迟操作,用新的delay重新开始计时,这个需求完全可以实现,而且不需要遍历每个时间步,也能高效仿真。

核心思路是给延迟操作的线程命名,每次触发flag事件时先终止旧线程,再启动新的延迟任务。

实现代码

module test();
  logic flag;
  integer delay = 10;

  initial begin
    flag = 0;
    #1;
    delay = 2;
    flag = 1;
    #1;
    delay = 20;
    flag = 0;
  end

  always @(flag) begin
    // 终止之前正在运行的延迟线程(如果存在)
    disable toggle_thread;
    $display("Inside flag always block at time: %0t with delay of %d", $realtime, delay);
    
    // 启动新的延迟线程,后台执行不阻塞
    fork : toggle_thread
      begin
        #delay;
        flag = ~flag;
        $display("Flag changed to %d at time: %0t", flag, $realtime);
      end
    join_none
  end
endmodule

代码说明

  • disable toggle_thread:每次flag变化时,先终止所有名为toggle_thread的活跃线程,直接打断之前未完成的#delay等待,保证旧的延迟操作不会继续执行。
  • fork : toggle_thread join_none:给fork块命名,方便后续disable;用join_none让延迟操作在后台执行,这样always块可以立刻响应下一次flag的变化,不会被阻塞。
  • 这种方式只在flag变化时才触发线程管理,完全不会额外消耗仿真资源,符合你加速仿真的要求。

另一种封装成任务的写法(更易维护)

如果逻辑复杂,也可以把延迟操作封装成任务,用法一样:

module test();
  logic flag;
  integer delay = 10;

  // 封装延迟翻转逻辑为任务
  task automatic delayed_toggle();
    #delay;
    flag = ~flag;
    $display("Flag changed to %d at time: %0t", flag, $realtime);
  endtask

  initial begin
    flag = 0;
    #1;
    delay = 2;
    flag = 1;
    #1;
    delay = 20;
    flag = 0;
  end

  always @(flag) begin
    // 终止旧任务实例
    disable delayed_toggle;
    $display("Inside flag always block at time: %0t with delay of %d", $realtime, delay);
    // 启动新任务
    fork
      delayed_toggle();
    join_none
  end
endmodule

内容的提问来源于stack exchange,提问作者M.O.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:35:29