1-搭建一个最简单的验证平台UVM,已用Questasim实现波形!

UVM-搭建一个最简单的验证平台,已用Questasim实现波形

      • 1,背景知识
      • 2,".sv"文件搭建的UVM验证平台,包括代码块分享
      • 3,Questasim仿真输出
        • (1)compile all,成功!
        • (2)simulation,仿真波形输出。

1,背景知识

验证是用于找出DUT的bug,这个过程通常是把DUT放入一个验证平台中来实现的。
一个验证平台要实现如下基本功能:
(1)验证平台要模拟DUT的各种真实使用情况,这意味着要给DUT施加各种激励,有正常的激励,也有异常的激励;有这种模式的激励,也有那种模式的激励。激励的功能是由driver来实现的。
(2)验证平台要能够根据DUT的输出来判断DUT的行为是否与预期相符合,完成这个功能的是记分板(scoreboard,也称:checker)。既然是判断,那么牵扯到两个方面:一是判断什么,需要把什么拿来判断,这里很明显是DUT的判断;二是判断的标准是什么。
(3)验证平台要收集DUT的输出并把它们传递给scoreboard,完成这个功能的是monitor。
(4)验证平台要能够给出预期结果。在记分板中提到了判断的标准,判断的标准通常就是预期。假设DUT是一个加法器,那么当它的加数和被加数中分别输入1,即输入1+1时,期待DUT输出2。当DUT在计算1+1的结果时,验证平台也必须相应完成同样的过程,也计算一次1+1。在验证平台中,完成这个过程的是参考模型(reference model)。

本篇章将从一个最简单的验证平台开始,逐步搭建起一个复杂的UVM验证平台。

在这里插入图片描述

2,".sv"文件搭建的UVM验证平台,包括代码块分享

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

// UVM实战
// 最简单的验证平台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) beginif(!rst_n)  begintxd   <= 8'b0;tx_en <= 1'b0;end  else begintxd   <= rxd;tx_en <= rx_dv;end
end
endmodule

第二块代码,my_driver.sv

UVM是一个库,在这个库中,几乎所有的东西都是使用类(class)来实现的。
driver,monitor,reference model,scoreboard等组成部分都是类。类是像SystemVerilog这些面向对象编程语言中最伟大的发明之一,是面向对象的精髓。
类有函数(function)、任务(task),通过这些function和task可以完成driver的输出激励功能。类中可以有成员变量,这些成员变量可以控制类的行为,如控制driver的行为等。当要实现一个功能时,首先想到的是从UVM的某个类派生出一个新的类,在这个新的类中实现所期望的功能。
因此,使用UVM的第一条原则是:验证平台中所有的组件应该派生自UVM中的类。

这个driver的功能非常简单,只是向rxd上发送256个随机数据,并将rx_dx信号置为高电平。当数据发送完毕后,将rx_dx信号置为低电平。在这个driver中,有两点应该引起注意:
(1)所有派生自uvm_driver的类的new函数有两个参数,一个是string类型的name,一个是uvm_component类型的parent。关于name参数,就是名字而已;关于parent参数先放一边。事实上,这两个参数是由uvm_component要求的,每一个派生自uvm_component或派生类的类在其new函数中要指明两个参数:name和parent,这是uvm_component类的一大特征。而uvm_driver是一个派生自uvm_component的类,所以也会有这两个参数。
(2)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语句。

