FPGA內部資料大匯集課件_第1頁
FPGA內部資料大匯集課件_第2頁
FPGA內部資料大匯集課件_第3頁
FPGA內部資料大匯集課件_第4頁
FPGA內部資料大匯集課件_第5頁
已閱讀5頁,還剩97頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第14章對驗證的支持學習內容理解Verilog文本輸出理解不同的讀取仿真時間的系統(tǒng)函數理解Verilog文件I/O功能第14章對驗證的支持學習內容1驗證系統(tǒng)中的任務(task)及函數(function)Verilog讀取當前仿真時間的系統(tǒng)函數$time $stime $realtimeVerilog支持文本輸出的系統(tǒng)任務: $display $strobe $write $monitor驗證系統(tǒng)中的任務(task)及函數(function)Ver2仿真時間訪問仿真時間$time,$realtime,和$stime函數返回當前仿真時間。這些函數的返回值使用調用模塊中`timescale定義的時間單位$time返回一個64位整數時間值。$stime返回一個32位整數時間值。$realtime返回一個實數時間值。$stime函數返回一個32位整數時間值。對大于232的時間,返回模232的值。使用它可以節(jié)省顯示及打印空間。仿真時間訪問仿真時間3輸出格式化時間信息`timescale10ns/100psmoduletop;regin1;notm1(o1,in1);initialbegin

$timeformat(-9,2,"ns",10);in1=0;#8in1=1;#10$display("%t%b%b",$realtime,in1,o1);#10$finish;endendmodule在這個例子中,顯示的時間為:180.00nsunit:0(s)到-15(fs)之間的整數,表示時間度量precision:要顯示的十進制小數位數。suffix:在時間值后顯示的字符串min_width:顯示前三項的最小寬度若使用多個`timescale,以最小的時間精度顯示時間值??捎孟到y(tǒng)任務$timeformat結合格式符%t全局控制時間顯示方式。$timeformat系統(tǒng)任務的語法為:

$timeformat(<unit>,<precision>,<suffix>,<min_width>);輸出格式化時間信息`timescale10ns/1004輸出格式化時間信息`timescale1ns/10psmoduletop;regin1;not#9.53n1(o1,in1);initialbegin$display("timerealtimestime\tin1\to1");

$timeformat(-9,2,"ns",10);

$monitor("%d%t%d\t%b\t%b",$time,$realtime,$stime,in1,o1);in1=0;#10in1=1;#10$finish;endendmoduletimerealtimestimein1o100.00ns00x109.53ns10011010.00ns10112019.53ns2010輸出格式化時間信息`timescale1ns/105輸出格式化時間信息對#延遲,Verilog將延遲值舍入最近(四舍五入)時間精度值。例如,上面的例子修改為:`timescale1ns/100psnot#9.42n1(o1,in1);結果為:timerealtimestimein1o100.00ns00x99.40ns9011010.00ns10111919.40ns1910`timescale1ns/100psnot#9.49n1(o1,in1);結果為:timerealtimestimein1o100.00ns00x99.50ns9011010.00ns10111919.50ns1910輸出格式化時間信息對#延遲,Verilog將延遲值舍入最近(6顯示信號值—$display$display輸出參數列表中信號的當前值。

語法:$display([“format_specifiers”,]<argument_list>)$display輸出時自動換行。

$display($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);$display($time,“%b\t”,sig1,“%h\t”,sig2,“%d\t”,sig3,“%o”,sig4);$display支持二進制、八進制、十進制和十六進制。缺省基數為十進制。

