如何从零开始构建一个可用的UVM验证平台_第1页
如何从零开始构建一个可用的UVM验证平台_第2页
如何从零开始构建一个可用的UVM验证平台_第3页
如何从零开始构建一个可用的UVM验证平台_第4页
如何从零开始构建一个可用的UVM验证平台_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

randintunsignedrandintunsigneddelay=0;如何从零开始构建一个可用的UVM验证平台前面大体说明了uvm的结构,前面大体说明了uvm的结构,类型关系以及启动过程。现在最关心的大概也就是uvm是如何把一串激励发送给被测对象的了。对于传统的基于verilog的验证平台,基本套路就是各种module中的task相互调用,最终把激励施加到顶层模块例化的被测对象中,但是具体步骤各个团队又有挺大差异。基于UVM的平台,本质其实也是这样,但是它把各种调用关系进行了更严格的限定,所以所有使用uvm的团队,实现的验证平台都更加相似。下面以之前的apb/spi接口为例具体讲解一下。这里把之前的图再贴过来一下。之前已经说过有关认为是验证平台的硬体,除此之外,还有一些在这之间流动的软体需要近一步说明一下sequencer,driver,monitor,env等的大体功能,这些可以被sequencer,driver,monitor,env等的大体功能,这些可以被。uvm_sequence_item就是这种软体最基本的构造单元。比如可以定义apb端的sequence_item,其中包括读写信息,数据地址这些成员。classapb_transferextendsuvm_sequence_item;randbit[31:0]addr;randapb_direction_enumdirection;randbit[31:0]data;constraintc_direction{directioninside{APB_READAPB_WRITE};}constraintc_delay{delay//这里需要将其中的变量注册一下,这些后边具体讲'uvm_object_utils_begin(apb_transfer)'uvm_field_int(addr,UVM_DEFAULT)'uvm_field_enum(apb_direction_enum,directionUVM_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);endfunction//Registersequencewithasequencer'uvm_object_utils(read_rx_fifo_seq)randbit[31:0]read_addr;randintunsigneddel=0;randintunsignednum_of_rd;constraintnum_of_rd_ct{(num_of_rdconstraintdel_ct{(delconstraintaddr_ct{(read_addr[1:0]==0);}//一个sequence最重要的行为就是body,里边定义这个息序列都发送什么东西virtualtaskbody();'uvm_info(get_type_name(),$sformatf('StartingReads...',num_of_rd),UVM_LOW)response_queue_error_report_disabled=1;for(inti=0;iread_addr='RX_FIFO_REG;//rxfifoaddress'uvm_do_with(req,{req.addr==read_addr;req.direction==APB_READ;req.delay==del;})endendtask//uvm_do_with这个宏负责把各个最基本的sequence_item加上约束发送出去。endclass:read_rx_fifo_seq如何把这个sequence发送出去呢?这就需要在testcase里边把这个sequence通过sequencer发出去。classread_rx_fifo_testextends'uvm_component_utils(read_rx_fifo_test)spi_apb_env_0;//testnew(stringname='read_rx_fifo_test'uvm_test;spi_apb_envendendtask//uvm_do_with这个宏负责把各个最基本的sequence_item加上约束发送出去。endclass:read_rx_fifo_seq如何把这个sequence发送出去呢?这就需要在testcase里边把这个sequence通过sequencer发出去。classread_rx_fifo_testextends'uvm_component_utils(read_rx_fifo_test)spi_apb_env_0;//testnew(stringname='read_rx_fifo_test'uvm_test;spi_apb_env中例化envfunctionuvm_componentparent=null);super.new(name,parent);endfunction:newvirtualfunctionbuild_phase(uvm_phasephase);voidsuper.build_phase(phase);spi_apb_env_0spi_apb_env::type_id::create('spi_apbenv_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连接的接口上。这样就将需要的激励施加给了被测对象。uvm_driver#(apb_transfer);classapb_master_driverextends//连接励施加给了被测对象。uvm_driver#(apb_transfer);classapb_master_driverextends//连接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);endendtaskendendtaskget_and_drive//具体一个发送过程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//在执行时一直在从endtask:赋值给run_phase//在执行时一直在从sqr取item并且viftaskapb_master_driver::get_and_drive();while(1)beginforkbeginforeverbegin@(posedgevif.pclockiff(vif.preset))seq_item_port.get_next_item(req);//从//从sqr取至Uitemdrive_transfer(req);//发送seq_item_port.item_done(req);//告知sqr使其产生下一个itemendendjoin_anydisablefork;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.paddrvif.pselvif.penableif(trans.direction==APB_READ)beginvif.prwdendelsebeginvif.prwdvif.pwdataend@(posedgevif.pclock);endtask:drive_address_phasetaskapb_master_driver::drive_data_phase(apb_transfertrans);vif.penable@(posedgevif.pclockiffvif.pready);if(trans.direction==APB_READ)begintrans.data=vif.prdata;endvif.penablevif.pselendtask:drive_data_phase再重复一下这个基本的步骤在test的main_phase中,由基本的sequence_item组成的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_driver中可以看到这个定义为uvm_seq_item_pull_port#(REQ,RSP)seq_item_port;这里的REQ,RSP都是对应uvm_driver的sequence_item。而uvm_seq_item_pull_port是一个uvm专用的tlm口同样,在uvm_sequencer中有uvm_seq_item_pull_imp#(REQ,RSPthis_type)seq_item_export;而在上层的uvm_agent中有virtualfunctionvoidconnect_phase(uvm_phasephase);logiclogicpenable;logidcr[v1.5s:e0q]_item_port.connepcste(ls;qr.seq_item_export);endfunction这里drv跟sqr分别是例化的uvm_driveruvm_sequencer的名字,可以看到他们两个实质是通过这个tlm接口来传item的。下面图大致说明了这个链接建立以及传送数据程。首先在build后的connect时段,会确立drv.seq_item_port与sqr.seq_item_export的链接,也就是检查port与export的一一对应关系,并将P与t对应的export映射给m_if,而后每次执行driver中的与item_done实际就是执行了sequencer中的get_next_item与item_done。而这实际上就是往一个队列不断存数与取数的过程。详细代码在uvm_sequencer中接来再看第2个问题,driver通过虚接口驱动信号的过这里是apb接口的定义interfaceapb_if(inputpclock,inputpreset);parameterPADDR_WIDTH=32;parameterPWDATA_WIDTH=32;parameterPRDA

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论