只有driver的简单验证平台
代码分析
-
DUT
- DUT功能:通过rxd接收数据,再通过txd发送出去;rx_dv是接收的数据有效指示,tx_en是发送的数据有效指示
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功能:通过rxd接收数据,再通过txd发送出去;rx_dv是接收的数据有效指示,tx_en是发送的数据有效指示
-
Driver
- UVM是一个库,库中几乎所有的东西都是使用类(class)来实现
- 类有函数(function),还有任务(task)
- 类中可以有成员变量
- 使用UVM的第一条原则是:验证平台中所有的组件应该派生自UVM中的类
- UVM验证平台中的driver应该派生自uvm_driver
- 每一个派生自uvm_component或其派生类的类在其new函数中要指明两个参数:name和parent
`ifndef MY_DRIVER__SV `define MY_DRIVER__SV class my_driver extends uvm_driver; function new(string name = "my_driver", uvm_component parent = null); //每一个派生自uvm_component或其派生类的类在其new函数中要指明两个参数:name和parent 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
- Driver功能:向rxd上发送256个随机数据,并将rx_dv信号置为高电平。当数据发送完毕后,将rx_dv信号置为低电平
- UVM由phase来管理验证平台的运行,这些phase统一以xxxx_phase来命名,且都有一个类型为uvm_phase、名字为phase的参数
- uvm_info宏
- 第一个参数是字符串,用于把打印的信息归类
- 第二个参数也是字符串,是具体需要打印的信息
- 第三个参数是冗余级别,非常关键的信息可以设置为UVM_LOW,其次UVM_MEDIUM,UVM_HIGH
- UVM采用树形结构,对于树中任何一个结点,都有一个与其相应的字符串类型的路径索引
- 路径索引可以通过get_full_name函数来获取
- 类的定义与类的实例化的区别
- 类的定义就是声明一个类型
- 类的实例化指的是通过new函数创造出一个实例,会占用内存空间
-
最终验证平台
`timescale 1ns/1ps `include "uvm_macros.svh" //uvm_macros.svh是UVM中的一个文件,里面包含了众多的宏定义 import uvm_pkg::*; //将整个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); //定义一个my_driver的实例并将其实例化,drv代表路径索引 drv.main_phase(null); //显式地调用my_driver的main_phase $finish(); //调用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
仿真结果
-
完成界面
-
波形界面
-
输出界面