30 UVM Adder Testbench Example

1 Adder Design

加法器设计在时钟的上升沿产生两个变量的加法。复位信号用于clear out信号。
注:加法器可以很容易地用组合逻辑开发。引入时钟和重置,使其具有测试台代码中时钟和重置的样子/风格。

module adder(input clk, reset, input [7:0] in1, in2, output reg [8:0] out);always@(posedge clk or posedge reset) begin if(reset) out <= 0;else out <= in1 + in2;end
endmodule

2 Testbench Code

2.1 Sequence Item

sequence item类包含必要的激励产生数据成员。

class seq_item extends uvm_sequence_item;rand bit [7:0] ip1, ip2;bit [8:0] out;function new(string name = "seq_item");super.new(name);endfunction`uvm_object_utils_begin(seq_item)`uvm_field_int(ip1,UVM_ALL_ON)`uvm_field_int(ip2,UVM_ALL_ON)`uvm_object_utils_endconstraint ip_c {ip1 < 100; ip2 < 100;}
endclass

2.2 Sequence

sequence创建激励并通过sequencer驱动到driver。

class base_seq extends uvm_sequence#(seq_item);seq_item req;`uvm_object_utils(base_seq)function new (string name = "base_seq");super.new(name);endfunctiontask body();`uvm_info(get_type_name(), "Base seq: Inside Body", UVM_LOW);`uvm_do(req);endtask
endclass

2.3 Sequencer

sequencer是在sequence和driver之间建立连接的中介。

class seqcr extends uvm_sequencer#(seq_item);`uvm_component_utils(seqcr)function new(string name = "seqcr", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunction
endclass

2.4 Driver

driver驱动随机后的事务transactions或者sequence item给pin-level接口的DUT。

class driver extends uvm_driver#(seq_item);virtual add_if vif;`uvm_component_utils(driver)function new(string name = "driver", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual add_if) :: get(this, "", "vif", vif))`uvm_fatal(get_type_name(), "Not set at top level");endfunctiontask run_phase (uvm_phase phase);forever begin// Driver to the DUTseq_item_port.get_next_item(req);`uvm_info(get_type_name, $sformatf("ip1 = %0d, ip2 = %0d", req.ip1, req.ip2), UVM_LOW);vif.ip1 <= req.ip1;vif.ip2 <= req.ip2;seq_item_port.item_done();endendtask

2.5 Monitor

UVM monitor是一个passive component,用于使用虚拟接口捕获DUT信号并将其转换为序列项sequence item格式。

class monitor extends uvm_monitor;virtual add_if vif;uvm_analysis_port #(seq_item) item_collect_port;seq_item mon_item;`uvm_component_utils(monitor)function new(string name = "monitor", uvm_component parent = null);super.new(name, parent);item_collect_port = new("item_collect_port", this);mon_item = new();endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);if(!uvm_config_db#(virtual add_if) :: get(this, "", "vif", vif))`uvm_fatal(get_type_name(), "Not set at top level");endfunctiontask run_phase (uvm_phase phase);forever beginwait(!vif.reset);@(posedge vif.clk);mon_item.ip1 = vif.ip1;mon_item.ip2 = vif.ip2;`uvm_info(get_type_name, $sformatf("ip1 = %0d, ip2 = %0d", mon_item.ip1, mon_item.ip2), UVM_HIGH);@(posedge vif.clk);mon_item.out = vif.out;item_collect_port.write(mon_item);endendtask
endclass

2.6 Agent

agent是包含并连接driver,monitor和sequencer实例的容器。

