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.
相关产品推荐
相关产品推荐

