如何从零开始构建一个可用的UVM验证平台.docx
- 文档编号:12697358
- 上传时间:2023-04-21
- 格式:DOCX
- 页数:9
- 大小:121.91KB
如何从零开始构建一个可用的UVM验证平台.docx
《如何从零开始构建一个可用的UVM验证平台.docx》由会员分享,可在线阅读,更多相关《如何从零开始构建一个可用的UVM验证平台.docx(9页珍藏版)》请在冰豆网上搜索。
如何从零开始构建一个可用的UVM验证平台
如何从零开始构建一个可用的UVM验证平台
前面大体说明了uvm的结构,类型关系以及启动过程。
现在最关心的大概也就是uvm是如何把一串激励发送给被
测对象的了。
对于传统的基于verilog的验证平台,基本套路
层模块例化的被测对象中,但是具体步骤各个团队又有挺大差异。
基于UVM的平台,本质其实也是这样,但是它把各种调用关系进行了更严格的限定,所以所有使用uvm的团队,实现的验证平台都更加相似。
下面以之前的apb/spi接口为例具体讲解一下。
这里把之前的图再贴过来一下。
之前已经说过有关sequencer,driver,monitor,env等的大体功能,这些可以被认为是验证平台的硬体,除此之外,还有一些在这之间流动的软体需要近一步说明一下。
uvm_sequence_item就是这种软体最基本的构造单元。
比如可以定义apb端的
sequence_item,其中包括读写信息,数据地址这些成员。
classapb_transferextendsuvm_sequence_item;
randapb_direction_enumdirection;
constraintc_direction{directioninside{APB_READ,
APB_WRITE};}
constraintc_delay{delay//这里需要将其中的变量注册一下,这些后边具体讲
'uvm_object_utils_begin(apb_transfer)
'uvm_field_int(addr,UVM_DEFAULT)
'uvm_field_enum(apb_direction_enum,direction,
UVM_DEFAULT)
'uvm_field_int(data,UVM_DEFAULT)
'uvm_object_utils_endfunctionnew(stringname='apb_transfer');
super.new(name);
endfunction//对其他方法没有进行特别的设定endclass:
apb_transfer比uvm_sequence_item稍微高一层极的信息单元是uvm_sequence,这个可以认为是一连串的
uvm_sequence_item,可以表达一个完整的操作,下面是读
fifo的一个例子。
classread_rx_fifo_seqextendsuvm_sequence#(apb_pkg:
:
apb_transfer);
//此类从uvm_sequence派生得到,uvm_sequence是一个参数化的类,这里类型赋值为apb_transfer,它被定义在
apb_pkg这个包中
functionnew(stringname='read_rx_fifo_seq');
super.new(name);
read_addr;
randintunsigneddel=0;
randintunsignednum_of_rd;
constraintnum_of_rd_ct{(num_of_rd
constraintdel_ct{(del
constraintaddr_ct{(read_addr[1:
0]==0);}
//一个sequence最重要的行为就是body,里边定义这个信
息序列都发送什么东西
virtualtaskbody();
'uvm_info(get_type_name(),$sformatf('Starting
Reads...',num_of_rd),UVM_LOW)
(inti=0;i
'uvm_do_with(req,
{req.addr==read_addr;
req.direction==APB_READ;
req.delay==del;})
end
endtask
//uvm_do_with这个宏负责把各个最基本的sequence_item
加上约束发送出去。
endclass:
read_rx_fifo_seq如何把这个sequence发送出去呢?
这就需要在testcase里边把这个sequence通过
sequencer发出去。
classread_rx_fifo_testextends
中例化envfunction
uvm_test;'uvm_component_utils(read_rx_fifo_test)spi_apb_envspi_apb_env_0;//testnew(stringname='read_rx_fifo_test',
uvm_componentparent=null);
super.new(name,parent);
endfunction:
newvirtualfunctionvoidbuild_phase(uvm_phasephase);
super.build_phase(phase);
spi_apb_env_0=spi_apb_env:
:
type_id:
:
create('spi_apb_env_0',this);
endfunction:
build_phasevirtualtaskmain_phase(uvm_phasephase);
super.main_phase(phase);
//执行基类的任务
read_rx_fifo_seq_inst
=read_rx_fifo_seq:
:
type_id:
:
create('read_rx_fifo_seq_inst',this);
//产生一个seqread_rx_fifo_seq_inst.start(spi_apb_env_0.apb_agent_0.apb_sqr);
//将seq通过sqr发送
endtaskendclass:
read_rx_fifo_testsequencer得到了这个序列,就要把它交给driver,然后driver把其中的信息元素放置到与dut连接的接口上。
这样就将需要的激励施加给了被测对象。
classapb_master_driverextendsuvm_driver#(apb_transfer);//连接driver与dut的虚接口.
virtualapb_ifvif;
functionnew(stringname,uvm_componentparent);
super.new(name,parent);
endfunction:
new//在外部定义以下任务
externvirtualfunctionvoidbuild_phase(uvm_phasephase);
externvirtualfunctionvoidconnect_phase(uvm_phasephase);
externvirtualtaskrun_phase(uvm_phasephase);
externvirtualprotectedtaskget_and_drive();
externvirtualprotectedtaskdrive_transfer(apb_transfertrans);
externvirtualprotectedtaskdrive_address_phase(apb_transfertrans);
externvirtualprotectedtaskdrive_data_phase(apb_transfertrans);endclass:
apb_master_driverfunctionvoidapb_master_driver:
:
connect_phase(uvm_phasephase);
super.connect_phase(phase);
if(!
uvm_config_db#(virtualapb_if):
:
get(this,'','vif',vif))
'uvm_error('NOVIF',{'virtualinterfacemustbesetfor:
',get_full_name(),'.vif'})
//将虚接口通过配置从顶层取出来,并赋值给vifendfunction:
connect_phasetaskapb_master_driver:
:
run_phase(uvm_phasephase);
get_and_drive();
endtask:
run_phase//在执行时一直在从sqr取item并且赋值给viftaskapb_master_driver:
:
get_and_drive();
while
(1)begin
fork
begin
foreverbegin
@(posedgevif.pclockiff(vif.preset))seq_item_port.get_next_item(req);
//从sqr取到item
drive_transfer(req);
//发送
seq_item_port.item_done(req);
//告知sqr使其产生下一个item
end
endjoin_anydisablefork;
endendtask:
get_and_drive//具体一个发送过程
taskapb_master_driver:
:
drive_transfer(apb_transfertrans);
drive_address_phase(trans);
//发送地址
drive_data_phase(trans);
//发送数据endtask:
drive_transfertaskapb_master_driver:
:
drive_address_phase
(apb_transfertrans);
intslave_indx;
slave_indx=cfg.get_slave_psel_by_addr(trans.addr);
vif.paddr
vif.psel
vif.penable
if(trans.direction==APB_READ)begin
vif.prwd
end
elsebegin
vif.prwdvif.pwdata
end
@(posedgevif.pclock);
endtask:
drive_address_phasetaskapb_master_driver:
:
drive_data_phase(apb_transfertrans);
vif.penable
@(posedgevif.pclockiffvif.pready);
if(trans.direction==APB_READ)begin
trans.data=vif.prdata;
end
vif.penable
vif.psel
endtask:
drive_data_phase再重复一下这个基本的步骤,在
sequence
被放到sequencer上执行,sequencer将它转交给driver,其后driver通过虚接口将具体信号施加到被测对象上,实现uvm中激励的产生传输与施加过程。
这里就产生了两个问题,一个是sequencer如何将sequence_item转交给driver,另一个是driver如何通过虚接口将具体信号施加到被测对象上。
这里具体解释对于第一个问题,我们在driver
中有这么2句
seq_item_port.get_next_item(req);
seq_item_port.item_done(req);
这里的seq_item_port就是driver与sequencer通信的接口。
uvm_seq_item_pull_port#(REQ,RSP)seq_item_port;
这里的REQ,RSP都是对应uvm_driver的sequence_item。
而uvm_seq_item_pull_port是一个uvm专用的tlm口
uvm_seq_item_pull_imp#(REQ,RSP,
this_type)seq_item_export;
voidconnect_phase(uvm_phasephase);
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction
这里drv跟sqr分别是例化的uvm_driveruvm_sequencer的
名字,可以看到他们两个实质是通过这个tlm接口来传递
item的。
下面图大致说明了这个链接建立以及传送数据的过
程。
首先在build后的connect时段,会确立
drv.seq_item_port与sqr.seq_item_export的链接,也就是
export映射给m_if,而后每次执行driver中的get_next_item
get_next_item与item_done。
而这实际上就是往一个队列中
来再看第2个问题,driver通过虚接口驱动信号的过程。
这里是apb接口的定义
interfaceapb_if(inputpclock,inputpreset);parameter
[PADDR_WIDTH-1:
0]paddr;
logic
prwd;
logic[PWDATA_WIDTH-1:
0]pwdata;
logic
penable;
logic[PRDATA_WIDTH-1:
0]prdata;
logic
pslverr;
logic
pready;
endinterface:
apb_if下面是顶层TB中的一段regclock;
regreset;apb_ifapb_if_0(clock,reset);
//例化接口
dut_dummydut(.apb_clock(clock),
.apb_reset(reset),
.apb_if(apb_if_0)
);
//例化被测对象,链接前面定义的接口
initialbegin
uvm_config_db#(virtualapb_if):
:
set(null,
'*.demo_tb0.apb0*','vif',apb_if_0);
//通过config_db将apb_if_0这个实际的接口,传送到验证
平台下层各组件的虚假口中
run_test();
//运行测试
end这里的
uvm_config_db#(virtualapb_if):
:
set对应之前
driver里边的
uvm_config_db#(virtualapb_if):
:
get
也就是在顶层
set,底层get,然后通过uvm_config_db这个
类似数据库的玩意,实现从顶层module到底层class中接口的链接,从而driver中的信息流进dut里边。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 如何 从零开始 构建 一个 可用 UVM 验证 平台