$display(sig1,sig2,sig3,sig4);$displayb(sig1,sig2,sig3,sig4);$displayo(sig1,sig2,sig3,sig4);$displayh(sig1,sig2,sig3,sig4);%h%o%d%b%c%s%v%m%thexoctaldecimalbinaryASCIIstringstrengthmoduletime\t\n\\\"\<1-3digitoctalnumber>%0dtab換行反斜杠雙引號上述的ASCII表示無前導0的十進制數格式符轉義符顯示信號值—$display$display輸出參數列7顯示信號值—$write和$strobe$write與$display相同,不同的是不會自動換行。$write($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);$strobe與$display相同,不同的是在仿真時間前進之前的信號值。而$display和$write立即顯示信號值。也就是說$strobe顯示穩(wěn)定狀態(tài)信號值,而$display和$write可以顯示信號的中間狀態(tài)值。$strobe($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);$write和$strobe都支持多種數基,缺省為十進制。 $writeb $strobeb $writeo $strobeo $writeh $strobeh顯示信號值—$write和$strobe$write與$di8顯示信號值—$write和$strobe下面是模塊textio仿真的輸出:$writeb輸出:0xxxxxxxxx注意data是32位數據,由8位十六進制數表示。時間以沒有前導零的十進制形式輸出。缺省情況下,值以十進制顯示,忽略前導零,與%0d格式符相同??梢栽谝粋€格式化符前插入一個0使Verilog忽略開頭的零。$displayh:00000000000000f000000101注意當前時間,一個64位量,需要16個十六進制的數。$display:1020$strobe:1030moduletextio;regflag;reg[31:0]data;initialbegin$writeb("%d",$time,,"%h\t",data,,flag,"\n");#15flag=1;data=16;$displayh($time,,data,,flag);endinitialbegin#10data=20;$strobe($time,,data);$display($time,,data);data=30;endendmodule顯示信號值—$write和$strobe下面是模塊texti9監(jiān)視信號值—$monitor$monitor持續(xù)監(jiān)視參數列表中的變量。在一個時間片中,參數表中任何信號發(fā)生變化,$monitor將在仿真時間前進前顯示參數表的信號值。后面的$monitor將覆蓋前面的$monitor??梢杂孟到y(tǒng)任務$monitoron和$monitoroff控制持續(xù)監(jiān)視。$monitor支持多種基數。缺省為十進制。$monitor($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);監(jiān)視信號值—$monitor$monitor持續(xù)監(jiān)視參數列表10監(jiān)示信號值—$monitor$monitor是唯一的不斷輸出信號值的系統(tǒng)任務。其它系統(tǒng)任務在返回值之后就結束。$monitor和$strobe一樣,顯示參數列表中信號的穩(wěn)定狀態(tài)值,也就是在仿真時間前進之前顯示信號。在一個時間步中,參數列表中信號值的任何變化將觸發(fā)$monitor。但$time,$stime,$realtime不能觸發(fā)。任何后續(xù)的$monitor覆蓋前面調用的$monitor。只有新的$monitor的參數列表中的信號被監(jiān)視,而前面的$monitor的參數則不被監(jiān)視??梢杂?monitoron和$monitoroff系統(tǒng)任務控制持續(xù)監(jiān)視,使用戶可以在仿真時只監(jiān)視特定時間段的信號。$monitor參數列表的形式與$display相同。$monitor支持多種基數。缺省為十進制。 $monitorb $monitoro $monitorh監(jiān)示信號值—$monitor$monitor是唯一的不斷輸出11文件輸出$fopen打開一個文件并返回一個多通道描述符(MCD)。MCD是與文件唯一對應的32位無符號整數。如果文件不能打開并進行寫操作,MCD將等于0。如果文件成功打開,MCD中的一位將被置位。以$f開始的顯示系統(tǒng)任務將輸出寫入與MCD相對應的文件中。...integer

MCD1;

