《从零开始,搭建一个简单的UVM验证平台》实操

news2025/2/25 13:54:49

最近的工作中需要用UVM平台去仿真软件同事写的C程序,虽然只要用EDA同事已经搭好的UVM平台稍微改改就行,但对于我这种从未接触过UVM甚至都没用过System Verilog的纯FPGA工程师来说还是很有难度的,因为我对这方面一点概念都没有。

基于此,想着边用边学,就在网上找了一些资料学习。看到了下面这篇文章:

从零开始,搭建一个简单的UVM验证平台(一)

看着还是挺简单的,但亲自动手去做一遍,还是费了很大功夫的。虽然这个博客里提供了大部分代码,但并没有写一步步地怎么做。另外,特别注意,这个博客系列文章里的代码有一些小问题,会导致结果出不来,我就遇到了好几个坑。

下面就记录下,我一步步的过程,并附上所以源码和相应的截图。

第1步:把这几个模块代码拷贝下来

dut.v

module dut(
  input             clk           , 
  input             rstn          ,
  input      [7:0]  data_i        ,
  input             data_i_valid  ,
  output reg [7:0]  data_o        ,
  output reg        data_o_valid
);
 
always @(posedge clk)begin
  if(!rstn)begin
    data_o       <= 8'd0;
    data_o_valid <= 1'b0;
  end
  else begin
    data_o       <= data_i;
    data_o_valid <= data_i_valid;
  end
end
 
endmodule 

my_driver.sv

//`ifndef _MY_DRIVER
//`define _MY_DRIVER


`include "uvm_macros.svh"
import uvm_pkg::*;
 
class my_driver extends uvm_driver;
   `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
 
    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);
    top_tb.data_i       <= 8'd0;
    top_tb.data_i_valid <= 1'b0;
    while(!top_tb.rstn)
      @(posedge top_tb.clk);
    for(int i = 0; i < 256; i = i+1)begin
      @(posedge top_tb.clk)
      top_tb.data_i <= $urandom_range(0,255);
      top_tb.data_i_valid <= 1'b1;
      `uvm_info("my_driver", "data is drived.", UVM_LOW) 
    end
    @(posedge top_tb.clk);
    top_tb.data_i_valid <= 1'b0;
    phase.drop_objection(this);
endtask


//`endif

top_tb.sv

`timescale 1ns/1ps
`include "uvm_macros.svh" //这是UVM中的一个文件,包含了众多宏定义
 
import uvm_pkg::*;        //只有导入了这个库,编译器在编译my_driver.sv文件时才会认识其中继承的uvm_driver等类名
 
//`include "my_driver.sv"
 
module top_tb;
 
reg clk,rstn;
reg  [7:0] data_i;
reg  data_i_valid;
wire [7:0] data_o;
wire data_o_valid;
 
dut my_dut(
  .clk            (clk   )        ,
  .rstn           (rstn  )        ,
  .data_i         (data_i)        ,
  .data_o         (data_o)        ,
  .data_i_valid   (data_i_valid)  ,
  .data_o_valid   (data_o_valid)
);

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

initial begin
    run_test("my_driver");
end 


initial begin
  clk = 0;
  forever begin
    #100 clk = ~clk;
  end
end
 
initial begin
  rstn = 1'b0;
  #1000
  rstn = 1'b1;
end

initial begin
    $fsdbDumpfile("tb.fsdb");
    $fsdbDumpvars;
end
 
endmodule

第2步:产生filelist

find ./ -name "*.*v" > filelist.f

第3步:产生makefile

这个makefile,我是在网上找了一些资料作为参考,写了个简单能用的。

#--------------------------------------------------------------------------------------
all  : clean vcs
#--------------------------------------------------------------------------------------
vcs   :
	vcs   	  -f filelist.f \
			  -ntb_opts uvm \
              -timescale=1ns/1ps \
              -full64 -R  +vc  +v2k  -sverilog \
			  -debug_access \
	          -kdb \
	          -l simv.log &
#--------------------------------------------------------------------------------------
verdi  :
	verdi -f filelist.f -ssf tb.fsdb &
