uvm白皮书练习_ch2_ch221只有driver的验证平台之*2.2.1 最简单的验证平台

2023-09-18 22:37:33

uvm白皮书练习
ch221


dut.sv
这个DUT的功能非常简单,通过rxd接收数据,再通过txd发送出去。其中rx_dv是接收的数据有效指示,tx_en是发送的数据有效指示。

module dut (
    clk,
    rst_n,
    rxd,
    rx_dv,
    txd,
    tx_en
);
    input clk    ;   
    input rst_n  ;   
    input 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

my_driver.sv
所有派生自uvm_driver的类的new函数有两个参数,一个是string类型的name,一个是uvm_component类型的parent。关于name参数,比较好理解,就是名字而已;至于parent则比较难以理解,读者可暂且放在一边,下文会有介绍。事实上,这两个参数是由uvm_component要求的,每一个派生自uvm_component或其派生类的类在其new函数中要指明两个参数:name和parent,这是uvm_component类的一大特征。而uvm_driver是一个派生自uvm_component的类,所以也会有这两个参数。
driver所做的事情几乎都在main_phase中完成。UVM由phase来管理验证平台的运行,这些phase统一以xxxx_phase来命名,且都有一个类型为uvm_phase、名字为phase的参数。main_phase是uvm_driver中预先定义好的一个任务。因此几乎可以简单地认为,实现一个driver等于实现其main_phase。上述代码中还出现了uvm_info宏。这个宏的功能与Verilog中display语句的功能类似,但是它比display语句更加强大。它有三个参数,第一个参数是字符串,用于把打印的信息归类;第二个参数也是字符串,是具体需要打印的信息;第三个参数则是冗余级别。在验证平台中,某些信息是非常关键的,这样的信息可以设置为UVM_LOW,而有些信息可有可无,就可以设置为UVM_HIGH,介于两者之间的就是UVM_MEDIUM。UVM默认只显示UVM_MEDIUM或者UVM_LOW的信息
uvm_info宏非常强大,它包含了打印信息的物理文件来源、逻辑结点信息(在UVM树中的路径索引)、打印时间、对信息的分类组织及打印的信息。读者在搭建验证平台时应该尽量使用uvm_info宏取代display语句。
类的定义类似于在纸上写下一纸条文,然后把这些条文通知给SystemVerilog的仿真器:验证平台可能会用到这样的一个类,请做好准备工作。而类的实例化在于通过new()来通知SystemVerilog的仿真器:请创建一个A的实例。仿真器接到new的指令后,就会在内存中划分一块空间,在划分前,会首先检查是否已经预先定义过这个类,在已经定义过的情况下,按照定义中所指定的“条文”分配空间,并且把这块空间的指针返回给a_inst,之后就可以通过a_inst来查看类中的各个成员变量,调用成员函数/任务等。对大部分的类来说,如果只定义而不实例化,是没有任何意义的(这里的例外是一些静态类,其成员变量都是静态的,不实例化也可以正常使用。);而如果不定义就直接实例化,仿真器将会报错。
第2行把uvm_macros.svh文件通过include语句包含进来。这是UVM中的一个文件,里面包含了众多的宏定义,只需要包含一次。
第4行通过import语句将整个uvm_pkg导入验证平台中。只有导入了这个库,编译器在编译my_driver.sv文件时才会认识其中的uvm_driver等类名。
第24和25行定义一个my_driver的实例并将其实例化。注意这里调用new函数时,其传入的名字参数为drv,前文介绍uvm_info宏的打印信息时出现的代表路径索引的drv就是在这里传入的参数drv。另外传入的parent参数为null,在真正的验证平台中,这个参数一般不是null,这里暂且使用null。
第26行显式地调用my_driver的main_phase。在main_phase的声明中,有一个uvm_ phase类型的参数phase,在真正的验证平台中,这个参数是不需要用户理会的。本节的验证平台还算不上一个完整的UVM验证平台,所以暂且传入null。
第27行调用finish函数结束整个仿真,这是一个Verilog中提供的函数。
(行数不一定一一对应,需要自己判断)

`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 //new()
    extern  virtual task main_phase(uvm_phase phase);//调用附近的代码
endclass //my_driver  extends uvm_driver

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<25;i++)begin
        @(posedge top_tb.clk);//等个时钟
        top_tb.rxd <= i[7:0];
        // top_tb.rxd <= $urand_range(0.255);
        top_tb.rx_dv    <= 1'b1;
        `uvm_info("my_driver","data is driver",UVM_LOW);
    end
    @(posedge top_tb.clk);
    top_tb.rx_dv    <=  1'b0;