MCD1=$fopen("<name_of_file>");$fdisplay(MCD1,P1,P2,..,Pn);$fwrite(MCD1,P1,P2,..,Pn);$fstrobe(MCD1,P1,P2,..,Pn);$fmonitor(MCD1,P1,P2,..,Pn);$fclose(MCD1);...文件輸出$fopen打開一個文件并返回一個多通道描述符(MC12文件輸出$fopen打開參數中指定的文件并返回一個32位無符號整數MCD,MCD是與文件一一對應的多通道描述符。如果文件不能打開并進行寫操作,它返回0。$fclose關閉MCD指定的通道。輸出信息到log文件和標準輸出的四個格式化顯示任務($display,$write,$monitor,$strobe)都有相對應的任務用于向指定文件輸出。這些對應的任務($fdisplay,$fwrite,$fmonitor,$fstrobe)的參數形式與對應的任務相同,只有一個例外:第一個參數必須是一個指定向何哪個文件輸出的MCD。MCD可以是一個表達式,但其值必須是一個32位的無符號整數。這個值決定了該任務向哪個打開的文件寫入。MCD可以看作由32個標志構成的組,每個標志代表一個單一的輸出通道。文件輸出$fopen打開參數中指定的文件并返回一個32位無符13文件輸出...integermessages,broadcast,cpu_chann,alu_chann;initialbegin

cpu_chann=$fopen("cpu.dat");if(!cpu_chann)$finish;

alu_chann=$fopen("alu.dat");if(!alu_chann)$finish;//channeltobothcpu.datandalu.dat

messages=cpu_chann|alu_chann;//channeltobothfiles,standardout,andverilog.log

broadcast=1|messages;endalways@(posedgeclock)//printthefollowingtoalu.dat

$fdisplay(alu_chann,"acc=%hf=%ha=%hb=%h",acc,f,a,b);/*ateveryresetprintamessagetoalu.dat,cpu.dat,standardoutputandtheverilog.logfile*/always@(negedgereset)$fdisplay(broadcast,"systemresetattime%d",$time);...必須聲明為integer通道0(編號為1)為標準輸出及verilog.log文件輸出...必須聲明為integer通道0(編號為1)14文件輸入Verilog中有兩個系統(tǒng)任務可以將數據文件讀入寄存器組。一個讀取二進制數據,另一個讀取十六進制數據:$readmemb$readmemb("file_name",<memory_name>);$readmemb("file_name",<memory_name>,<start_addr>);$readmemb("file_name",<memory_name>,<start_addr>,<finish_addr>);$readmemh$readmemh("file_name",<memory_name>);$readmemh("file_name",<memory_name>,<start_addr>);$readmemh("file_name",<memory_name>,<start_addr>,<finish_addr>);文件輸入Verilog中有兩個系統(tǒng)任務可以將數據文件讀入寄存15文件輸入系統(tǒng)任務$readmemb和$readmemh從一個文本文件讀取數據并寫入存儲器。如果數據為二進制,使用$readmemb;如果數據為十六進制,使用$readmemh。filename指定要調入的文件。mem_name指定存儲器名。start和finish決定存儲器將被裝載的地址。Start為開始地址,finish為結束地址。如果不指定開始和結束地址,$readmem按從低端開始讀入數據,與說明順序無關。文件輸入系統(tǒng)任務$readmemb和$readmemh從一個16文件輸入$readmemb和$readmemh的文件格式:$readmemb("mem_file.txt",mema);0000_00000110_00010011_0010//地址3~255沒有定義@100//hex1111_1100//地址257~1022沒有定義@3FF1110_0010文本文件:mem_file.txt0000000000110000110011001031111110025611100010102307聲明的存儲器組reg[0:7]mema[0:1023]modulereadmem;reg[0:7]mema[0:1023]initial$readmemb(“mem_file.txt”,mema);endmodule文件輸入$readmemb和$readmemh的文件格式:17文件輸入$readmemb和$readmemh的文件格式:$readmemb("mem_file.txt",mema);可以指定二進制(b)或十六進制(h)數用下劃線(_)提高可讀性??梢园瑔涡谢蚨嘈凶⑨???梢杂每崭窈蛽Q行區(qū)分存儲器字??梢越o后面的值設定一個特定的地址,格式為:

@(hex_address)十六進制地址的大小寫不敏感。在@和數字之間不允許有空格。

文件輸入$readmemb和$readmemh的文件格式:18復習問題:哪個系統(tǒng)任務顯示參數列表中信號的穩(wěn)定狀態(tài)值?每次能打開多少個輸出文件?解答:系統(tǒng)任務$monitor和$strobe顯示參數列表中信號的穩(wěn)定狀態(tài)值。這些任務在時間前進之前輸出信號值。每次只能打開一個輸出文件,包括已由仿真器打開的任何log文件。復習問題:解答:19第十五章VerilogTestBench使用簡介學習內容:用一個復雜的testbench復習設計的組織與仿真建立testbench通常使用的編碼風格及方法第十五章VerilogTestBench使用簡介學習20設計組織虛線表示編譯時檢測輸入文件是否存在及可讀并允許生成輸出文件。設計組織虛線表示編譯時檢測輸入文件是否存在及可讀并允許生成輸21testbench組織簡單的testbench向要驗證的設計提供向量,人工驗證輸出。復雜的testbench是自檢測的,其結果自動驗證。stimulus要驗證的設計簡單的testbench復雜的testbench激勵驗證結果要驗證的設計testbench組織簡單的testbench向要驗證的22并行塊fork…join塊在測試文件中很常用。他們的并行特性使用戶可以說明絕對時間,并且可以并行的執(zhí)行復雜的過程結構,如循環(huán)或任務。moduleinline_tb;reg[7:0]data_bus;//instanceofDUTinitialforkdata_bus=8'b00;#10data_bus=8'h45;#20repeat(10)#10data_bus=data_bus+1;#25repeat(5)#20data_bus=data_bus<<1;#140data_bus=8'h0f;joinendmodule上面的兩個repeat循環(huán)從不同時間開始,并行執(zhí)行。象這樣的特殊的激勵集在單個的begin…end塊中將很難實現。Time|data_bus0|8’b0000_000010|8’b0100_010130|8’b0100_011040|8’b0100_011145|8’b1000_111050|8’b1000_111160|8’b1001_000065|8’b0010_000070|8’b0010_000180|8’b0010_001085|8’b0100_010090|8’b0100_0101100|8’b0100_0110105|8’b1000_1100110|8’b1000_1101120|8’b1000_1110125|8’b0001_1100140|8’b0000_1111并行塊fork…join塊在測試文件中很常用。他們的并行特性23包含文件包含文件用于讀入代碼的重復部分或公共數據。moduleclk_gen(clk);outputclk;regclk;`include"common.txt"initialbeginwhile($time<sim_end)beginclk=initial_clock;#(period/2)clk=!initial_clock;#(period/2);end$finish;endendmodule在上面的例子中,公共參數在一個獨立的文件中定義。此文件在不同的仿真中可被不同的測試文件調用。//common.txt//clockandsimulatorconstantsparameterinitial_clock=1;parameterperiod=15;parametermax_cyc=100;parametersim_end=period*max_cyc包含文件包含文件用于讀入代碼的重復部分或公共數據。modu24施加激勵產生激勵并加到設計有很多種方法。一些常用的方法有:從一個initial塊中施加線激勵從一個循環(huán)或always塊施加激勵從一個向量或整數數組施加激勵記錄一個仿真過程,然后在另一個仿真中回放施加激勵施加激勵產生激勵并加到設計有很多種方法。一些常用的方法有:25線性激勵線性激勵有以下特性:只有變量的值改變時才列出易于定義復雜的時序關系對一個復雜的測試,測試基準(testbench)可能非常大moduleinline_tb;reg[7:0]data_bus,addr;wire[7:0]results;DUTu1(results,data_bus,addr);initialforkdata_bus=8'h00;addr=8'h3f;#10data_bus=8'h45;#15addr=8'hf0;#40data_bus=8'h0f;#60$finish;joinendmodule線性激勵線性激勵有以下特性:moduleinline_t26循環(huán)激勵從循環(huán)產生激勵有以下特性:在每一次循環(huán),修改同一組激勵變量時序關系規(guī)則代碼緊湊moduleloop_tb;regclk;reg[7:0]stimulus;wire[7:0]results;integeri;DUTu1(results,stimulus);alwaysbegin//clockgenerationclk=1;#5clk=0;#5endinitialbeginfor(i=0;i<256;i=i+1)@(negedgeclk)stimulus=i;#20$finish;endendmodule循環(huán)激勵從循環(huán)產生激勵有以下特性:moduleloop_t27數組激勵從數組產生激勵有以下特性:在每次反復中,修改同一組激勵變量激勵數組可以直接從文件中讀取modulearray_tb;reg[7:0]data_bus,stim_array[0:15];//數組integeri;DUTu1(results,stimulus);initialbegin//從數組讀入數據#20stimulus=stim_array[0];#30stimulus=stim_array[15];//線激勵#20stimulus=stim_array[1];for(i=14;i>1;i=i-1)//循環(huán)#50stimulus=stim_array[i];#30$finish;endendmodule數組激勵從數組產生激勵有以下特性:modulearray_28矢量采樣在仿真過程中可以對激勵和響應矢量進行采樣,作為其它仿真的激勵和期望結果。modulecapture_tb;parameterperiod=20reg[7:0]in_vec,out_vec;integerRESULTS,STIMULUS;DUTu1(out_vec,in_vec);initialbeginSTIMULUS=$fopen("stimulus.txt");RESULTS=$fopen("results.txt");fork

if(STIMULUS!=0)forever#(period/2)$fstrobeb(STIMULUS,"%b",in_vec);

if(RESULTS!=0)#(period/2)forever#(period/2)$fstrobeb(RESULTS,"%b",out_vec);joinendendmodule矢量采樣在仿真過程中可以對激勵和響應矢量進行采樣,作為其它仿29矢量回放保存在文件中的矢量反過來可以作為激勵moduleread_file_tb;parameternum_vecs=256;reg[7:0]data_bus;reg[7:0]stim[num_vecs-1:0];integeri;DUTu1(results,data_bus)initialbegin//Vectorsareloaded$readmemb("vec.txt",stim);for(i=0;i<num_vecs;i=i+1)#50data_bus=stim[i];endendmodule//激勵文件vec.txt001110000011100100111010001111000011000000101000000110000111100010111000..使用矢量文件輸入/輸出的優(yōu)點:激勵修改簡單設計反復驗證時直接使用工具比較矢量文件。矢量回放保存在文件中的矢量反過來可以作為激勵moduler30錯誤及警告報告使用文本或文件輸出類的系統(tǒng)任務報告錯誤及警告always@(posedgepar_err)$display("error-busparityerrorsdetected");always@(posedgecor_err)$display("warning-correctableerrordetected");一個更為復雜的testbench可以:不但能報告錯誤,而能進行一些動作,如取消一個激勵塊并跳轉到下一個激勵。在內部保持錯誤跟蹤,并在每次測試結束時產生一個錯誤報告。錯誤及警告報告使用文本或文件輸出類的系統(tǒng)任務報告錯誤及警告a31強制激勵在過程塊中,可以用兩種持續(xù)賦值語句驅動一個值或表達式到一個信號。過程持續(xù)賦值通常不可綜合,所以它們通常用于測試基準描述。對每一種持續(xù)賦值,都有對應的命令停止信號賦值。不允許在賦值語句內部出現時序控制。對一個寄存器使用assign和deassign,將覆蓋所有其他在該信號上的賦值。這個寄存器可以是RTL設計中的一個節(jié)點或測試基準中在多個地方賦值的信號等。

initialbegin#10assigntop.dut.fsm1.state_reg=`init_state;#20deassigntop.dut.fsm1.state_reg;end在register和net上(例如一個門級掃描寄存器的輸出)使用force和release,將覆蓋該信號上的所有其他驅動。

initialbegin#10forcetop.dut.counter.scan_reg.q=0;#20releasetop.dut.counter.scan_reg.q;end強制激勵在過程塊中,可以用兩種持續(xù)賦值語句驅動一個值或表達式32強制激勵可以強制(force)并釋放一個信號的指定位、部分位或連接,但位的指定不能是一個變量(例如out_vec[i])不能對register的一位或部分位使用assign和deassign對同一個信號,force覆蓋assign。后面的assign或force語句覆蓋以前相同類型的語句。如果對一個信號先assign然后force,它將保持force值。在對其進行release后,信號為assign值。如果在一個信號上force多個值,然后release該信號,則不出現任何force值。在上面兩個例子中,在net或register上所賦的常數值,覆蓋所有在時刻10和時刻20之間可能發(fā)生在該信號上的其他任何賦值或驅動。如果所賦值是一個表達式,則該表達式將被持續(xù)計算。強制激勵在上面兩個例子中,在net或register上所賦33建立時鐘例1:雖然有時候在設計中給出時鐘,但通常時鐘是測試基準中建立。下面介紹如何產生不同的時鐘波形。同時給出用門級和行為級描述方法下面是一個簡單對稱時鐘的例子:regck;alwaysbegin#(period/2)ck=0;#(period/2)ck=1;endreggo;wireck;nand#(period/2)u1(ck,ck,go);initialbegingo=0;#(period/2)go=1;end注意:在一些仿真器中,時鐘與設計使用相同的抽象級描述時,仿真性能會好一些。產生的波形(假定period為20)建立時鐘例1:雖然有時候在設計中給出時鐘,但通常時鐘是測試基34建立時鐘例2:有啟動延時的對稱時鐘的例子:regck;initialbeginck=0;#(period)forever#(period/2)ck=!ck;endreggo;wireck;nand#(period/2)u1(ck,ck,go);initialbegingo=0;#(period)go=1;end注意:在行為描述中,在時間0將CK初始化為0;而在結構描述中,直到period/2才影響CK值。當go信號在時間0初始化時,CK值到period/2才變化??梢允褂锰厥饷頵orce和release立即影響CK值。產生的波形(假定period為20)建立時鐘例2:有啟動延時的對稱時鐘的例子:regck;re35建立時鐘例3:有不規(guī)則啟動延時的不對稱時鐘的例子:注意:在行為描述中,CK值立刻被影響;而在結構描述中,在傳播延時后才輸出正確波形。產生的波形(假定period為20)regck;initialbegin#(period+1)ck=1;#(period/2–1)foreverbegin#(period/4)ck=0;#(3*period/4)ck=1;endendreggo;wireck;nand#(3*period/4,period/4)u1(ck,ck,go);initialbegin#(period/4+1)go=0;#(5*period/4–1)go=1;end建立時鐘例3:有不規(guī)則啟動延時的不對稱時鐘的例子:注意:在行36使用task在testbench中使用task可以壓縮重復操作,提高代碼效率。modulebus_ctrl_tb;reg[7:0]data;regdata_valid,data_rd;cpuu1(data_valid,data,data_rd);initialbegincpu_driver(8'b0000_0000);cpu_driver(8'b1010_1010);cpu_driver(8'b0101_0101);endtaskcpu_driver;input[7:0]data_in;begin#30data_valid=1;wait(data_rd==1);#20data=data_in;wait(data_rd==0);#20data=8'hzz;#30data_valid=0;endendtaskendmodule

使用task在testbench中使用task可以壓縮重復37使用task產生的波形使用task產生的波形38復習問題:什么操作可以容易的在fork…join塊做到,而不容易在begin…end塊做到?通常怎樣產生規(guī)則激勵和不規(guī)則激勵?從一個文件中讀取激勵時使用什么數據類型?在行為級時鐘模型中能做哪些在門級時鐘模型中很難或不能作到的事?解答:fork…join塊中不但能夠賦值,還可以并行執(zhí)行循環(huán)、條件語句、任務或函數調用。循環(huán)或always塊能有效地產生規(guī)則激勵,不規(guī)則激勵適合用在initial塊產生。用寄存器組(存儲器)并用$readmem系統(tǒng)任務從一個文件以讀取向量。行為級代碼可以很容易地產生一個啟動時間不規(guī)則的時鐘波形,并且可以在時刻零初始化時鐘。復習問題:解答:39第16章存儲器建模學習內容:如何描述存儲器如何描述雙向端口第16章存儲器建模學習內容:40存儲器件建模描述存儲器必須做兩件事:說明一個適當容量的存儲器。提供內容訪問的級別,例如:只讀讀和寫寫同時讀多個讀操作,同時進行單個寫操作同時有多個讀和多個寫操作,有保證一致性的方法存儲器件建模描述存儲器必須做兩件事:41簡單ROM描述下面的ROM描述中使用二維寄存器組定義了一個存儲器mem。ROM的數據單獨保存在文件my_rom_data中,如右邊所示。通常用這種方法使ROM數據獨立于ROM描述。`timescale1ns/10psmodulemyrom(read_data,addr,read_en_);inputread_en_;input[3:0]addr;output[3:0]read_data;reg[3:0]read_data;reg[3:0]mem[0:15];initial

$readmemb("my_rom_data",mem);always@(addrorread_en_)if(!read_en_)read_data=mem[addr];endmodulemy_rom_data0000010111000011110100100011111110001001100000011101101000011101簡單ROM描述下面的ROM描述中使用二維寄存器組42簡單的RAM描述RAM描述比ROM略微復雜,因為必須既有讀功能又有寫功能,而讀寫通常使用同一數據總線。這要求使用新的處理雙向數據線的建模技術。在下面的例子中,若讀端口未使能,則模型不驅動數據總線;此時若數據總線沒有寫數據驅動,則總線為高阻態(tài)Z。這避免了RAM寫入時的沖突。`timescale1ns/1nsmodulemymem(data,addr,read,write);inout[3:0]data;input[3:0]addr;inputread,write;reg[3:0]memory[0:15];//16*4//讀assigndata=read?memory[addr]:4'bz;//寫always@(posedgewrite)memory[addr]=data;endmodule

這個描述可綜合,但許多工具僅僅產生一個寄存器堆,因此與一個真正的存儲器相比耗費更多的面積。簡單的RAM描述RAM描述比ROM略微復雜,因為43參數化存儲器描述在下面的例子中,給出如何定義一個字長和地址均參數化的只讀存儲器件。modulescalable_ROM(mem_word,address);

parameteraddr_bits=8;//地址總線寬度

parameterwordsize=8;//字寬

parameterwords=(1<<addr_bits);//mem容量

output[wordsize:1]mem_word;//存儲器字

input[addr_bits:1]address;//地址總線

reg[wordsize:1]mem[0:words-1];//mem聲明//輸出存儲器的一個字

wire[wordsize:1]mem_word=mem[address];endmodule

例中存儲器字范圍從0而不是1開始,因為存儲器直接用地址線確定地址。也可以用下面的方式聲明存儲器并尋址。reg[wordsize:1]mem[1:words];//從地址1開始的存儲器//存儲器尋址時地址必須加1wire[wordsize:1]mem_word=mem[address+1];

參數化存儲器描述在下面的例子中,給出如何定義一個字44存儲器數據裝入可以使用循環(huán)或系統(tǒng)任務給存儲器裝入初始化數據用循環(huán)給存儲器的每個字賦值for(i=0;i<memsize;i=i+1)

//initializememorymema[i]={wordsize{1'b1}};

調用系統(tǒng)任務$readmem$readmemb("mem_file.txt",mema);

可以用系統(tǒng)任務$readmem給一個ROM或RAM加載數據。對于ROM,開始時寫入的數據就是其實際內容。對于RAM,可以通過初始化,而不是用不同的寫周期給每個字裝入數據以減少仿真時間。存儲器數據裝入可以使用循環(huán)或系統(tǒng)任務給存儲器裝入初始化數據45使用雙向端口用關鍵詞inout聲明一個雙向端口

inout[7:0]databus;雙向端口聲明遵循下列規(guī)則:inout端口不能聲明為寄存器類型,只能是net類型。這樣仿真器若有多個驅動時可以確定結果值。對inout端口可以從任意一個方向驅動數據。端口數據類型缺省為net類型。不能對net進行過程賦值,只能在過程塊外部持續(xù)賦值,或將它連接到基本單元。在同一時間應只從一個方向驅動inout端口。例如:在RAM模型中,如果使用雙向數據總線讀取RAM數據,同時在數據總線上驅動寫數據,則會產生邏輯沖突,使數據總線變?yōu)槲粗?。必須設計與inout端口相關的邏輯以確保正確操作。當把該端口作為輸入使用時,必須禁止輸出邏輯。使用雙向端口用關鍵詞inout聲明一個雙向端口46雙向端口建?!褂没締卧odulebus_xcvr(bus_a,bus_b,en_a_b,en_b_a);inoutbus_a,bus_b;inputen_a_b,en_b_a;bufif1b1(bus_b,bus_a,en_a_b);bufif1b2(bus_a,bus_b,en_b_a);//Structuralmodulelogicendmodule