#--------------------------------------------------------------------------------------
clean  :
	 rm  -rf  *~  core  csrc  simv*  vc_hdrs.h  ucli.key  urg* *.log  novas.* *.fsdb*  
	 rm  -rf  64* DVEfiles *.vpd  verdiLog verdi_config_file
#---------------------------------------------------------------------------------------

第4步:编译

所有文件如上图所示,在当前路径下执行如下命令进行编译:

make all

或者

make vcs

第5步:查看结果

编译结果如下图所示:

也可以打开simv.log查看编译结果,还可以用make verdi查看波形。


附:问题记录

我现在学到了第三篇,也就是下面这篇博客,遇到了几个问题,卡了我好几天才找到原因,也一并记录在此,方便后来人!

从零开始,搭建一个简单的UVM验证平台(三)

第一个问题

第二个问题,这个是巨坑啊,编译的时候发现会卡住,一直找不到原因,差点让我UVM从入门到放弃,花了几天的时间各种找资料各种加log才定位到这里。啊。。。超级想骂人!!!

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

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

相关文章

批量网络装机

1. PXE概念 PXE(preboot execute environment&#xff0c;预启动执行环境)是由Intel公司开发的最新技术&#xff0c;工作于Client/Server的网络模式&#xff0c;支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启动操作系统。在启动过程中&#xff0c;…

【智能算法】雪消融优化算法(SAO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2023年&#xff0c;L Deng受到雪升华和融化行为启发&#xff0c;提出了雪消融优化算法&#xff08;Snow Ablation Optimizer, SAO&#xff09;。 2.算法原理 2.1算法思想 SAO模拟了雪的…

微信云小程序快速上手云数据库+云函数+云存储的操作

&#x1f680; 作者 &#xff1a;“二当家-小D” &#x1f680; 博主简介&#xff1a;⭐前荔枝FM架构师、阿里资深工程师||曾任职于阿里巴巴担任多个项目负责人&#xff0c;8年开发架构经验&#xff0c;精通java,擅长分布式高并发架构,自动化压力测试&#xff0c;微服务容器化k…

JSP技术讲解

目录 1、JSP简介 2、JSP体验 3、JSP运行原理 4、JSP基本语法 5、JSP指令 6、JSP内置九大对象 7、JSP标签 8、JSP配置 9、JSP排错 10、总结 在前面的Servlet学习中发现Servlet本质是一个java程序&#xff0c;因此Servlet更加擅长编写程序的业务逻辑&#xff0c;而如果要…

Java特性之设计模式【代理模式】

一、代理模式 概述 在代理模式&#xff08;Proxy Pattern&#xff09;中&#xff0c;一个类代表另一个类的功能。这种类型的设计模式属于结构型模式 在代理模式中&#xff0c;我们创建具有现有对象的对象&#xff0c;以便向外界提供功能接口 主要解决&#xff1a; 在直接访问…

Apple强大功能:在新款 iPad Pro 和 iPad Air 中释放 M4 芯片潜力

Apple 的最新强大功能&#xff1a;在新款 iPad Pro 和 iPad Air 中释放 M4 芯片的潜力 概述 Apple 推出配备强大 M4 芯片的最新 iPad Pro 和 iPad Air 型号&#xff0c;再次突破创新界限。新一代 iPad 有望彻底改变我们的工作、创造和娱乐方式。凭借无与伦比的处理能力、令人惊…

CTF-reverse,逆向分析,对“左移4或右移4,即(x<<4) | (x >>4)的加密探讨

博主在刷题过程中遇上这样一个有意思的加密&#xff08;如下图&#xff09;&#xff0c;苦苦思索其逆向运算&#xff0c;被硬控了很久&#xff0c;也没搜到什么资料来解释这个问题&#xff08;也许是太简单&#xff1f;&#xff1f;蒟蒻博主怀疑人生……&#xff09; 经过博主不…

【MATLAB源码-第205期】基于matlab的LDPC译码算法仿真,对比BF算法,最小和算法,对数BP和概率BP四种算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 LDPC 码简介 LDPC码是一种通过稀疏奇偶校验矩阵定义的线性分组码&#xff0c;1962年由Gallager首次提出。这种码具有高效的解码性能&#xff0c;尤其在接近香农极限的情况下&#xff0c;其性能表现尤为突出。LDPC码的核心特…

Logstash分析MySQL慢查询日志实践

删除匹配到的行&#xff0c;当前行信息不记录到message中

VMware Workstation 虚拟机学习 安装centos7.9

1打开VMware Workstation--文件--新建虚拟机 #选择对应的&#xff0c;本例选择最新的 2开始安装centos #网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-ens33 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DEFROUTEyes IPV4_FAILURE_FATALno IPV6INITy…

Linux:进程通信(二)信号的保存

目录 一、信号的处理是否是立即处理的&#xff1f; 二、信号如何保存 1、阻塞、未决、递达 2、信号集 3、信号集操作函数 4、sigprocmask函数 5、sigpending 函数 上篇文章我们讲解了信号的产生&#xff1a;Linux&#xff1a;进程信号&#xff08;一&#xff09;信号的产…

【C语言】字符函数和字符串函数--超详解

前言&#xff1a; 在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了⽅便操作字符和字符串&#xff0c;C语⾔标准库中提供了 ⼀系列库函数&#xff0c;接下来我们就学习⼀下这些函数。 1. 字符分类函数 C语⾔中有⼀系列的函数是专⻔做字符分类的&#…

实战BACnet/IP标准通信网关在楼宇自动化中的应用

智慧楼宇建设实现不同设备间的互联互通是一项巨大挑战&#xff0c;尤其是在那些历史悠久的建筑中&#xff0c;新旧系统并存的情况尤为普遍。某大型商业综合体就面临着这样的困境&#xff1a;老旧的暖通空调系统采用Modbus RTU协议&#xff0c;而新部署的能源管理系统却要求BACn…

一文搞懂MySQL索引的数据结构

一、引言 在数据库管理系统中&#xff0c;索引是提高查询性能的关键所在。对于MySQL这类关系型数据库来说&#xff0c;索引更是其优化查询不可或缺的一部分。索引能够大大加快数据的检索速度&#xff0c;减少数据库的I/O操作&#xff0c;提高数据库的整体性能。本文将从索引的…

第2章.STM32开发C语言常用知识点

目录 0. 《STM32单片机自学教程》专栏总纲 2.1. STM32嵌入式开发C语言编程的不同 2.2. C语言常用知识点 2.2.1 位操作 2.2.2 define 宏定义 2.2.3 条件编译 2.2.3.1 #ifdef 2.2.3.2 #ifndef 2.2.3.3 #if !defined 2.2.4 extern 变量声明 2.2.5 typedef 类型别名 …

PPP点对点协议

概述 Point-to-Point Protocol&#xff0c;点到点协议&#xff0c;工作于数据链路层&#xff0c;在链路层上传输网络层协议前验证链路的对端&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 PPP主要是用来通过拨号或专线方式在两个网络节点之间建立连接、…

Mysql:Before start of result set

解决方法&#xff1a;使用resultSet.getString&#xff08;&#xff09;之前一定要调用resultSet.next() ResultSet resultSet statement1.executeQuery();while (resultSet.next()){String username1 resultSet.getString("username");int id1 resultSet.getInt…

识货小程序逆向

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872&#xff0c;x30184483x…

java io模型

目录 BIO 模型模型一&#xff1a;单线程服务器模型二&#xff1a;多线程服务器 NIO 模型模型一&#xff1a;遍历轮训 select/poll模型二&#xff1a;基于事件响应机制的 epoll BIO BIO 模型 模型一&#xff1a;单线程服务器 执行过程&#xff1a;阻塞等待 connection&#xff…

JS-拖拽元素放大缩小

效果左右布局&#xff0c;拖拽后&#xff0c;宽度放大缩小 其实自己写也可以&#xff0c;不过还是发现了两个好用的js库&#xff0c;既然不需要自己写&#xff0c;当然是能偷懒就偷懒 1、resizerjs 官网地址&#xff1a;https://github.com/eknowles/resizerjs <!doctype …