// UVM 验证平台中的 driver应该派生自 uvm_driver,
// 下面是一个简单的 driver 
`ifndef MY_DRIVER_SV
`define MY_DRIVER_SV`include "uvm_macros.svh"  // 这是UVM的一个文件,里面包含了众多的宏定义,只需要包含一次
import uvm_pkg::*;   // 只要导入了这个库,编译器在编译my_driver.sv文件时才会认识其中的uvm——driver等类名。class my_driver extends uvm_driver;function new(string name = "my_driver", uvm_component parent = null);super.new(name, parent);endfunctionextern virtual task main_phase(uvm_phase phase);
endclasstask 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

uvm_pkg的解释:
uvm_pkg是一个开放源代码的解决方案库,用于基于IEEE 1800 SystemVerilog标准实现通用验证方法(Universal Verification Methodology,简称UVM)。UVM是一种常用的硬件验证方法学,用于验证集成电路设计的正确性。

uvm_pkg提供了一组类、函数和宏,用于建模和实现验证环境中常见的验证功能,如生成和管理事务、约束和随机性、组织测试用例、收集和报告结果等。它还定义了一套规范,描述了验证架构的结构和交互方式。

通过使用uvm_pkg,验证工程师可以更高效地编写可重用和可扩展的验证环境,加快验证开发的速度,提高项目的可靠性和生产力。

第三块代码,top_tb.sv

// 对 my_driver 实例化并且最终搭建的验证平台如下:`timescale 1ns/1ps
`include  "uvm_macros.svh"   // UVM宏
import uvm_pkg::*;  //  通过 import 语句将整个 uvm_pkg导入验证平台。// 只有导入了这个库,编译器在编译my_driver.sv文件时才会认识其中的ruvm_driver等类名。`include "my_driver.sv"      // 对 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 beginmy_driver drv;drv = new("drv", null); // 注意这里调用new函数时,其传入的名字参数为drv。前文介绍的uvm_info宏的打印信息时出现的代表路径索引的drv就是在这里传入的参数drv。// 另外传入的parent的参数为null,在真正的验证平台中,这个参数一般不是null,这里是暂时用null。 drv.main_phase(null);// 这里调用的死my_driver 中的main_phase,在main_phase的声明中,有一个uvm_phase类型的参数phase// 在真正的验证平台中,这个参数是不需要用户理会的。这里搭建的还不是一个完整的验证平台,所以暂且传入null。$finish();
endinitial beginclk = 0;forever begin#100 clk = ~clk;end
endinitial beginrst_n = 1'b0;#1000;rst_n = 1'b1;
endendmodule

3,Questasim仿真输出

注明:参考文献:,这里有Questasim仿真时碰到的各种错误解决方案,非常有用!
1,questasim常见问题解决方案

(1)compile all,成功!

在这里插入图片描述

(2)simulation,仿真波形输出。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 CentOS 7 构建 LVS-DR 集群 及 配置nginx负载均衡

一、构建LVS-DR集群 1、主机规划 Node01&#xff1a;PC Node02&#xff1a;LVS Node03、Node04&#xff1a;Webserver 2、部署环境 2.1 在Node02上配置 2.1.1 安装ipvsadm管理软件按 [rootlocalhost ~]# yum install -y ipvsadm 2.1.2 配置VIP [rootlocalhost ~]# if…

【力扣每日一题】2023.8.8 任意子数组和的绝对值的最大值

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一个数组&#xff0c;让我们找出它的绝对值最大的子数组的和。 这边的子数组是要求连续的&#xff0c;让我们找出一个元素之和…

GG修改器安装与Root环境的安装

关于GG修改器大家应该都有一定的了解吧&#xff0c;就是类似于电脑端CE的一个软件。 GG修改器在百度云盘里请自行下载&#xff01; 百度网盘链接&#xff1a;https://pan.baidu.com/s/1p3KJRg9oq4s0XzRuEIBH4Q 提取码&#xff1a;vuwj 那我要开始了&#xff01; 本来不想讲GG…

Spring Boot集成EasyPoi实现导入导出操作

文章目录 Spring Boot集成EasyPoi实现导入导出操作0 简要说明1 环境搭建1.1 项目目录1.2 依赖管理2.3 关于swagger处理2.4 关于切面处理耗时1 自定义注解2 定义切面类3 如何使用 2.5 核心导入操作2.6 核心导出操作 2 最佳实线2.1 导入操作1 实体类说明2 业务层3 效果3 控制层 2…

常用抓包工具

Fiddler Fiddler 是一个很好用的抓包工具&#xff0c;可以用于抓取http/https的数据包&#xff0c;常用于Windows系统的抓包&#xff0c;它有个优势就是免费 Charles Charles是由JAVA开发的&#xff0c;可以运行在window Linux MacOS&#xff0c;但它是收费的&#xff0c;和…

.Net Framework请求外部Api

要在.NET Framework 4.5中进行外部API的POST请求&#xff0c;你可以使用HttpClient类。 1. Post请求 using System; using System.Net.Http; using System.Threading.Tasks;class Program {static async Task Main(string[] args){// 创建一个HttpClient实例using (HttpClien…

Python取得系统进程列表

Python取得系统进程列表 上代码 上代码 import psutilfor proc in psutil.process_iter():try:pinfo proc.as_dict(attrs[pid, name])except psutil.NoSuchProcess:passelse:print(pinfo)

httpd+Tomcat(jk)的Web动静分离搭建

