如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)_第1頁
如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)_第2頁
如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)_第3頁
如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)_第4頁
如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

randintunsignedrandintunsigneddelay=0;如何從零開始構(gòu)建一個(gè)可用的UVM驗(yàn)證平臺(tái)前面大體說明了uvm的結(jié)構(gòu),前面大體說明了uvm的結(jié)構(gòu),類型關(guān)系以及啟動(dòng)過程?,F(xiàn)在最關(guān)心的大概也就是uvm是如何把一串激勵(lì)發(fā)送給被測(cè)對(duì)象的了。對(duì)于傳統(tǒng)的基于verilog的驗(yàn)證平臺(tái),基本套路就是各種module中的task相互調(diào)用,最終把激勵(lì)施加到頂層模塊例化的被測(cè)對(duì)象中,但是具體步驟各個(gè)團(tuán)隊(duì)又有挺大差異?;赨VM的平臺(tái),本質(zhì)其實(shí)也是這樣,但是它把各種調(diào)用關(guān)系進(jìn)行了更嚴(yán)格的限定,所以所有使用uvm的團(tuán)隊(duì),實(shí)現(xiàn)的驗(yàn)證平臺(tái)都更加相似。下面以之前的apb/spi接口為例具體講解一下。這里把之前的圖再貼過來一下。之前已經(jīng)說過有關(guān)認(rèn)為是驗(yàn)證平臺(tái)的硬體,除此之外,還有一些在這之間流動(dòng)的軟體需要近一步說明一下sequencer,driver,monitor,env等的大體功能,這些可以被sequencer,driver,monitor,env等的大體功能,這些可以被。uvm_sequence_item就是這種軟體最基本的構(gòu)造單元。比如可以定義apb端的sequence_item,其中包括讀寫信息,數(shù)據(jù)地址這些成員。classapb_transferextendsuvm_sequence_item;randbit[31:0]addr;randapb_direction_enumdirection;randbit[31:0]data;constraintc_direction{directioninside{APB_READAPB_WRITE};}constraintc_delay{delay//這里需要將其中的變量注冊(cè)一下,這些后邊具體講'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//對(duì)其他方法沒有進(jìn)行特別的設(shè)定endclass:apb_transfer比uvm_sequence_item稍微高一層極的信息單元是uvm_sequence,這個(gè)可以認(rèn)為是一連串的uvm_sequence_item,可以表達(dá)一個(gè)完整的操作,下面是讀fifo的一個(gè)例子。classread_rx_fifo_seqextendsuvm_sequence#(apb_pkg::apb_transfer);//此類從uvm_sequence派生得到,uvm_sequence是一個(gè)參數(shù)化的類,這里類型賦值為apb_transfer,它被定義在apb_pkg這個(gè)包中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);}//一個(gè)sequence最重要的行為就是body,里邊定義這個(gè)息序列都發(fā)送什么東西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這個(gè)宏負(fù)責(zé)把各個(gè)最基本的sequence_item加上約束發(fā)送出去。endclass:read_rx_fifo_seq如何把這個(gè)sequence發(fā)送出去呢?這就需要在testcase里邊把這個(gè)sequence通過sequencer發(fā)出去。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這個(gè)宏負(fù)責(zé)把各個(gè)最基本的sequence_item加上約束發(fā)送出去。endclass:read_rx_fifo_seq如何把這個(gè)sequence發(fā)送出去呢?這就需要在testcase里邊把這個(gè)sequence通過sequencer發(fā)出去。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);//執(zhí)行基類的任務(wù)read_rx_fifo_seq_inst=read_rx_fifo_seq::type_id::create('read_rx_fifo_seq_inst',this);//產(chǎn)生一個(gè)seqread_rx_fifo_seq_inst.start(spi_apb_env_0.apb_agent_0.apb_sqr);得到了這個(gè)把其中的信息//將seq通過sqr發(fā)送得到了這個(gè)把其中的信息endtaskendclass:read_rx_fifo_testsequencer序列,就要把它交給driver,然后driver元素放置到與dut連接的接口上。這樣就將需要的激勵(lì)施加給了被測(cè)對(duì)象。uvm_driver#(apb_transfer);classapb_master_driverextends//連接勵(lì)施加給了被測(cè)對(duì)象。uvm_driver#(apb_transfer);classapb_master_driverextends//連接driver與dut的虛接virtualapb_ifvif;functionnew(stringname,uvm_componentparent);super.new(name,parent);endfunction:new//在外部定義以下任務(wù)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//具體一個(gè)發(fā)送過程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//在執(zhí)行時(shí)一直在從endtask:賦值給run_phase//在執(zhí)行時(shí)一直在從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);//發(fā)送seq_item_port.item_done(req);//告知sqr使其產(chǎn)生下一個(gè)itemendendjoin_anydisablefork;taskapb_master_driver::drive_transfer(apb_transfertrans);drive_address_phase(trans);//發(fā)送地址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再重復(fù)一下這個(gè)基本的步驟在test的main_phase中,由基本的sequence_item組成的sequence被放到sequencer上執(zhí)行,sequencer將它轉(zhuǎn)交給driver,其后driver通過虛接口將具體信號(hào)施加到被測(cè)對(duì)象上,實(shí)現(xiàn)uvm中激勵(lì)的產(chǎn)生傳輸與施加過程。這里就產(chǎn)生了兩個(gè)問題,一個(gè)是sequencer如何將sequence_item轉(zhuǎn)交給driver,另一個(gè)是driver如何通過虛接口將具體信號(hào)施加到被測(cè)對(duì)象上。這里具體解釋對(duì)于第一個(gè)問題,我們?cè)赿river中有這么2句seq_item_port.get_next_item(req);seq_item_port.item_done(req);這里的seq_item_port就是driver與sequencer通信的接口。在uvm_driver中可以看到這個(gè)定義為uvm_seq_item_pull_port#(REQ,RSP)seq_item_port;這里的REQ,RSP都是對(duì)應(yīng)uvm_driver的sequence_item。而uvm_seq_item_pull_port是一個(gè)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的名字,可以看到他們兩個(gè)實(shí)質(zhì)是通過這個(gè)tlm接口來傳item的。下面圖大致說明了這個(gè)鏈接建立以及傳送數(shù)據(jù)程。首先在build后的connect時(shí)段,會(huì)確立drv.seq_item_port與sqr.seq_item_export的鏈接,也就是檢查port與export的一一對(duì)應(yīng)關(guān)系,并將P與t對(duì)應(yīng)的export映射給m_if,而后每次執(zhí)行driver中的與item_done實(shí)際就是執(zhí)行了sequencer中的get_next_item與item_done。而這實(shí)際上就是往一個(gè)隊(duì)列不斷存數(shù)與取數(shù)的過程。詳細(xì)代碼在uvm_sequencer中接來再看第2個(gè)問題,driver通過虛接口驅(qū)動(dòng)信號(hào)的過這里是apb接口的定義interfaceapb_if(inputpclock,inputpreset);parameterPADDR_WIDTH=32;parameterPWDATA_WIDTH=32;parameterPRDA

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論