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

UVM驱动与采样模块时序异常及#1延时必要性解析

UVM总线driver时序异常问题分析

问题背景

基于UVM编写了总线driver类,同时编写了sampler_n_dummy_gnt模拟从端响应逻辑,精简后代码如下:

driver代码

class driver extends uvm_driver #(bus_trans);
    ...
    task run_phase();
        forever begin
            seq_item_port.get_next_item(bus_trans_h);
            drive_item(bus_trans_h);
            ...
        end
    ...
    endtask

    task drive_item();
        vif.sel = 1;
        vif.req = 0;
        @(posedge vif.clk);
        vif.req = 1;
        // #1; // this delay needed to prolong req for 1 clock
        if (vif.gnt == 1)
            @(posedge vif.clk);
        else begin
            while (vif.gnt == 0)
                @(posedge vif.clk);
            end
        end
        vif.req = 0;
    endtask
endclass

从端sampler代码

module sampler_n_dummy_gnt;
    logic clk, rstn;
    int rdelay;

    bus_interface vif(clk, rstn);

    always #10ns clk = ~clk;

    always @(posedge vif.req) begin
        rdelay = $urandom_range(0,5);
        if (rdelay != 0) begin
          for (int i=0; i<rdelay; i=i+1) begin
            vif.gnt = 0;
            @(posedge vif.clk);
          end
        end
        vif.gnt = 1;
    end
endmodule

逻辑规则说明

  • driver侧协议要求:新事务发起时拉高sel信号,等待1个时钟周期后拉高req信号;之后等待gnt信号为高,再过1个时钟周期后拉低req信号。
  • 从端sampler逻辑:检测到req拉高后,随机生成0~5范围内的延迟值rdelay,若rdelay不为0则等待对应数量的时钟周期后拉高gnt,若rdelay为0则直接拉高gnt。

异常现象

第一笔事务传输正常,第二笔事务出现时序异常:时钟7上升沿处gnt拉低,预期req应保持高电平直到时钟8上升沿检测到gnt拉高后再拉低,但实际从时钟7开始req始终保持为0,未按预期拉高。初步怀疑时钟7上升沿时逻辑检测到gnt=1,跳过了if-else分支的时钟等待逻辑,直接执行了req=0赋值;添加代码中注释掉的#1延时语句后,即可得到符合预期的时序。
预期与实际时序对比如下:

(预期时序)                               (实际时序)
        1   2   3   4   5   6   7   8          1   2   3   4   5   6   7   8
       _   _   _   _   _   _   _   _          _   _   _   _   _   _   _   _  
clk  _| |_| |_| |_| |_| |_| |_| |_| |_      _| |_| |_| |_| |_| |_| |_| |_| |_
       _______________     ___________        _______________     ___________
sel  _|               |___|                 _|               |___|
           ___________         _______            ___________         
req  _____|           |_______|             _____|           |_______________   
                   ___________     ___                    ___________     ___
gnt  _____________|           |___|         _____________|           |___|

根因解释

该异常是SystemVerilog仿真调度的delta cycle竞争导致的,核心逻辑如下:

  1. 信号残留:第一笔事务传输完成后,vif.gnt会保持高电平,直到第二笔事务的req拉高触发sampler进程,才会被sampler拉低。
  2. 同沿执行顺序无保证:第二笔事务中,driver在时钟上升沿执行vif.req = 1后,会立刻触发sampler的always @(posedge vif.req)进程。此时driver的gnt电平判断逻辑、sampler的gnt拉低逻辑在同一个仿真时间点执行,仿真器不保证二者的执行顺序:
    • 若sampler先执行将gnt拉为0,driver读到gnt=0,进入等待循环,时序符合预期;
    • 若driver先执行if判断,sampler还未及时拉低gnt,driver读到的是上一笔事务残留的gnt=1,就会直接进入if分支,仅等待1个时钟沿就拉低req,出现req提前变低的异常。
      第一笔事务传输正常只是仿真器刚好调度顺序正确,不代表代码不存在问题。

#1延时的作用原理

添加#1延时后,driver在拉高req后会等待1个时间单位,让出仿真执行权,等sampler进程完成gnt信号的更新,再读取gnt的电平值。此时读到的是sampler设置的正确电平,不会再误判gnt为高,时序就符合预期。

工程提示:直接加#1是临时解决方式,更规范的做法是在总线接口中定义clocking block,明确约定信号驱动、采样相对于时钟沿的偏移,从语法层面彻底避免同沿调度竞争问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:39:35