UVM实战CH2:05 验证平台加入virtual interface

验证平台加入virtual interface

加入virtual interface

top_tb.rxd <= 8'b0; 
top_tb.rx_dv <= 1'b0;
@(posedge top_tb.clk);
  • 之前driver中等待时钟事件、给DUT中输入端口赋值都是使用绝对路径
  • 绝对路径的使用大大减弱了验证平台的可移植性
  • 避免在验证平台中使用绝对路径
    • 方法1:使用宏
    `define TOP top_tb
    
    使用场景有限
  • 避免绝对路径的另外一种方式是使用interface
    • 使用interface来连接验证平台与DUT的端口

代码分析

interface定义

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

   logic [7:0] data;
   logic valid;
endinterface

`endif

在TB中例化使用interface

`timescale 1ns/1ps
`include "uvm_macros.svh"

import uvm_pkg::*;
`include "my_if.sv"
`include "my_driver.sv"

module top_tb;

reg clk;
reg rst_n;
reg[7:0] rxd;
reg rx_dv;
wire[7:0] txd;
wire tx_en;

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);
//在TB中例化两个interface,一个输入,一个输出

dut my_dut(.clk(clk),
           .rst_n(rst_n),
           .rxd(input_if.data),
           .rx_dv(input_if.valid),
           .txd(output_if.data),
           .tx_en(output_if.valid));
//例化DUT时,使用interface连接dut

initial begin
   clk = 0;
   forever begin
      #100 clk = ~clk;
   end
end

initial begin
   rst_n = 1'b0;
   #1000;
   rst_n = 1'b1;
end

initial begin
   run_test("my_driver");
   //通过run_test语句创建了一个my_driver的实例,但此处driver实例的层次结构不在top_tb中,无法通过直接赋值把tb中的interface与driver中vif连接起来
   //无论传递给run_test的参数是什么,创建的实例的名字都为uvm_test_top

end

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if);
   //uvm引入config_db机制,在top_tb中实行set操作
   //使用双冒号是因为这两个函数都是静态函数,而uvm_config_db#(virtual my_if)则是一个参数化的类
   //可以传递不同类型的数据,也可以传递相同类型的不同数据
end

endmodule

在driver中使用virtual interface

  • driver是一个类,在类中不能声明一个interface,在module中可以。在类中使用virtual interface
`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;

   virtual my_if vif;
   //在类中使用virtual interface

   `uvm_component_utils(my_driver)
   function new(string name = "my_driver", uvm_component parent = null);
      super.new(name, parent);
      `uvm_info("my_driver", "new is called", UVM_LOW);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("my_driver", "build_phase is called", UVM_LOW);
      if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
         `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
         //uvm中的config_db机制,在driver中使用get操作。与top_tb中get操作相连接
   endfunction
   //build_phase在new函数之后main_phase之前执行
   //在build_phase中主要通过config_db的set和get操作来传递一些数据,以及实例化成员变量等
   //build_phase为function phase,不消耗仿真时间

   extern virtual task main_phase(uvm_phase phase);
endclass

task my_driver::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
   vif.data <= 8'b0; 
   vif.valid <= 1'b0;
   //声明了virtual interface后,在main_phase中使用vif的信号。代码中的绝对路径已经消除,提高可移植性和可重用性
   while(!vif.rst_n)
      @(posedge vif.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge vif.clk);
      vif.data <= $urandom_range(0, 255);
      vif.valid <= 1'b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW);
   end
   @(posedge vif.clk);
   vif.valid <= 1'b0;
   phase.drop_objection(this);
endtask
`endif

仿真截图

仿真界面

在这里插入图片描述
可以看出,模块里已经有两个interface了。output interface在top_tb中进行了声明,但没有通过config_db进行配置

输出结果

在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值