记录
参考使用uvm白皮书内容
从根本上来说,应该杜绝在验证平台中使用绝对路径
避免绝对路径一个方法是使用宏
`define TOP top_tb
`define TOP top_tb
task my_driver::main_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("my_driver", "main_phase is called", UVM_LOW);
`TOP.rxd <= 8'b0;
`TOP.rx_dv <= 1'b0;
while(!`TOP.rst_n)
@(posedge `TOP.clk);
for(int i = 0; i < 256; i++)begin
@(posedge `TOP.clk);
`TOP.rxd <= $urandom_range(0, 255);
`TOP.rx_dv <= 1'b1;
`uvm_info("my_driver", "data is drived", UVM_LOW);
end
@(posedge `TOP.clk);
`TOP.rx_dv <= 1'b0;
phase.drop_objection(this);
endtask
避免绝对路径的另外一种方式是使用interface。
注意点记录
class my_driver extends uvm_driver;
my_if drv_if;
…
endclass
因为my_driver是一个类,在类中不能使用上述方式声明一个interface,只有在类似top_tb这样的模块(module)中才可以。
正确使用方式
文件:src/ch2/section2.2/2.2.4/my_driver.sv
3 class my_driver extends uvm_driver;
4 5 virtual my_if vif;
如何把top_tb中的input_if和my_driver中的vif对应起来呢?
最简单的方法莫过于直接赋值。此时一个新的问题又摆在了面前:在top_tb中,通过run_test语句建立了一个my_driver的实例,但是应该如何引用这个实例呢?不可能像引用my_dut那样直接引用my_driver中的变量:top_tb.my_dut.xxx是可以的,但是top_tb.my_ driver.xxx是不可以的。这个问题的终极原因在于UVM通过run_test语句实例化了一个脱离了top_tb层次结构的实例,建立了一个新的层次结构。
对于这种脱离了top_tb层次结构,同时又期望在top_tb中对其进行某些操作的实例,UVM引进了config_db机制。在config_db机制中,分为set和get两步操作。所谓set操作,可以简单地理解成是“寄信”,而get则相当于是“收信”。在top_tb中执行set操作
寄信
文件:src/ch2/section2.2/2.2.4/top_tb.sv
44 initial begin
45 uvm_config_db#(virtual my_if)::set(null,"uvm_test_top", "vif", input_if);
46 end
收信
文件:src/ch2/section2.2/2.2.4/my_driver.sv
13 virtual function void build_phase(uvm_phase phase);
14 super.build_phase(phase);
15 `uvm_info("my_driver", "build_phase is called", UVM_LOW);
16 if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
17 `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
18 endfunction
config_db的set和get函数都有四个参数,这两个函数的第三个参数必须完全一致。
set函数的第四个参数表示要将哪个interface通过config_db传递给my_driver,
get函数的第四个参数表示把得到的interface传递给哪个my_driver的成员变量。
set函数的第二个参数表示的是路径索引
dut.sv
module dut (
clk,
rst_n,
rxd,
rx_dv,
txd,
tx_en
);
input clk ;
input rst_n ;
input [7:0]rxd ;
input rx_dv ;
output txd ;
output tx_en ;
reg [7:0] txd;
reg tx_en;
always @(posedge clk) begin
if(!rst_n)begin
txd <= 8'h00;
tx_en <= 1'b0;
end
else begin
txd <= rxd;
tx_en <= rx_dv;
end
end
endmodule
TB
my_driver.sv
`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;
virtual my_if vif;
`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!!!")
endfunction
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;
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
my_if.sv
`ifndef MY_IF__SV
`define MY_IF__SV
interface my_if(input clk, input rst_n);
logic [7:0] data;
logic valid;
endinterface
`endif
top_tb.sv
`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);
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));
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");
end
initial begin
uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if);
end
endmodule
仿真结果
将发送激励改成了25次
UVM_INFO my_driver.sv(11) @ 0: uvm_test_top [my_driver] new is called
UVM_INFO @ 0: reporter [RNTST] Running test my_driver...
fsdbDumpfilrs is start at 0
UVM_INFO my_driver.sv(16) @ 0: uvm_test_top [my_driver] virtual interface must be set for vif!!!
UVM_INFO my_driver.sv(36) @ 13000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 15000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 17000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 19000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 21000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 23000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 25000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 27000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 29000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 31000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 33000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 35000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 37000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 39000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 41000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 43000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 45000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 47000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 49000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 51000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 53000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 55000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 57000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 59000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 61000: uvm_test_top [my_driver] data is driver
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO : 28
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1
[my_driver] 27