UVM使用双顶层的用法

15 篇文章 1 订阅

在UVM中,我们一般都是使用单顶层的模式。也就是只有一个uvm_test_top顶层,然后下面有env,env下面有agent等。如下图所示:
在这里插入图片描述
通过uvm_top.print_topology()函数,可以打印uvm的拓扑结构。比如如下我的一个uvm环境,打印的拓扑结构如下:
在这里插入图片描述
如果我有另外一个uvm环境,那么怎么可以简单的,将两个uvm环境给集成到一起,进行整体验证了?

此时,就要用到uvm的双顶层结构。

一、uvm双顶层实现

其实uvm,并没有限定uvm_top下,只能有一个叶子节点,也就是uvm_test,也可以有多个叶子节点,也就是多个uvm_test。只不过,两个字节点的名字,都不能叫做uvm_test_top。

如果两个字节点的名字,是一样的,比如都叫uvm_test_top,那么仿真的时候会报错:
在这里插入图片描述
使用2个uvm_test顶层,结构如下:
在这里插入图片描述
如上图,有2个uvm_test顶层,一个uvm_test顶层名字叫做uvm_test_top,另外一个uvm_test顶层名字叫做uvm_test_top1。

这样的话,每个uvm_test下面,可以有自己的uvm环境。使用这种方式,就可以很容易的将两个,或者多个uvm环境,给集成到一起。

下面说一下,如何进行集成:

比如有另外一个uvm环境,叫做your uvm,那么首先要将这个uvm环境,封装成一个module的顶层wrapper,这样其他uvm环境使用这个uvm环境的时候,只需要例化这个顶层wrapper到他的环境即可。

如下图所示,将your uvm环境需要的RTL信号,定义在module的端口信号列表中,内部在连接到your uvm环境的interface中。
module test_bfm_top(clk,rstn,opcode);
input clk;
input rstn;
input [8:0] opcode;

test_bfm_if test_bfm_intf();
assign test_bfm_intf.clk = clk;
assign test_bfm_intf.rstn = rstn;
assign test_bfm_intf.opcode = opcode;

下面就是关键的代码了:
initial begin
uvm_config_db#(virtual test_bfm_if)::set(uvm_root::get(),“*”,“test_bfm_vif”,test_bfm_intf);
ifndef USER_RUN run_test("test_bfm_base_test"); else
begin
string testname = “test_bfm_base_test”;
ifdef UVM_1_1 uvm_factory fact = uvm_factory::get(); else
uvm_coreservice_t coreservice = uvm_coreservice_t::get();
uvm_factory fact = coreservice.get_factory();
endif if($value$plusargs("+UVM_YOUR_TESTNAME",testname)) $display("found your testname: %s" testname); else $display("use default testname:test_bfm_base_teset"); fact.create_component_by_name(testname,"","bfm_test_top",uvm_top); $display("init_test_bfm_teset:Root has %d children",uvm_top.get_num_children()); end endif
end

首先使用uvm_config_db机制,将interface,传递给your uvm环境中,需要使用的interface的component中去。

增加了USER_RUN这个宏,用来判断,your uvm环境,是单独运行,还是要放到其他的uvm环境中运行。

如果是单独运行,那么直接调用run_test函数,即可启动your uvm环境。

如果是放到其他的uvm环境中运行,那么就不能调用run_test,因为在uvm环境中,run_test不能调用2次。此时,需要自己将your uvm环境中的uvm_test,手动创建一个实例,然后给挂到uvm_top下。

关键的代码就在fact.create_component_by_name这行代码。使用factory的创建component实例机制,根据传入的testname,创建一个命名为bfm_test_top的实例,,并指定父节点为uvm_top。这样创建后,在uvm_top下,就会多一个bfm_test_top这个子节点,这样整个uvm环境,就多了一个uvm_test顶层。

为了让bfm_test_top这个uvm_test顶层,能够通过仿真参数,动态的修改需要跑的testcase,增加了+UVM_YOUR_TESTNAME这个仿真参数,来指定。

在顶层,直接将your uvm环境封装的顶层wrapper例化,然后将模块的端口信号连接一下即可。这样就完成了2个UVM环境的集成。
module tb_top();
reg clk;
reg rstn;
hw_wrapper u_hw_wrapper(
.clk(clk),
.rstn(rstn)
);
initial begin
clk = 1’b0;
forever #10 clk = ~clk;
end
initial begin
rstn = 1’n0;
repeat(100) @(posedge clk);
rstn = 1’b1;
end
// my uvm test
initial begin
uvm_config_db#(virtual sync_if)::set(uvm_root::get(),
“*”,
“sync_intf”,
tb_top.u_hw_wrapper.sync_intf);
end
// your uvm test
wire [8:0] opcode = u_hw_wrapper.opcode;
test_bfm_top u_test_bfm_top(clk,rstn,opcode);
endmodule

当然,在编译的时候,要加入+define+USER_RUN这个宏。

通过uvm_top.print_topology()函数,可以打印此时uvm的拓扑结构:
在这里插入图片描述
从打印可以看出,此时UVM环境,有2个uvm test顶层,每个顶层下面有自己的uvm环境。

通过以上的方式,就将2个uvm环境,给集成到了一个uvm环境中,并且可以通过仿真参数,+UVM_TESTNAME和+UVM_YOUR_TESTNAME,分别指定2个UVM环境,仿真需要跑的testcase。

二、双顶层的好处

以上只是一个简单的例子,来说明,在怎么将2个uvm环境给集成到一起,那么双顶层有什么好处了?

我认为,好处是可以增强uvm环境的复用性。在模块级别,搭建uvm环境验证,当模块层次上升,到ip级,那么这个uvm环境依然还是可以用。从ip级到top级,这个uvm环境依然可以使用。

下面举个例子来说明下。比如对于一个IP,分成2个模块A和B。数据流程从A到B。
在这里插入图片描述
模块A交由验证甲负责,模块B交由验证乙来负责。

在验证开始,验证甲搭建uvm环境,验证模块A。验证乙搭建uvm验证,验证模块B。

当验证甲和验证乙,分别验证完毕后,此时要进行IP级别的验证,那么此时IP集成的验证,就可以使用上面的双顶层方式,将模块A的uvm验证环境和模块B的uvm验证环境给集成到一起,进行IP级的验证,这样就实现了UVM环境的复用。

当然在这种情况下,需要将模块B验证环境中的uvm_driver给去掉,因为输入是来源于模块A,但是monitor以及scoreboar等都是可以复用的。

当IP验证完毕后,需要集成到top进行验证,那top也可以复用这个IP的uvm验证环境。

所以说,双顶层或者多顶层,能够提高uvm环境的复用性。让顶层验证,变得容易。

移知是中国半导体线上讲座和技术交流平台;这里汇聚了众多优秀和资深的大咖,通过提供最接地气的实战课程,分享最实用的经验,为您职场学习和成长助力;关注移知,还可领取新人红包和免费半导体课程!

  • 6
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值