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

SystemVerilog信号升降沿差异化延迟的中断问题及解决咨询

SystemVerilog实现边沿敏感的差异化延迟(新边沿取消旧延迟)

问题核心需求

为信号en生成延迟信号en_delayed,要求:

  • 上升沿、下降沿分别施加不同长度的延迟
  • 当en出现新的边沿变化时,未完成的旧延迟事件必须立即取消,仅响应最新边沿对应的延迟

原实现的缺陷:

  1. 带边沿延迟的连续赋值(assign #(rise, fall)):当上升沿延迟远大于下降沿时,下降沿的延迟会被长上升沿延迟掩盖,无法正确触发
  2. always_comb+非阻塞赋值方案:无法取消未完成的延迟事件,导致旧延迟触发错误的电平变化

解决方案:边沿触发+动态取消挂起进程

方案1:使用disable标签块(简洁实现)

通过边沿触发的always块,每次检测到en的边沿时,先取消之前挂起的延迟赋值进程,再启动对应边沿的新延迟任务。

module top;
  timeunit            1ns;
  timeprecision       1ps;
  parameter   real    delay_en_rising_us  = 4000.0;    // 4ms
  parameter   real    delay_en_falling_us = 300.0;     // 300us
  logic en;
  logic en_delayed;

  always @(posedge en or negedge en) begin
    // 取消所有挂起的延迟赋值进程
    disable delayed_assign;
    fork : delayed_assign
      if (en) begin
        // 上升沿延迟处理
        #(delay_en_rising_us * 1us);
        en_delayed <= 1'b1;
      end else begin
        // 下降沿延迟处理
        #(delay_en_falling_us * 1us);
        en_delayed <= 1'b0;
      end
    join_none
  end

  // 仿真激励与初始化
  initial begin
    $dumpfile("dump.vcd");
    $dumpvars;
    en = 1'b1;
    en_delayed = 1'b1; // 初始值对齐
    #1000us en = 1'b0;
    #3000us en = 1'b1;
    #6900us en = 1'b0;
    #7100us en = 1'b1;
    #15000us $finish;
  end
endmodule

方案2:使用process系统类(灵活进程管理)

如果需要更精细化的进程控制,可以用SystemVerilog的process类跟踪并终止挂起的延迟进程:

module top;
  timeunit            1ns;
  timeprecision       1ps;
  parameter   real    delay_en_rising_us  = 4000.0;    // 4ms
  parameter   real    delay_en_falling_us = 300.0;     // 300us
  logic en;
  logic en_delayed;
  process delay_proc; // 声明进程句柄

  always @(posedge en or negedge en) begin
    // 终止未完成的旧延迟进程
    if (delay_proc != null && delay_proc.status != process::FINISHED) begin
      delay_proc.kill();
    end
    // 启动新的延迟进程
    fork
      begin
        delay_proc = process::self(); // 获取当前进程句柄
        if (en) begin
          #(delay_en_rising_us * 1us);
          en_delayed <= 1'b1;
        end else begin
          #(delay_en_falling_us * 1us);
          en_delayed <= 1'b0;
        end
      end
    join_none
  end

  // 仿真激励与初始化
  initial begin
    $dumpfile("dump.vcd");
    $dumpvars;
    en = 1'b1;
    en_delayed = 1'b1;
    #1000us en = 1'b0;
    #3000us en = 1'b1;
    #6900us en = 1'b0;
    #7100us en = 1'b1;
    #15000us $finish;
  end
endmodule

方案说明

  • 两种方案均通过边沿触发机制,确保每次en变化时优先终止旧延迟任务,再启动新任务,完全符合"仅响应最新边沿"的需求
  • 方案1语法简洁,适合常规场景;方案2的process类支持更复杂的进程状态判断,扩展性更强
  • 手动设置en_delayed初始值,避免仿真初始阶段的电平不一致问题

内容的提问来源于stack exchange,提问作者Du mmyTransistor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:23:18