UVM:2.2只有driver的验证平台->2.2.1最简单的验证平台

177 篇文章 139 订阅

1.DUT代码如下:

module dut(clk,
           rst_n, 
           rxd,
           rx_dv,
           txd,
           tx_en);
input clk;
input rst_n;
input[7:0] rxd;
input rx_dv;
output [7:0] txd;
output tx_en;

reg[7:0] txd;
reg tx_en;

always @(posedge clk) begin
   if(!rst_n) begin
      txd <= 8'b0;
      tx_en <= 1'b0;
   end
   else begin
      txd <= rxd;
      tx_en <= rx_dv;
   end
end
endmodule

这个DUT就是txd发送rxd的值,同时tx_en有效。


2.uvm_driver代码:

`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;

   function new(string name = "my_driver", uvm_component parent = null);
      super.new(name, parent);
   endfunction
   extern virtual task main_phase(uvm_phase phase);
endclass

task my_driver::main_phase(uvm_phase phase);
   top_tb.rxd <= 8'b0; 
   top_tb.rx_dv <= 1'b0;
   while(!top_tb.rst_n)
      @(posedge top_tb.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge top_tb.clk);
      top_tb.rxd <= $urandom_range(0, 255);
      top_tb.rx_dv <= 1'b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW)
   end
   @(posedge top_tb.clk);
   top_tb.rx_dv <= 1'b0;
endtask
`endif

1)这个driver向rxd发送256个数据,同时rx_dv有效。

2)这个driver是没有注册的。所以想用run_test("my_driver")实例化是不可能的;默认调用main_phase更是想都不要想。

3)driver是extends uvm_component,所以所有components的new函数一定要包括两个参数:string类型的name,uvm_component类型的parent。

4)UVM由phase来管理验证平台,都是类似xx_phase,比如build_phase,main_phase。所有的xx_phase都有类型为uvm_phase,名字为phase的参数。上面的也不例外。

5)main_phase是UVM中类似keyword的流程,如果吧main_phase的内容写到user定义的其他名字,也不会报错。但是注册后,自动调用main_phase,会是空的感觉。


3.最后一步,top_tb.sv如下:

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

import uvm_pkg::*;
`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;

dut my_dut(.clk(clk),
           .rst_n(rst_n),
           .rxd(rxd),
           .rx_dv(rx_dv),
           .txd(txd),
           .tx_en(tx_en));

initial begin
   my_driver drv;
   drv = new("drv", null);
   drv.main_phase(null);
   $finish();
end

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

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

endmodule


1)line2:include uvm_macros.svh。UVM的文件,里面又包含了其他的文件,只要一次。

2)line4:import将uvm_pkg导入验证平台,类似lib。要不然编译器什么都不认识。

3)上面两句都是写在module外面。我还见过有的写在里面的,而且效果不一样,甚至报错,我也不知道为什么。

4)line5:每个文件都要把在这个文件例化的源文件include。这个实在恶心,次数太多了。本来想加到file_list,只要一次就可以,但是报错找不到,一定要include(file_list不加也行),大公司的代码是这么写的,看了真是机制问题。

5)line24:定义句柄。

6)line25:实例化。uvm_info打印信息室drv就是这里给的,null后面再说。

7)显示调用my_driver的main_phase,真正的uvm不需要。


4打印的信息如下:



问题:这个drv到底是句柄决定的,还是传参决定的,因为两个都叫drv。

把传给new的 “drv"改成 ”testdrv“,看看上面效果。

initial begin
   my_driver drv;
   drv = new("testdrv", null);
   drv.main_phase(null);
   $finish();
end
结果如下:



果然,决定driver在UVM树中所以的是真正的,实实在在的,我们传给它的,被UVM吃掉的string类型变量。drv不过是一个句柄,在内存中占个地址罢了。


5.这么知道当前component在UVM树的路径出于什么位置呢?

加入下面这句代码



看看输入结果:



看!它说自己叫 testdrv,和下面的打印信息吻合。但是这个实在太简单了,就它自己,前面也没有任何索引。。。。


看一下最后的结束时间:


是51300000ps。这个先知道就行,后面的objection机制会对比

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值