动静分离是指将动态请求和静态请求分别交给不同的服务器来处理&#xff0c;可以提高服务器的效率和性能。在Java Web开发中&#xff0c;常见的动态请求处理方式是通过Tomcat来处理&#xff0c;而静态请求则可以通过Apache服务器来处理。本文将详细讲解如何结合Apache和Tomcat来…

Logback ThresholdFilter LevelFilter

当我们需要对日志的打印要做一些范围的控制的时候&#xff0c;通常都是通过为各个Appender设置不同的Filter配置来实现。在Logback中自带了两个过滤器实现&#xff1a; ch.qos.logback.classic.filter.LevelFilter和 ch.qos.logback.classic.filter.ThresholdFilter&#xff0c…

面试热题(翻转k个链表)

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值&a…

使用Feign 的远程调用,把mysql数据导入es

要把数据库数据导入到elasticsearch中&#xff0c;包括下面几步&#xff1a; 1&#xff09;将商品微服务中的分页查询商品接口定义为一个FeignClient&#xff0c;放到feign-api模块中 2&#xff09;搜索服务编写一个测试业务&#xff0c;实现下面功能&#xff1a; 调用item-ser…

ctfshow-web7

0x00 前言 CTF 加解密合集 CTF Web合集 0x01 题目 0x02 Write Up 通过尝试&#xff0c;发现是数字型的注入&#xff0c;并且同样是过滤了空格 判断字段 获取一下flag即可 1/**/union/**/select/**/1,flag,3/**/from/**/web7.flag#&passworda以上

Spring接口ApplicationRunner的作用和使用介绍

在Spring框架中&#xff0c;ApplicationRunner接口是org.springframework.boot.ApplicationRunner接口的一部分。它是Spring Boot中用于在Spring应用程序启动完成后执行特定任务的接口。ApplicationRunner的作用是在Spring应用程序完全启动后&#xff0c;执行一些初始化任务或处…

kylin-Desktop gsettings 获取或设置系统配置

gsettings提供了对GSetings的命令行操作。GSetings实际上是一套高级API,用来操作dconf。 dconf存储着GNOME3的配置,是二进制格式。它做为GSettings的后端系统存在,暴露出低级API。在GNOME2时代,类似的角色是gconf,但它是以XML文本形式存储。 更接地气的说法是,dconf是G…

JavaScript基础知识

JavaScript基础知识 一、变量与数据类型1. 变量2. 数据类型 二、表达式与运算符1.字面量2.表达式3.运算符3.1 算术运算符3.2 比较运算符3.3 逻辑运算符3.4 赋值运算符 三、条件语句1. 控制流程2. 语句块3. if 语句3. switch 语句4. 条件运算符 四、循环语句1. while2. do...whi…

【框架篇】MyBatis 介绍及使用(详细教程)

一&#xff0c;MyBatis 介绍 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff…

Oracle以逗号分隔的字符串拆分为多行数据实例详解

前言 近期在工作中遇到某表某字段是可扩展数据内容&#xff0c;信息以逗号分隔生成的&#xff0c;现需求要根据此字段数据在其它表查询相关的内容展现出来&#xff0c;第一想法是切割数据&#xff0c;以逗号作为切割符&#xff0c;以下为总结的实现方法&#xff0c;以供大家参…

微服务 云原生:基于 Gogs + Drone 进行项目 CI/CD

传统构建部署 以一个简单的前后端项目来说&#xff0c;分别编写前后端的 Dockerfile 文件并构建镜像&#xff0c;然后编写 docker-compose.yml 构建部署&#xff0c;启动运行。 一个简单的例子&#xff1a; 前端&#xff1a; 项目名&#xff1a;kubemanagement-web技术栈&am…

基于java医院分诊管理系统设计与实现

摘 要 当我们举步迈入21世纪&#xff0c;计算机的蓬勃发展加快了这个社会前进的速度。信息技术的传播正在以飞快的速度传向世界的每一个角落。人们的生产生活方式也受到了计算机以及网络化带来的巨大改变&#xff0c;计算机在赋予人们工作、娱乐、生活等等方面巨大的改变&#…

Linux 内核音频数据传递主要流程

Linux 用户空间应用程序通过声卡驱动程序&#xff08;一般牵涉到多个设备驱动程序&#xff09;和 Linux 内核 ALSA 框架导出的 PCM 设备文件&#xff0c;如 /dev/snd/pcmC0D0c 和 /dev/snd/pcmC0D0p 等&#xff0c;与 Linux 内核音频设备驱动程序和音频硬件进行数据传递。PCM 设…