class agent extends uvm_agent;`uvm_component_utils(agent)driver drv;seqcr seqr;monitor mon;function new(string name = "agent", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);if(get_is_active == UVM_ACTIVE) begin drv = driver::type_id::create("drv", this);seqr = seqcr::type_id::create("seqr", this);endmon = monitor::type_id::create("mon", this);endfunctionfunction void connect_phase(uvm_phase phase);if(get_is_active == UVM_ACTIVE) begin drv.seq_item_port.connect(seqr.seq_item_export);endendfunction
endclass

2.7 Scoreboard

UVM scoreboard是检查DUT功能的组件。它使用analysis port从monitor接收事务以进行检查。

class scoreboard extends uvm_scoreboard;uvm_analysis_imp #(seq_item, scoreboard) item_collect_export;seq_item item_q[$];`uvm_component_utils(scoreboard)function new(string name = "scoreboard", uvm_component parent = null);super.new(name, parent);item_collect_export = new("item_collect_export", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctionfunction void write(seq_item req);item_q.push_back(req);endfunctiontask run_phase (uvm_phase phase);seq_item sb_item;forever beginwait(item_q.size > 0);if(item_q.size > 0) beginsb_item = item_q.pop_front();$display("----------------------------------------------------------------------------------------------------------");if(sb_item.ip1 + sb_item.ip2 == sb_item.out) begin`uvm_info(get_type_name, $sformatf("Matched: ip1 = %0d, ip2 = %0d, out = %0d", sb_item.ip1, sb_item.ip2, sb_item.out),UVM_LOW);endelse begin`uvm_error(get_name, $sformatf("NOT matched: ip1 = %0d, ip2 = %0d, out = %0d", sb_item.ip1, sb_item.ip2, sb_item.out));end$display("----------------------------------------------------------------------------------------------------------");endendendtaskendclass

2.8 Environment

env提供了包含agent,scoreboard,和其他验证组件的容器。

class env extends uvm_env;`uvm_component_utils(env)agent agt;scoreboard sb;function new(string name = "env", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);agt = agent::type_id::create("agt", this);sb = scoreboard::type_id::create("sb", this);endfunctionfunction void connect_phase(uvm_phase phase);agt.mon.item_collect_port.connect(sb.item_collect_export);endfunction
endclass

2.9 Test

test位于组件层次顶部。

class base_test extends uvm_test;env env_o;base_seq bseq;`uvm_component_utils(base_test)function new(string name = "base_test", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env_o = env::type_id::create("env_o", this);endfunctiontask run_phase(uvm_phase phase);phase.raise_objection(this);bseq = base_seq::type_id::create("bseq");repeat(10) begin #5; bseq.start(env_o.agt.seqr);endphase.drop_objection(this);`uvm_info(get_type_name, "End of testcase", UVM_LOW);endtask
endclass

2.10 Testbench Top

testbench是一个静态容器,实例化DUT和接口。

module tb_top;bit clk;bit reset;always #2 clk = ~clk;initial begin//clk = 0;reset = 1;#5; reset = 0;endadd_if vif(clk, reset);adder DUT(.clk(vif.clk),.reset(vif.reset),.in1(vif.ip1),.in2(vif.ip2),.out(vif.out));initial begin// set interface in config_dbuvm_config_db#(virtual add_if)::set(uvm_root::get(), "*", "vif", vif);endinitial beginrun_test("base_test");end
endmodule

2.11 Execute Complete Code

Output:

UVM_INFO base_seq.sv(10) @ 5: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 5: uvm_test_top.env_o.agt.drv [driver] ip1 = 22, ip2 = 14
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 10: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 22, ip2 = 14, out = 36
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 10: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 10: uvm_test_top.env_o.agt.drv [driver] ip1 = 92, ip2 = 70
UVM_INFO base_seq.sv(10) @ 15: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 15: uvm_test_top.env_o.agt.drv [driver] ip1 = 4, ip2 = 62
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 18: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 92, ip2 = 70, out = 162
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 20: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 20: uvm_test_top.env_o.agt.drv [driver] ip1 = 57, ip2 = 60
UVM_INFO base_seq.sv(10) @ 25: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 25: uvm_test_top.env_o.agt.drv [driver] ip1 = 47, ip2 = 1
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 26: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 57, ip2 = 60, out = 117
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 30: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 30: uvm_test_top.env_o.agt.drv [driver] ip1 = 74, ip2 = 84
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 34: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 47, ip2 = 1, out = 48
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 35: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 35: uvm_test_top.env_o.agt.drv [driver] ip1 = 42, ip2 = 70
UVM_INFO base_seq.sv(10) @ 40: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 40: uvm_test_top.env_o.agt.drv [driver] ip1 = 48, ip2 = 36
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 42: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 42, ip2 = 70, out = 112
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 45: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 45: uvm_test_top.env_o.agt.drv [driver] ip1 = 91, ip2 = 40
----------------------------------------------------------------------------------------------------------
UVM_INFO scoreboard.sv(28) @ 50: uvm_test_top.env_o.sb [scoreboard] Matched: ip1 = 91, ip2 = 40, out = 131
----------------------------------------------------------------------------------------------------------
UVM_INFO base_seq.sv(10) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO driver.sv(20) @ 50: uvm_test_top.env_o.agt.drv [driver] ip1 = 75, ip2 = 55
UVM_INFO base_test.sv(25) @ 50: uvm_test_top [base_test] End of testcase

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

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

相关文章

数据结构模拟实现LinkedList双向不循环链表

目录 一、双向不循环链表的概念 二、链表的接口 三、链表的方法实现 &#xff08;1&#xff09;display方法 &#xff08;2&#xff09;size方法 &#xff08;3&#xff09;contains方法 &#xff08;4&#xff09;addFirst方法 &#xff08;5&#xff09;addLast方法 …

QT音频编程实战项目(一)ui搭建和槽函数的完成

第一个类实现播放音乐&#xff0c;第二个类实现歌曲列表&#xff0c;第三个类是播放本地歌曲 上边是歌曲的总时长&#xff0c;下边是当前播放的时长。 所需要的槽函数如上图。 这个是构造函数&#xff1a; …

Group k-fold解释和代码实现

Group k-fold解释和代码实现 文章目录 一、Group k-fold解释和代码实现是什么&#xff1f;二、 实验数据设置2.1 实验数据生成代码2.2 代码结果 三、实验代码3.1 实验代码3.2 实验结果3.3 结果解释 四、总结 一、Group k-fold解释和代码实现是什么&#xff1f; 0&#xff0c;1…

找不到msvcp140.dll文件的多种解决方法,五个方法轻松搞定

msvcp140.dll是Microsoft Visual C 2015 Redistributable的一个组件&#xff0c;它是运行许多Windows应用程序所必需的动态链接库文件之一。当这个文件丢失或损坏时&#xff0c;就会导致相关应用程序无法正常启动或运行。本文将全面解析msvcp140.dll丢失的原因以及解决方法。 关…

JavaWeb——前端之AjaxVue

6. 前后端交互 6.1 Ajax&#xff08;原生的&#xff09; 概念&#xff1a; Asynchronous JavaScript And XML&#xff08;异步的JavaScript和XML&#xff09; 作用&#xff1a; 数据交互&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据异步交…

爱思唯尔的KBS——模板、投稿、返修、接收的总结

第二篇论文终于是接受了QAQ&#xff0c;被审稿人疯狂拖时间&#xff0c;KBS是真难绷啊 由于之前发布过关于爱思唯尔旗下的ESWA博客&#xff0c;KBS和ESWA是类似的&#xff0c;因此本篇博客主要说下区别以及期间碰到的各种情况&#xff0c;有疑问依然可以在评论区说&#xff0c;…

从0到1入门C++编程——02 通讯录管理系统

文章目录 一、创建结构体及菜单显示二、添加联系人三、显示联系人四、删除联系人五、查找联系人六、修改联系人七、清空联系人八、退出通讯录 本文通过C实现一个通讯录管理系统&#xff0c;系统要实现的功能如下。 1、添加联系人&#xff1a;向通讯录中添加新人&#xff0c;信息…

Lightroom Classic 2024 for Mac/win中文版:摄影后期处理的极致体验

随着数字摄影的普及&#xff0c;后期处理成为创作过程中的关键环节。对于摄影师而言&#xff0c;一款强大的后期处理软件是必不可少的。Adobe Lightroom Classic 2024正是这样一款备受推崇的软件&#xff0c;它为摄影师提供了从导入、编辑到共享的一站式解决方案&#xff0c;让…

数据结构期末复习(3)栈和队列

堆栈&#xff08;stack&#xff09; 堆栈&#xff08;stack&#xff09;是一种基于后进先出&#xff08;LIFO&#xff0c;Last In First Out&#xff09;原则的数据结构。它模拟了现实生活中的堆栈&#xff0c;类似于一摞盘子或一堆书。 堆栈有两个基本操作&#xff1a;入栈&a…

2.3物理层下面的传输媒体

目录 2.3物理层下面的传输媒体2.3.1导引型传输媒体1.双绞线2.同轴电缆3.光纤 2.3.2非导引型传输媒体无线电微波通信 2.3物理层下面的传输媒体 传输媒体是数据传输系统中在发送器和接收器之间的物理通路 两大类&#xff1a; 导引型传输媒体&#xff1a;电磁波被导引沿着固体媒体…

开放原子训练营(第四季)TobudOS——TobudOS内核移植(keil版)

前言 12月份参加了开放原第四季线下活动&#xff0c;觉得很有意义。通过这篇博文&#xff0c;记录一下这次活动进行的移植TobudOS内核的过程&#xff0c;下面就让我们开始吧。 开发板介绍 本次使用的开发板型号为STM32H750&#xff0c;当然了&#xff0c;其他型号的开发版也…

Angular进阶之六:Progressive rendering

简介 Progressive Rendering 是一种提高 Web 应用性能的方法&#xff0c;允许页面在加载过程中逐步呈现&#xff0c;以提高用户体验。在本文中&#xff0c;我们将探讨如何在 Angular 中通过自定义指令实现 Progressive Rendering&#xff0c;特别是处理从服务器获取大量数据的…

Java开发过程中的幂等性问题

幂等性问题&#xff1a; 1. 有时我们在填写某些 form表单 时&#xff0c;保存按钮不小心快速点了两次&#xff0c;表中竟然产生了两条重复的数据&#xff0c;只是id不一样。 2. 我们在项目中为了解决 接口超时 问题&#xff0c;通常会引入了 重试机制 。第一次请求接口超时了…

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存?

LRU&#xff08;Least Recently Used&#xff09;缓存是一种常用的缓存淘汰策略&#xff0c;用于在有限的缓存空间中存储数据。其基本思想是&#xff1a;如果数据最近被访问过&#xff0c;那么在未来它被访问的概率也更高。因此&#xff0c;LRU缓存会保留最近访问过的数据&…

Python编程新技能:如何优雅地实现水仙花数?

水仙花数&#xff08;Narcissistic number&#xff09;也被称为阿姆斯特朗数&#xff08;Armstrong number&#xff09;或自恋数等&#xff0c;它是一个非负整数&#xff0c;其特性是该数的每个位上的数字的n次幂之和等于它本身&#xff0c;其中n是该数的位数。简单来说&#x…

00-开篇导读:学习分库分表开源框架的正确方法

1 前言 互联网高速发展带来海量的信息化数据&#xff0c;也带来更多的技术挑战。各种智能终端设备&#xff08;比如摄像头或车载设备等&#xff09;以每天千万级的数据量上报业务数据&#xff0c;电商、社交等互联网行业更不必说。这样量级的数据处理&#xff0c;已经远不是传…

SELinux 安全模型——MLS

首发公号&#xff1a;Rand_cs BLP 模型&#xff1a;于1973年被提出&#xff0c;是一种模拟军事安全策略的计算机访问控制模型&#xff0c;它是最早也是最常用的一种多级访问控制模型&#xff0c;主要用于保证系统信息的机密性&#xff0c;是第一个严格形式化的安全模型 暂时无…

机器学习三要素与拟合问题

1.如何构建机器学习模型&#xff1f; 机器学习工作流程总结 1.获取数据 2.数据基本处理 3.特征工程 4.机器学习(模型训练) 5.模型评估 结果达到要求&#xff0c;上线服务&#xff0c;没有达到要求&#xff0c;重新上面步骤 我们使用机器学习监督学习分类预测模型的工作流…

Qt5 安装教程 - 跳过登录界面

Qt5 安装教程 - 跳过登录界面 引言一、下载二、安装三、使用四、修改、维护、卸载 引言 Qt5.14.2及以前的版本有离线安装包&#xff0c;无需登录 (老版本连登录界面也无)。之后的版本需登录进行在线安装。 本文以Qt5.12.2版本为例&#xff0c;说明如何跳过登录界面&#xff0c…

Android Context在四大组件及Application中的表现

文章目录 Android Context在四大组件及Application中的表现Context是什么Context源码Activity流程分析Service流程分析BroadcastReceiver流程分析ContentProvider流程分析Application流程分析 Android Context在四大组件及Application中的表现 Context是什么 Context可以理解…