若en_a_b=1,基本單元b1使能,bus_a數據傳送到bus_b若en_b_a=1,基本單元b2使能,bus_b數據傳送到bus_a信號en_a_b和en_b_a控制使能雙向端口建?!褂没締卧odulebus_xc47雙向端口建?!褂贸掷m(xù)賦值建模modulebus_xcvr(bus_a,bus_b,en_a_b,en_b_a);inoutbus_a,bus_b;inputen_a_b,en_b_a;assignbus_b=en_a_b?bus_a:'bz;assignbus_a=en_b_a?bus_b:'bz;//Structuralmodulelogicendmodule

若en_a_b=1,賦值語句驅動bus_a數據到bus_b若en_b_a=1,賦值語句驅動bus_b值到bus_a信號en_a_b和en_b_a控制使能雙向端口建?!褂贸掷m(xù)賦值建模modulebus_xc48雙向端口建?!鎯ζ鞫丝诮oduleram_cell(databus,rd,wr);inoutdatabus;inputrd,wr;regdatareg;assigndatabus=rd?datareg:'bz;always@(negedgewr)datareg<=databus;endmodule當rd=1時,datareg的值賦值databus在wr下降沿,databus數據寫入datareg雙向端口建?!鎯ζ鞫丝诮oduleram_cel49復習問題:在Verilog中用什么結構定義一個存儲器組?如何向存儲器加載數據?如何通過一個雙向(inout)端口傳送數據?解答:在Verilog中將存儲器聲明為一個一個2維寄存器陣列??梢杂孟到y(tǒng)任務$readmem或$readmemb或用過程賦值向存儲器加載數據因為inout兩端信號必須都是net數據類型,因此只能使用基本單元,子模塊,或持續(xù)賦值驅動數據。同時還必須注意確保在任何一端不要發(fā)生驅動沖突。復習問題:解答:50演講完畢,謝謝觀看!演講完畢,謝謝觀看!51第14章對驗證的支持學習內容理解Verilog文本輸出理解不同的讀取仿真時間的系統(tǒng)函數理解Verilog文件I/O功能第14章對驗證的支持學習內容52驗證系統(tǒng)中的任務(task)及函數(function)Verilog讀取當前仿真時間的系統(tǒng)函數$time $stime $realtimeVerilog支持文本輸出的系統(tǒng)任務: $display $strobe $write $monitor驗證系統(tǒng)中的任務(task)及函數(function)Ver53仿真時間訪問仿真時間$time,$realtime,和$stime函數返回當前仿真時間。這些函數的返回值使用調用模塊中`timescale定義的時間單位$time返回一個64位整數時間值。$stime返回一個32位整數時間值。$realtime返回一個實數時間值。$stime函數返回一個32位整數時間值。對大于232的時間,返回模232的值。使用它可以節(jié)省顯示及打印空間。仿真時間訪問仿真時間54輸出格式化時間信息`timescale10ns/100psmoduletop;regin1;notm1(o1,in1);initialbegin