endtask //my_driver::main_phase
`endif

top_tb.sv

`timescale 1ns/1ns
`include "uvm_macros.sv"

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

module top_tb ;
reg         clk     ;    //时钟
reg         rst_n   ;   //复位
reg [7:0]   rxd     ;   //接受数据
reg         rx_dv   ;   //接受数据
reg [7:0]   txd     ;   //发送数据
reg         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
        #100ns clk = ~clk;
    end
end
/*复位模块*/
initial begin
    rst_n = 1'b0;
    #1000;
    rst_n = 1'b1;
end

/*fsdb*/
initial begin
    $fsdbDumpfile("verilog.fsdb");
    $fsdbDumpvars(0);
    $display("fsdbDumpfilrs is start at %d",$time);
    // #1e7;
    // $finish;
end
endmodule

仿真结果
激励本来是256次,发送随机数,这里为了方便直观,改25次,升序

fsdbDumpfilrs is start at                    0
UVM_INFO my_driver.sv(22) @ 1000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 3000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 5000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 7000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 9000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 11000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 13000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 15000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 17000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 19000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 21000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 23000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 25000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 27000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 29000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 31000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 33000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 35000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 37000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 39000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 41000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 43000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 45000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 47000: drv [my_driver] data is driver
UVM_INFO my_driver.sv(22) @ 49000: drv [my_driver] data is driver
$finish called from file "top_tb.sv", line 28.
$finish at simulation time                51000

更多推荐

第三十一章 Classes - 继承规则

第三十一章Classes-继承规则继承规则与其他基于类的语言一样,可以通过继承组合多个类定义。类定义可以扩展(或继承)多个其他类。这些类又可以扩展其他类。请注意,类不能继承Python中定义的类(即.py文件中包含的类定义),反之亦然。以下小节提供了中类继承的基本规则。继承顺序使用以下继承顺序规则:默认情况下,如果在多

JDK21你可以不用,新特性还是要了解的

大家好,我是风筝今年6月份的时候,写过一篇JDK21引入协程,再也不用为并发而头疼了,那时候只是预览版,终于,前两天(2023年9月19日)发布了JDK21正式版。老早就在YouTube上订阅了JDK21发布会的直播,一场预计历时8个小时的直播。SpringBoot3.x版本最低支持的JDK版本为JDK17,也就是说如

SpringBoot实战(二十四)集成 LoadBalancer

目录一、简介1.定义2.取代Ribbon3.主要特点与功能4.LoadBalancer和OpenFeign的关系二、使用场景一:Eureka+LoadBalancer服务A:loadbalancer-consumer消费者1.Maven依赖2.application.yml配置3.RestTemplateConfig.

设计模式:责任链模式

目录组件代码示例源码中使用优缺点总结责任链模式(ChainofResponsibilityPattern)是一种行为型设计模式,它允许多个对象按照顺序处理请求,直到其中一个对象能够处理该请求为止。责任链模式将请求发送者和接收者解耦,使得多个对象都有机会处理请求,同时避免了请求发送者与接收者之间的直接耦合关系。在责任链模

influxdb2.7基本介绍安装与启动

概念timestamp:influxdb所有的数据都会有一个列_time来存timestamp。默认是以nanosecond格式存储的。field:field就是mysql中的字段,fieldkey存储在_field字段中,fieldvalue就是字段值,存储在_value字段中。fieldkey和fieldvalue

如何在微软Edge浏览器上一键观看高清视频?

编者按:视频是当下最流行的媒体形式之一。但由于视频压缩、网络不稳定等原因,我们常常可以看到互联网上的很多视频其画面质量并不理想,尤其是在浏览器端,这极大地影响了观看体验。不过,近期微软Edge浏览器推出了一项新功能,一键就可以让浏览器中的视频变为高清版。这项神奇功能背后的技术秘诀是什么?今天,让我们一起来了解一下微软E

selenium学习

selenium模块和爬虫之间的关联便捷的获取网站中动态加载的数据便捷实现模拟登录什么是selenium模块基于浏览器自动化的一个模块selenium使用流程:-环境安装:pipinstallselenium-下载一个浏览器的驱动程序(谷歌浏览器)-下载路径:http://chromedriver.storage.go

C++版本的OpenCV实现二维图像的卷积定理(通过傅里叶变换实现二维图像的卷积过程,附代码!!)

C++版本的OpenCV库实现二维图像的卷积定理过程详解前言一、卷积定理简单介绍二、不同卷积过程对应的傅里叶变换过程1、“Same”卷积2、“Full”卷积3、“Valid”卷积三、基于OpenCV库实现的二维图像卷积定理四、基于FFTW库实现的二维图像卷积定理五、总结与讨论前言工作中用到许多卷积过程,需要转成C++代

SpringBoot的配置环境属性

SpringBoot的配置环境属性在本文中,我们将讨论SpringBoot的配置环境属性。我们将了解如何使用这些属性来配置我们的应用程序,以便在不同的环境中运行。我们还将了解如何使用SpringBoot的配置文件来管理这些属性。最后,我们将介绍一些最佳实践,以帮助您更有效地使用这些属性。理解SpringBoot的配置环

《C和指针》笔记28:可变参数和stdarg宏

可变参数列表可以通过宏来实现,这些宏定义于stdarg.h头文件,它是标准库的一部分。这个头文件声明了一个类型va_list和三个宏——va_start、va_arg和va_end。我们可以声明一个类型为va_list的变量,与这几个宏配合使用,访问参数的值。下面的程序使用这三个宏计算指定数量的值的平均值。注意参数列表

linux和windows选哪个?

linux和windows选哪个?每年在大学中都会有这么一批学生:沉浸在安装Linux系统,安装双系统,使用Linux系统看看电影,搞一搞炫酷的桌面效果。最后收获了啥?怕是啥也没有,命令学会了几个?能不能写shell?这些才有点价值。最近很多小伙伴找我,说想要一些linux学习资料,然后我根据自己从业十年经验,熬夜搞了

热文推荐