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

UVM中如何通过modport强制使用clocking block?

UVM中通过Modport限制虚拟接口访问的标准方案

我想在验证环境中使用以下SystemVerilog特性:

  • clocking block:放在接口中,避免driver与monitor之间的竞争条件
  • modport:通过传递modport而非完整接口,确保只能通过clocking block访问接口信号

但在UVM环境中,我们通常实例化虚拟接口并通过config database传递。我不清楚怎么让driver只获取modport引用而非完整虚拟接口,想知道避免意外绕过modport访问信号的标准方案是什么?

我自己写了一段未验证的代码,但不确定是否是最优方案,而且发现一个问题:接口中实现的函数/任务无法被访问。

我的代码示例

interface my_interface(input clk);
  logic I;
  logic O;
  
  clocking cb_drv @(posedge clk);
    output I;
    input O;
  endclocking
  
  clocking cb_mon @(posedge clk);
    input I;
    output O;
  endclocking
  
  modport drv(clocking cb_drv, output clk);
  modport mon(clocking cb_mon, input clk);
endinterface


class my_driver extends uvm_driver #(my_transaction);
  `uvm_component_utils(my_driver);
  
  virtual my_interface.drv vif;
  
  // ... 其他代码
  
  virtual function void build_phase(uvm_phase phase);
    virtual my_interface temp;
    super.build_phase(phase);
            
    if(!uvm_config_db#(virtual my_interface)::get(this, "", "my_interface", temp))
      `uvm_fatal("VIF_GET", "Failed to get virtual interface");
    
    vif = temp.drv;
  endfunction
  
  virtual task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(transaction);
      @(vif.cb_drv);
      vif.cb_drv.I = transaction.I;
      seq_item_port.item_done();      
    end
  endtask
  
endclass

问题分析与解决方案

你的思路方向是对的:在component中声明带有modport的虚拟接口句柄,从config_db获取完整接口后转成modport类型,这确实能限制对接口信号的直接访问。但接口函数/任务无法访问的原因是你的modport没有显式包含这些方法。

标准解决方法

要解决这个问题,只需在modport定义中通过import关键字显式导入需要访问的接口函数/任务,示例如下:

修改后的接口代码

interface my_interface(input clk);
  logic I;
  logic O;
  
  // 接口内的自定义函数
  function void drv_init();
    cb_drv.I <= 1'b0;
  endfunction
  
  // 接口内的自定义任务
  task drv_reset(int cycles);
    repeat(cycles) @(posedge clk);
    cb_drv.I <= 1'b0;
  endtask
  
  clocking cb_drv @(posedge clk);
    output I;
    input O;
  endclocking
  
  clocking cb_mon @(posedge clk);
    input I;
    output O;
  endclocking
  
  // 在modport中导入需要的函数/任务
  modport drv(clocking cb_drv, output clk, import drv_init, import drv_reset);
  modport mon(clocking cb_mon, input clk);
endinterface

修改后的driver代码(可调用接口函数)

class my_driver extends uvm_driver #(my_transaction);
  `uvm_component_utils(my_driver);
  
  virtual my_interface.drv vif;
  
  // ... 其他代码
  
  virtual function void build_phase(uvm_phase phase);
    virtual my_interface temp;
    super.build_phase(phase);
            
    if(!uvm_config_db#(virtual my_interface)::get(this, "", "my_interface", temp))
      `uvm_fatal("VIF_GET", "Failed to get virtual interface");
    
    vif = temp.drv;
  endfunction
  
  virtual task run_phase(uvm_phase phase);
    // 调用接口内的初始化函数
    vif.drv_init();
    
    forever begin
      seq_item_port.get_next_item(transaction);
      @(vif.cb_drv);
      vif.cb_drv.I = transaction.I;
      seq_item_port.item_done();      
    end
  endtask
  
endclass

核心要点总结

  1. 传递完整虚拟接口,转换为modport类型:从config_db获取完整虚拟接口后,赋值给带有modport的句柄,实现访问限制
  2. 显式导入接口方法:通过modport的import关键字,把需要的函数/任务加入modport定义,确保component能正常调用接口提供的方法
  3. 严格限制信号访问:所有信号操作必须通过clocking block完成,避免直接访问接口信号,彻底消除竞争条件风险

内容的提问来源于stack exchange,提问作者G. B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:12:39