$timeformat(-9,2,"ns",10);in1=0;#8in1=1;#10$display("%t%b%b",$realtime,in1,o1);#10$finish;endendmodule在這個例子中,顯示的時間為:180.00nsunit:0(s)到-15(fs)之間的整數,表示時間度量precision:要顯示的十進制小數位數。suffix:在時間值后顯示的字符串min_width:顯示前三項的最小寬度若使用多個`timescale,以最小的時間精度顯示時間值??捎孟到y(tǒng)任務$timeformat結合格式符%t全局控制時間顯示方式。$timeformat系統(tǒng)任務的語法為:

$timeformat(<unit>,<precision>,<suffix>,<min_width>);輸出格式化時間信息`timescale10ns/10055輸出格式化時間信息`timescale1ns/10psmoduletop;regin1;not#9.53n1(o1,in1);initialbegin$display("timerealtimestime\tin1\to1");

$timeformat(-9,2,"ns",10);

$monitor("%d%t%d\t%b\t%b",$time,$realtime,$stime,in1,o1);in1=0;#10in1=1;#10$finish;endendmoduletimerealtimestimein1o100.00ns00x109.53ns10011010.00ns10112019.53ns2010輸出格式化時間信息`timescale1ns/1056輸出格式化時間信息對#延遲,Verilog將延遲值舍入最近(四舍五入)時間精度值。例如,上面的例子修改為:`timescale1ns/100psnot#9.42n1(o1,in1);結果為:timerealtimestimein1o100.00ns00x99.40ns9011010.00ns10111919.40ns1910`timescale1ns/100psnot#9.49n1(o1,in1);結果為:timerealtimestimein1o100.00ns00x99.50ns9011010.00ns10111919.50ns1910輸出格式化時間信息對#延遲,Verilog將延遲值舍入最近(57顯示信號值—$display$display輸出參數列表中信號的當前值。

語法:$display([“format_specifiers”,]<argument_list>)$display輸出時自動換行。

$display($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);$display($time,“%b\t”,sig1,“%h\t”,sig2,“%d\t”,sig3,“%o”,sig4);$display支持二進制、八進制、十進制和十六進制。缺省基數為十進制。

$display(sig1,sig2,sig3,sig4);$displayb(sig1,sig2,sig3,sig4);$displayo(sig1,sig2,sig3,sig4);$displayh(sig1,sig2,sig3,sig4);%h%o%d%b%c%s%v%m%thexoctaldecimalbinaryASCIIstringstrengthmoduletime\t\n\\\"\<1-3digitoctalnumber>%0dtab換行反斜杠雙引號上述的ASCII表示無前導0的十進制數格式符轉義符顯示信號值—$display$display輸出參數列58顯示信號值—$write和$strobe$write與$display相同,不同的是不會自動換行。$write($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);$strobe與$display相同,不同的是在仿真時間前進之前的信號值。而$display和$write立即顯示信號值。也就是說$strobe顯示穩(wěn)定狀態(tài)信號值,而$display和$write可以顯示信號的中間狀態(tài)值。$strobe($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);$write和$strobe都支持多種數基,缺省為十進制。 $writeb $strobeb $writeo $strobeo $writeh $strobeh顯示信號值—$write和$strobe$write與$di59顯示信號值—$write和$strobe下面是模塊textio仿真的輸出:$writeb輸出:0xxxxxxxxx注意data是32位數據,由8位十六進制數表示。時間以沒有前導零的十進制形式輸出。缺省情況下,值以十進制顯示,忽略前導零,與%0d格式符相同??梢栽谝粋€格式化符前插入一個0使Verilog忽略開頭的零。$displayh:00000000000000f000000101注意當前時間,一個64位量,需要16個十六進制的數。$display:1020$strobe:1030moduletextio;regflag;reg[31:0]data;initialbegin$writeb("%d",$time,,"%h\t",data,,flag,"\n");#15flag=1;data=16;$displayh($time,,data,,flag);endinitialbegin#10data=20;$strobe($time,,data);$display($time,,data);data=30;endendmodule顯示信號值—$write和$strobe下面是模塊texti60監(jiān)視信號值—$monitor$monitor持續(xù)監(jiān)視參數列表中的變量。在一個時間片中,參數表中任何信號發(fā)生變化,$monitor將在仿真時間前進前顯示參數表的信號值。后面的$monitor將覆蓋前面的$monitor??梢杂孟到y(tǒng)任務$monitoron和$monitoroff控制持續(xù)監(jiān)視。$monitor支持多種基數。缺省為十進制。$monitor($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);監(jiān)視信號值—$monitor$monitor持續(xù)監(jiān)視參數列表61監(jiān)示信號值—$monitor$monitor是唯一的不斷輸出信號值的系統(tǒng)任務。其它系統(tǒng)任務在返回值之后就結束。$monitor和$strobe一樣,顯示參數列表中信號的穩(wěn)定狀態(tài)值,也就是在仿真時間前進之前顯示信號。在一個時間步中,參數列表中信號值的任何變化將觸發(fā)$monitor。但$time,$stime,$realtime不能觸發(fā)。任何后續(xù)的$monitor覆蓋前面調用的$monitor。只有新的$monitor的參數列表中的信號被監(jiān)視,而前面的$monitor的參數則不被監(jiān)視??梢杂?monitoron和$monitoroff系統(tǒng)任務控制持續(xù)監(jiān)視,使用戶可以在仿真時只監(jiān)視特定時間段的信號。$monitor參數列表的形式與$display相同。$monitor支持多種基數。缺省為十進制。 $monitorb $monitoro $monitorh監(jiān)示信號值—$monitor$monitor是唯一的不斷輸出62文件輸出$fopen打開一個文件并返回一個多通道描述符(MCD)。MCD是與文件唯一對應的32位無符號整數。如果文件不能打開并進行寫操作,MCD將等于0。如果文件成功打開,MCD中的一位將被置位。以$f開始的顯示系統(tǒng)任務將輸出寫入與MCD相對應的文件中。...integer

MCD1;

MCD1=$fopen("<name_of_file>");$fdisplay(MCD1,P1,P2,..,Pn);$fwrite(MCD1,P1,P2,..,Pn);$fstrobe(MCD1,P1,P2,..,Pn);$fmonitor(MCD1,P1,P2,..,Pn);$fclose(MCD1);...文件輸出$fopen打開一個文件并返回一個多通道描述符(MC63文件輸出$fopen打開參數中指定的文件并返回一個32位無符號整數MCD,MCD是與文件一一對應的多通道描述符。如果文件不能打開并進行寫操作,它返回0。$fclose關閉MCD指定的通道。輸出信息到log文件和標準輸出的四個格式化顯示任務($display,$write,$monitor,$strobe)都有相對應的任務用于向指定文件輸出。這些對應的任務($fdisplay,$fwrite,$fmonitor,$fstrobe)的參數形式與對應的任務相同,只有一個例外:第一個參數必須是一個指定向何哪個文件輸出的MCD。MCD可以是一個表達式,但其值必須是一個32位的無符號整數。這個值決定了該任務向哪個打開的文件寫入。MCD可以看作由32個標志構成的組,每個標志代表一個單一的輸出通道。文件輸出$fopen打開參數中指定的文件并返回一個32位無符64文件輸出...integermessages,broadcast,cpu_chann,alu_chann;initialbegin

cpu_chann=$fopen("cpu.dat");if(!cpu_chann)$finish;

alu_chann=$fopen("alu.dat");if(!alu_chann)$finish;//channeltobothcpu.datandalu.dat

messages=cpu_chann|alu_chann;//channeltobothfiles,standardout,andverilog.log

broadcast=1|messages;endalways@(posedgeclock)//printthefollowingtoalu.dat

$fdisplay(alu_chann,"acc=%hf=%ha=%hb=%h",acc,f,a,b);/*ateveryresetprintamessagetoalu.dat,cpu.dat,standardoutputandtheverilog.logfile*/always@(negedgereset)$fdisplay(broadcast,"systemresetattime%d",$time);...必須聲明為integer通道0(編號為1)為標準輸出及verilog.log文件輸出...必須聲明為integer通道0(編號為1)65文件輸入Verilog中有兩個系統(tǒng)任務可以將數據文件讀入寄存器組。一個讀取二進制數據,另一個讀取十六進制數據:$readmemb$readmemb("file_name",<memory_name>);$readmemb("file_name",<memory_name>,<start_addr>);$readmemb("file_name",<memory_name>,<start_addr>,<finish_addr>);$readmemh$readmemh("file_name",<memory_name>);$readmemh("file_name",<memory_name>,<start_addr>);$readmemh("file_name",<memory_name>,<start_addr>,<finish_addr>);文件輸入Verilog中有兩個系統(tǒng)任務可以將數據文件讀入寄存66文件輸入系統(tǒng)任務$readmemb和$readmemh從一個文本文件讀取數據并寫入存儲器。如果數據為二進制,使用$readmemb;如

溫馨提示

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

評論

0/150

提交評論