一、軟件平臺(tái)與硬件平臺(tái)
軟件平臺(tái):
操作系統(tǒng):Windows 8.1 64-bit
開發(fā)套件:Vivado2015.4.2
硬件平臺(tái):
評(píng)估板:ZYNQ-7 ZC706 Evaluation Board
二、打開例子工程
1、新建工程,并在IP Catalog中找到Serial RapidIO Gen2
2、雙擊Serial RapidIO Gen2進(jìn)入核的配置界面,所用參數(shù)全部保持默認(rèn),然后直接點(diǎn)擊OK
3、在彈出的的對(duì)話框中直接點(diǎn)擊Generate
4、在彈出的對(duì)話框中點(diǎn)擊OK
5、等待srio_gen2_0核綜合完畢,可能會(huì)花幾分鐘的時(shí)間
6、IP核綜合完畢以后,單擊srio_gen2_0,并點(diǎn)擊鼠標(biāo)右鍵,在彈出的菜單欄中單擊Open IP Example Design…
7、在彈出的的對(duì)話框中選擇例子工程的存放目錄(這個(gè)目錄可任意選擇),然后單擊OK
8、等一段時(shí)間以后例子工程就會(huì)自動(dòng)打開
三、例子工程詳解
3.1 工程概述
RapidIO核的例子工程的仿真頂層代碼里面例化了兩個(gè)實(shí)體,一個(gè)叫做srio_example_top_primary,另外一個(gè)叫做srio_example_top_mirror,如下圖所示
其中每個(gè)例化實(shí)體都能被配置為發(fā)送支持的包類型,檢測(cè)接收包失配以及上報(bào)鏈路的仿真細(xì)節(jié)。下表列出了例子工程中各個(gè)主要模塊的功能簡(jiǎn)介
文件名 |
功能 |
srio_example_top.v |
例子工程的頂層模塊 |
srio_request_gen.v |
生成請(qǐng)求事務(wù)的模塊 |
instruction_list.vh |
這是一個(gè)Verilog頭文件,里面定義了120個(gè)事務(wù),它被包含在srio_request_gen.v模塊中,srio_request_gen.v模塊會(huì)把里面的所有事務(wù)依次發(fā)出去 |
srio_response_gen.v |
這個(gè)模塊用來(lái)產(chǎn)生有響應(yīng)事務(wù)的響應(yīng)包 |
srio_condensed_gen.v |
當(dāng)IP核的端口配置為Condensed I/O模式時(shí),這個(gè)文件才會(huì)出現(xiàn)在例子工程中。它用來(lái)產(chǎn)生Condensed I/O模式的請(qǐng)求事務(wù)。 |
srio_quick_start.v |
這個(gè)模塊與IP核的維護(hù)端口相連,用來(lái)發(fā)起維護(hù)事務(wù)。 |
maintenance_list.vh |
這是一個(gè)Verilog頭文件,里面定義了一些維護(hù)事務(wù),它被包含在srio_quick_start.v模塊中,srio_quick_start.v模塊會(huì)把里面的所有維護(hù)事務(wù)依次發(fā)出去用來(lái)配置相關(guān)寄存器 |
srio_report.v |
在仿真時(shí),這個(gè)模塊用來(lái)產(chǎn)生包接收和發(fā)送的時(shí)間戳,在硬件上運(yùn)行的時(shí)候這個(gè)模塊可以刪除 |
srio_statistics.v |
這個(gè)模塊用來(lái)收集核的統(tǒng)計(jì)信息并通過(guò)寄存器接口提交一些信息,提交的信息可以通過(guò)Vivado的調(diào)試特征以及用戶設(shè)計(jì)來(lái)訪問(wèn) |
srio_sim.v |
srio_sim.v是仿真頂層文件,它例化了兩個(gè)核,分別是primary和mirror,并把它們連接到一起用于仿真。它也包含了上報(bào)測(cè)試是否成功的機(jī)制與超時(shí)(timeout)功能。 |
3.2 工程結(jié)構(gòu)
例子工程的頂層模塊例化了所有核的所有組件和在硬件上執(zhí)行所需要的例子代碼,整個(gè)工程的結(jié)構(gòu)如下圖所示。
整個(gè)結(jié)構(gòu)包括時(shí)鐘模塊,復(fù)位模塊,配置結(jié)構(gòu)以及產(chǎn)生RapidIO事務(wù)的激勵(lì)模塊。
srio_quick_start模塊在頂層srio_example_top.v中例化,它與IP核的維護(hù)端口相連用來(lái)產(chǎn)成維護(hù)事務(wù),維護(hù)事務(wù)在maintenance_list.vh中進(jìn)行定義,用戶可以根據(jù)需要編輯maintenance_list.vh文件來(lái)添加,修改和移除維護(hù)事務(wù)。
srio_request_gen.v模塊也在頂層srio_example_top.v中例化,它用來(lái)產(chǎn)生I/O事務(wù)與消息事務(wù)。這個(gè)模塊也存儲(chǔ)了期望的響應(yīng)并把接收的響應(yīng)與期望值進(jìn)行比較。
srio_response_gen.v模塊也在頂層srio_example_top.v中例化,它用來(lái)為接收到的請(qǐng)求事務(wù)生成對(duì)應(yīng)的響應(yīng)事務(wù)。
通過(guò)上圖可以看出,產(chǎn)生I/O事務(wù)一共有兩種方式:第一種是通過(guò)例子工程中自帶的srio_request_gen.v產(chǎn)生I/O事務(wù);第二種是通過(guò)頂層模塊中Initiator和Target的resquest/response接口自己編寫代碼產(chǎn)生I/O事務(wù)。同理,產(chǎn)生維護(hù)事務(wù)也有兩種方式:第一種是通過(guò)例子工程中自帶的srio_quick_start.v模塊產(chǎn)生維護(hù)事務(wù);第二種是通過(guò)頂層模塊中的維護(hù)接口自己編寫代碼產(chǎn)生維護(hù)事務(wù)。I/O事務(wù)的端口類型是AXI4-Stream類型,維護(hù)事務(wù)的端口類型是AXI4-Lite類型。
默認(rèn)情況下,由于例子工程的頂層srio_example_top.v模塊中,VALIDATION_FEATURES與QUICK_STARTUP兩個(gè)參數(shù)均被設(shè)置為1,如下圖所示
所以,例子工程是采用自帶的srio_request_gen.v和srio_quick_start.v分別產(chǎn)生I/O事務(wù)與維護(hù)事務(wù),另外,推薦注釋掉外部接口以節(jié)省管腳和改善時(shí)序。
如果要使用外部接口產(chǎn)生I/O事務(wù),那么需要設(shè)置參數(shù)VALIDATION_FEATURES=0,并且取消頂層模塊srio_example_top.v中外部接口(axis_ireq_*,axis_tresp_*, axis_iresp_*, axis_treq_*, axis_iotx_*, axis_iorx_*)的注釋。如果要使用外部接口產(chǎn)生維護(hù)事務(wù),那些需要設(shè)置參數(shù)QUICK_STARTUP=0,并且取消頂層模塊srio_example_top.v中外部接口(axis_maintr_*)的注釋。使用外部接口的工程結(jié)構(gòu)如下圖所示
3.3 工程分析
I/O事務(wù)與維護(hù)事務(wù)
默認(rèn)情況下,例子工程會(huì)使用srio_request_gen.v模塊和srio_quick_start.v模塊來(lái)產(chǎn)生I/O事務(wù)與維護(hù)事務(wù)。其中instruction_list.vh頭文件定義了待發(fā)送的I/O事務(wù),maintenance_list.vh頭文件定義了待發(fā)送的維護(hù)事務(wù)。
當(dāng)核被復(fù)位以后,maintenance_list.vh中的維護(hù)事務(wù)可以對(duì)核進(jìn)行配置,維護(hù)事務(wù)可以在maintenance_list.vh進(jìn)行添加、修改或移除。當(dāng)沒(méi)有處理器時(shí),srio_quick_start.v模塊可以用來(lái)管理公共的維護(hù)事務(wù)。當(dāng)核復(fù)位以后,這是一種比較好的配置核的方法。
srio_request_gen.v模塊和srio_response_gen.v模塊可以用來(lái)產(chǎn)生I/O事務(wù),srio_request_gen.v模塊可以用來(lái)產(chǎn)生定義在instruction_list.vh中的I/O請(qǐng)求事務(wù)。instruction_list.vh中的I/O事務(wù)可以被添加、修改或移除,I/O事務(wù)的順序是隨機(jī)的,但是每次重新仿真時(shí)都是按照相同的順序產(chǎn)生的。而且,只有IP核端口支持的事務(wù)才能被產(chǎn)生。srio_request_gen.v模塊還可以追蹤期望的響應(yīng)并且比較接收的響應(yīng)與期望值,這在仿真的時(shí)候可以很方便的確定事務(wù)的收發(fā)情況。
srio_response_gen.v模塊用來(lái)產(chǎn)生接收到的請(qǐng)求所對(duì)應(yīng)的目標(biāo)響應(yīng)I/O事務(wù)。如果寫事務(wù)目標(biāo)地址的第23位到16位為8’h12(address[23:16]=8’h12),那么數(shù)據(jù)負(fù)載會(huì)被存儲(chǔ)在本地存儲(chǔ)器。不需要響應(yīng)的寫事務(wù)會(huì)被丟棄,并且srio_response_gen.v模塊不會(huì)響應(yīng)SWRITE事務(wù)。如果讀事務(wù)目標(biāo)地址的第23位到16位為8’h12(address[23:16]=8’h12),那么數(shù)據(jù)將會(huì)從實(shí)際地址讀出。對(duì)于那些地址不滿足第23位到16位為8’h12(address[23:16]=8’h12)的事務(wù),srio_response_gen.v模塊將以地址遞增的方式寫入I/O事務(wù)攜帶的數(shù)據(jù)。響應(yīng)會(huì)根據(jù)接收到的請(qǐng)求的順序依次產(chǎn)生,所以不會(huì)有無(wú)序的事務(wù)產(chǎn)生。在所有的情況中,響應(yīng)事務(wù)的優(yōu)先級(jí)等于請(qǐng)求事務(wù)的優(yōu)先級(jí)加1。
注意:每個(gè)srio_request_gen.v模塊會(huì)消耗一個(gè)塊RAM(Block RAM),每個(gè)srio_response_gen.v模塊會(huì)消耗兩個(gè)塊RAM(Block RAM)。
配置結(jié)構(gòu)
配置空間分布在RapidIO核的所有塊中,配置結(jié)構(gòu)的參考設(shè)計(jì)在例子設(shè)計(jì)的cfg_fabric模塊中,用來(lái)管理每個(gè)塊配置空間的訪問(wèn)情況。塊(Block)的配置模塊在配置總線(AXI4-Lite)上是作為從機(jī)存在的,cfg_fabric模塊是作為主機(jī)存在的。維護(hù)事務(wù)的讀寫操作是從本地或者遠(yuǎn)程被發(fā)起,它是通過(guò)邏輯層的配置主端口接入配置模塊,配置模塊會(huì)把讀寫事務(wù)送入對(duì)應(yīng)的塊中,但如果地址不在各自配置寄存器的有效范圍內(nèi),配置模塊不會(huì)移交任何讀寫事務(wù)。往非法的空間寫事務(wù)會(huì)被丟棄,讀非法的空間將返回0。
時(shí)鐘模塊
例子設(shè)計(jì)的時(shí)鐘模塊與IP核的時(shí)鐘模塊是相同的。srio_clk模塊有1個(gè)MMCM_ADV,1個(gè)IBUFDS和3個(gè)或4個(gè)BUFGs組成,在2x或4x模式,其中一個(gè)BUFGs將被轉(zhuǎn)化為BUFGMUX。srio_clk模塊會(huì)根據(jù)配置的不同產(chǎn)生合適的參考頻率與用戶時(shí)鐘。
復(fù)位模塊
srio_rst模塊會(huì)把每個(gè)時(shí)鐘域里面的異步復(fù)位信號(hào)轉(zhuǎn)化為一個(gè)脈沖擴(kuò)展的同步復(fù)位信號(hào)。當(dāng)被用戶設(shè)計(jì)調(diào)用的時(shí)候,srio_rst模塊會(huì)用一個(gè)狀態(tài)機(jī)強(qiáng)制對(duì)核重新初始化。
四、工程源碼分析
3.1 頂層模塊srio_example_top.v源碼分析
頂層模塊srio_example_top.v源碼的端口定義如下
頂層模塊包含5個(gè)參數(shù):SIM_VERBOSE,VALIDATION_FEATURES,QUICK_STARTUP,STATISTICS_GATHERING和C_LINK_WIDTH。
SIM_VERBOSE設(shè)為1時(shí),可以利用srio_report.v模塊生成不可綜合的報(bào)告。為0時(shí),此功能被屏蔽。
VALIDATION_FEATURES設(shè)為1時(shí),選擇例子工程中的srio_request_gen.v和srio_response_gen.v產(chǎn)生相應(yīng)的請(qǐng)求事務(wù)與響應(yīng)事務(wù)對(duì)IP核的功能進(jìn)行測(cè)試。為0時(shí),選擇外部的用戶接口由用戶自己編寫請(qǐng)求事務(wù)與響應(yīng)事務(wù)的代碼對(duì)IP進(jìn)行測(cè)試。
QUICK_STARTUP設(shè)為1時(shí),選擇例子工程中的srio_quick_start.v產(chǎn)生相應(yīng)的維護(hù)事務(wù)對(duì)IP核的配置空間進(jìn)行訪問(wèn)。為0時(shí),選擇外部的維護(hù)接口由用戶自己編寫維護(hù)事務(wù)的代碼對(duì)IP核的配置空間進(jìn)行訪問(wèn)。
STATISTICS_GATHERING設(shè)為1時(shí),可以利用srio_statistics.v模塊搜集IP的性能細(xì)節(jié),這個(gè)模塊是可綜合的,可以通過(guò)Chipscope或ILA進(jìn)行訪問(wèn)。為0時(shí),此功能被屏蔽。
頂層模塊的差分時(shí)鐘sys_clkp和sys_clkn就是IP核配置界面第一頁(yè)的參考時(shí)鐘,由于例子工程中采用的全部是默認(rèn)參數(shù),所以這里這個(gè)時(shí)鐘為125MHz,這個(gè)時(shí)鐘可以由FPGA外部的有源晶振或鎖相環(huán)芯片輸出。
sys_rst為IP核的復(fù)位信號(hào),高電平有效。
差分信號(hào)srio_rxn0和srio_rxp0為串行接收數(shù)據(jù)信號(hào),srio_txn0和srio_txp0為串行發(fā)送數(shù)據(jù)信號(hào)。
sim_train_en信號(hào)是一個(gè)用來(lái)減少仿真時(shí)間的控制信號(hào),仿真時(shí)把這個(gè)信號(hào)置1可以加快仿真速度,但是代碼在硬件上運(yùn)行時(shí)這個(gè)信號(hào)必須賦值為0。
led0是led指示信號(hào),可以把port_initialized和link_initialized兩個(gè)信號(hào)接到led0中,這樣在硬件上執(zhí)行時(shí)可以方便觀察鏈路狀態(tài)。
頂層模塊srio_example_top.v中的第466行到第590行例化了RapidIO核,部分源碼如下圖所示
第612行到631行是例化了srio_report.v模塊用來(lái)收集ireq接口的統(tǒng)計(jì)信息。除此以外,還例化了3個(gè)srio_report.v模塊用來(lái)收集iresp,treq,tresp接口的統(tǒng)計(jì)信息。下圖是收集ireq統(tǒng)計(jì)信息的源代碼。源碼如下圖所示
第637行到684行srio_request_gen.v模塊用來(lái)生成請(qǐng)求事務(wù)。這個(gè)模塊有7個(gè)參數(shù),分別為SEND_SWRITE,SEND_NWRITER,SEND_NWRITE,SEND_NREAD,SEND_FTYPE9,SEND_DB和SEND_MSG。當(dāng)他們?cè)O(shè)置為1時(shí),srio_request_gen.v模塊將會(huì)把instruction_list.vh模塊中對(duì)應(yīng)的事務(wù)發(fā)送給SRIO IP核。部分源碼如下圖所示
第779行到804行例化了srio_response_gen.v模塊,這個(gè)模塊用來(lái)產(chǎn)生響應(yīng)事務(wù)。部分源碼如下圖所示
第890行到937行例化了srio_quick_start.v模塊,這個(gè)模塊產(chǎn)生維護(hù)事務(wù)來(lái)訪問(wèn)配置空間。部分源碼如下圖所示
第944行到988行例化了srio_statistics.v模塊,這個(gè)模塊用來(lái)收集統(tǒng)計(jì)信息,它是一個(gè)可綜合的模塊。部分源碼如下圖所示
3.2 模塊srio_request_gen.v源碼分析
模塊srio_request_gen.v的作用是產(chǎn)生RapidIO請(qǐng)求事務(wù),上篇文章《Xilinx RapidIO核詳解》(鏈接:https://www.cnblogs.com/liujinggang/p/10072115.html)已經(jīng)提到過(guò),RapidIO核為了簡(jiǎn)化包的構(gòu)建過(guò)程,設(shè)計(jì)了一種精簡(jiǎn)的包格式——HELLO格式來(lái)完成包的構(gòu)建,然后按照HELLO格式的時(shí)序把數(shù)據(jù)發(fā)送給RapidIO核,RapidIO核會(huì)把HELLO格式的包轉(zhuǎn)化為標(biāo)準(zhǔn)的RapidIO串行物理層的包。這樣,用戶在設(shè)計(jì)請(qǐng)求事務(wù)的Verilog代碼時(shí)只需要對(duì)HELLO格式的包與時(shí)序有所了解,而不需要過(guò)多的關(guān)注RapidIO的協(xié)議與RapidIO包格式。這里重新復(fù)習(xí)一下HELLO格式的包結(jié)構(gòu)與HELLO格式的時(shí)序。
HELLO格式的包結(jié)構(gòu)如下圖所示:
HELLO格式的時(shí)序圖如下圖所示:
事實(shí)上,整個(gè)srio_request_gen.v源代碼的核心就是先構(gòu)建HELLO格式的包,然后把包頭(Header)和數(shù)據(jù)按照HELLO格式的時(shí)序傳給RapidIO核就可以了。下面詳細(xì)分析一下。
分析instruction_list.vh頭文件
在分析srio_request_gen.v源代碼之前先來(lái)分析一下instruction_list.vh頭文件。因?yàn)閟rio_request_gen.v文件中包含了instruction_list.vh頭文件,instruction_list.vh頭文件中定義了srio_request_gen.v將要發(fā)送的所有事務(wù)。
instruction_list.vh頭文件的第1行到第9行定義了事務(wù)的個(gè)數(shù)以及所有事務(wù)的總個(gè)數(shù),每種事務(wù)的個(gè)數(shù)由一個(gè)控制變量進(jìn)行選擇,源碼如下:
第11行到50行是37個(gè)SWRITE事務(wù)(流寫事務(wù)),其中第1列的12位數(shù)據(jù)是由8-bit的保留位(SWRITE事務(wù)沒(méi)有srcTID字段),1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(SWRITE事務(wù)沒(méi)有TTYPE字段),第4列的36-bit數(shù)據(jù)是由最高2-bit的保留位和34-bit的address字段組成,第5列是8-bit保留字段(SWRITE事務(wù)沒(méi)有size字段),不管這個(gè)字段的值為多少,目標(biāo)設(shè)備都會(huì)把這個(gè)值當(dāng)做0來(lái)處理。源代碼如下圖所示
第52行到72行是19個(gè)NWRITE_R事務(wù)(帶響應(yīng)的寫事務(wù)),其中第1列的12位數(shù)據(jù)是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數(shù)據(jù)是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個(gè)字段的值為實(shí)際的數(shù)據(jù)量減1。比如size=0,表示實(shí)際傳輸?shù)臄?shù)據(jù)量為1。源代碼如下圖所示
第74行到94行是19個(gè)NWRITE事務(wù)(寫事務(wù)),其中第1列的12位數(shù)據(jù)是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數(shù)據(jù)是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個(gè)字段的值為實(shí)際的數(shù)據(jù)量減1。比如size=0,表示實(shí)際傳輸?shù)臄?shù)據(jù)量為1。源代碼如下圖所示
第96行到123行是26個(gè)NREAD事務(wù)(讀事務(wù)),其中第1列的12位數(shù)據(jù)是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數(shù)據(jù)是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個(gè)字段的值為實(shí)際的數(shù)據(jù)量減1。比如size=0,表示實(shí)際傳輸?shù)臄?shù)據(jù)量為1。源代碼如下圖所示
第125行到128行是兩個(gè)DOORBELL事務(wù)(門鈴事務(wù)),其中第1列的12位數(shù)據(jù)是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(DOORBELL事務(wù)沒(méi)有TTYPE字段),第4列的36-bit數(shù)據(jù)是由最高4-bit的保留位,8-bit的信息高8位,8-bit的信息低8位以及最后的16-bit保留位組成。第5列是8-bit保留字段(DOORBELL事務(wù)沒(méi)有size字段)。源代碼如下圖所示
第130行到148行是17個(gè)MESSAGE事務(wù)(消息事務(wù)),其中第1列的12位數(shù)據(jù)是由4-bit的msglen,4-bit的msgseg,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(MESSAGE事務(wù)沒(méi)有TTYPE字段),第4列的36-bit數(shù)據(jù)是由最高26-bit的保留位,6-bit的mailbox字段,2-bit的保留位以及2-bit的ltr組成。第5列是8-bit的size字段。源代碼如下圖所示
第150行到152行是1個(gè)Data Streaming事務(wù),這是Xilinx定義的第9類事務(wù),由于這種事務(wù)用的不多,我自己也不太了解,所以這里就不進(jìn)行分析了。源代碼如下圖所示
分析srio_request_gen.v源碼
在分析完畢instruction_list.vh頭文件以后接下來(lái)開始著手分析srio_request_gen.v源碼。分析過(guò)程中始終要記住的一點(diǎn)是:srio_request_gen.v的核心功能就是組裝HELLO包頭并把包頭和數(shù)據(jù)按照HELLO格式的時(shí)序發(fā)送出去。
srio_request_gen.v源碼的第50行到92行是參數(shù)與接口的定義。它包含7個(gè)參數(shù),分別為SEND_SWRITE、SEND_NWRITER、SEND_NWRITE、SEND_NREAD、SEND_DB、SEND_FTYPE9和SEND_MSG,它們的默認(rèn)值被設(shè)置為0,但是在頂層模塊中例化的時(shí)候,它們的值分別被設(shè)置為1、1、1、1、0、1、1。如下圖所示
根據(jù)上面分析instruction_list.vh頭文件可知,如果上面的7個(gè)參數(shù)為1的話,各個(gè)事務(wù)的個(gè)數(shù)應(yīng)該由instruction_list.vh頭文件中NUM_SWRITES、NUM_NWRITERS、NUM_NWRITES、NUM_NREADS、NUM_DBS、NUM_MSGS和NUM_FTYPE9決定。
接下來(lái)就是端口的定義,其中l(wèi)og_clk與log_rst均由IP輸出,log_clk的頻率與鏈路線速率和鏈路寬度有關(guān),具體的對(duì)應(yīng)關(guān)系在上篇文章中能找到。接下來(lái)就是設(shè)備ID,目的ID以及源ID的定義。然后定義了ireq與iresp,它們都采用了AXI4-Stream協(xié)議。link_initialized信號(hào)由IP核輸出,當(dāng)它為高時(shí)表明鏈路成功初始化。以u(píng)ser_*開頭的幾個(gè)變量可以方便用戶自定義HELLO格式包頭中的各個(gè)字段。
第96到110行定義了HELLO格式包頭中的FTYPE字段與TTYPE字段的值,這兩個(gè)字段的值與事務(wù)的類型有關(guān),源碼如下圖所示
第120行定義了一個(gè)memory類型變量,綜合的時(shí)候ram的類型為分布式ram,121行導(dǎo)入了instruction_list.vh頭文件,126行定義的變量可以看做AXI4-Stream總線上數(shù)據(jù)有效的標(biāo)志位,當(dāng)這個(gè)信號(hào)為高時(shí),AXI4-Stream總線上tdata上的數(shù)據(jù)為有效數(shù)據(jù)。源代碼如下圖所示
第178行到205行用來(lái)初始化事務(wù)列表,instruction[ii]存放的是instruction_list.vh頭文件中定義的各個(gè)事務(wù)的相關(guān)字段值,源代碼如下圖所示
第208到第219行是一些簡(jiǎn)單的賦值操作。其中第208行的val_ireq_tkeep和val_ireq_tuser是根據(jù)HELLO格式的時(shí)序要求賦值的,HELLO格式的時(shí)序要求tkeep為8’hFF,tuser在第一個(gè)有效的時(shí)鐘(log_clk)周期內(nèi)由src_id與dest_id拼接而成。第213行和第217行的go變量用來(lái)選擇HELLO格式包頭各個(gè)字段由用戶定義還是由instruction_list.vh定義。第219行的header_beat變量就是HELLO格式的包頭,在第一個(gè)有效時(shí)鐘(log_clk)周期,tdata上的數(shù)據(jù)必須為header_beat。源代碼如下圖所示
第266行到288行主要用來(lái)產(chǎn)生有效時(shí)鐘計(jì)數(shù)器current_beat_cnt與有效時(shí)鐘計(jì)數(shù)總數(shù)number_of_data_beats。當(dāng)AXI4_Stream總線的tvalid和tready信號(hào)同時(shí)為高時(shí),時(shí)鐘為有效時(shí)鐘,current_beat_cnt加1,當(dāng)檢測(cè)到tlast信號(hào)為高時(shí)表明最后一個(gè)數(shù)據(jù)已發(fā)送完畢,所以把current_beat_cnt清0。由于tdata的寬度為64-bit,也就是8個(gè)字節(jié),所以有效時(shí)鐘計(jì)數(shù)總數(shù)number_of_data_beats為current_size右移3位。源代碼如下圖所示
第294行到306行用來(lái)產(chǎn)生AXI4_Stream總線中tlast信號(hào),tlast為高時(shí)表明發(fā)送的是最后一個(gè)數(shù)據(jù),所以tlast信號(hào)相當(dāng)于一幀數(shù)據(jù)的邊界。
第307行到328行用來(lái)產(chǎn)生AXI4_Stream總線中的tdata信號(hào),當(dāng)有效時(shí)鐘計(jì)數(shù)器current_beat_cnt為0時(shí),tdata為包頭header_beat,包頭header_beat后面是待發(fā)送的數(shù)據(jù)data_beat,例子工程為了簡(jiǎn)單起見(jiàn),發(fā)送的數(shù)據(jù)是累加數(shù),每個(gè)累加數(shù)為8-bit,然后把每個(gè)累加數(shù)拼接8次作為待發(fā)送的數(shù)據(jù),也就是說(shuō),待發(fā)送的數(shù)據(jù)為64’h0000000000000000,64’h0101010101010101,64’h0202020202020202,……..,后面以此類推。
第330行到345行主要用來(lái)產(chǎn)生AXI4_Stream總線中的tvalid信號(hào),同時(shí)也產(chǎn)生了一些其他的標(biāo)志信號(hào)。至此,整個(gè)AXI4_Stream總線中的所有信號(hào)的邏輯都編寫完畢,并且整個(gè)邏輯都是完全符合HELLO格式的時(shí)序。代碼的核心部分全部分析完畢。
第351行到第371行與數(shù)據(jù)的存儲(chǔ)相關(guān)。每當(dāng)current_beat_cnt的值為0時(shí),request_address變量加1, request_address也被賦給了tid,也就是說(shuō)request_address也是事務(wù)ID值,同時(shí)request_address也是instruction的索引值。源代碼如下圖所示
第382行到第406行例化了一個(gè)RAMB36SDP原語(yǔ),RAMB36SDP是一個(gè)大小為36Kb的簡(jiǎn)單雙口Block RAM(SDP=Simple Dual Port)。它的作用是把請(qǐng)求事務(wù)的tid,current_ftype和current_size寫入RAM中存起來(lái),對(duì)于有響應(yīng)的事務(wù),RapidIO會(huì)收到一個(gè)響應(yīng)事務(wù),收到響應(yīng)事務(wù)事務(wù)以后可以把存放在RAMB36SDP中的數(shù)據(jù)讀出來(lái)與響應(yīng)事務(wù)中對(duì)應(yīng)的字段進(jìn)行對(duì)比從而對(duì)整個(gè)事務(wù)的交互過(guò)程的正確性進(jìn)行一個(gè)初步判斷。關(guān)于RAMB36SDP原語(yǔ)的詳細(xì)解釋請(qǐng)閱讀下一小節(jié)。源代碼如下圖所示
第458行到482行就是把存儲(chǔ)在RAM中請(qǐng)求事務(wù)的tid,current_ftype和current_size與響應(yīng)事務(wù)對(duì)應(yīng)的字段進(jìn)行對(duì)比,在仿真時(shí)給出對(duì)應(yīng)的提示信息。
至此,整個(gè)產(chǎn)生請(qǐng)求事務(wù)的代碼全部分析完畢,其他未分析到的代碼大家自己嘗試分析。
3.3 RAMB36SDP原語(yǔ)分析
RAMB36SDP是一個(gè)大小為36Kb的簡(jiǎn)單雙口Block RAM(SDP=Simple Dual-Port),它其實(shí)是Virtex-5系列FPGA的一個(gè)原語(yǔ),Vivado里面并沒(méi)有RAMB36SDP的語(yǔ)法模板,ISE中才有它的語(yǔ)法模板,如下圖所示
RAMB36SDP原語(yǔ)的完整代碼如下所示
// RAMB36SDP : In order to incorporate this function into the design, // Verilog : the forllowing instance declaration needs to be placed // instance : in the body of the design code. The instance name // declaration : (RAMB36SDP_inst) and/or the port declarations within the // code : parenthesis may be changed to properly reference and // : connect this function to the design. All inputs // : and outputs must be connected. // <-----Cut code below this line----> // RAMB36SDP: 72x512 Simple Dual-Port BlockRAM w/ ECC // Virtex-5 // Xilinx HDL Language Template, version 14.7 RAMB36SDP #( .SIM_MODE("SAFE"), // Simulation: "SAFE" vs. "FAST", see "Synthesis and Simulation Design Guide" for details .DO_REG(0), // Optional output register (0 or 1) .EN_ECC_READ("FALSE"), // Enable ECC decoder, "TRUE" or "FALSE" .EN_ECC_WRITE("FALSE"), // Enable ECC encoder, "TRUE" or "FALSE" .INIT(72'h000000000000000000), // Initial values on output port .SIM_COLLISION_CHECK("ALL"), // Collision check enable "ALL", "WARNING_ONLY", // "GENERATE_X_ONLY" or "NONE" .SRVAL(72'h000000000000000000), // Set/Reset value for port output // The forllowing INIT_xx declarations specify the initial contents of the RAM .INIT_00(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_01(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_02(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_03(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_04(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_05(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_06(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_07(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_08(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_09(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_0F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_10(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_11(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_12(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_13(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_14(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_15(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_16(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_17(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_18(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_19(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_1F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_20(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_21(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_22(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_23(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_24(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_25(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_26(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_27(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_28(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_29(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_2F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_30(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_31(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_32(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_33(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_34(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_35(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_36(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_37(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_38(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_39(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_3F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_40(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_41(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_42(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_43(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_44(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_45(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_46(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_47(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_48(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_49(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_4F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_50(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_51(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_52(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_53(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_54(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_55(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_56(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_57(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_58(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_59(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_5F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_60(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_61(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_62(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_63(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_64(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_65(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_66(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_67(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_68(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_69(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_6F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_70(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_71(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_72(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_73(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_74(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_75(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_76(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_77(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_78(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_79(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), .INIT_7F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000), // The next set of INITP_xx are for the parity bits .INITP_00(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_01(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_02(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_03(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_04(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_05(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_06(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_07(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_08(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_09(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00), .INITP_0F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00) ) RAMB36SDP_inst ( .DBITERR(DBITERR), // 1-bit double bit error status output .SBITERR(SBITERR), // 1-bit single bit error status output .DO(DO), // 64-bit data output .DOP(DOP), // 8-bit parity data output .ECCPARITY(ECCPARITY), // 8-bit generated error correction parity .RDCLK(RDCLK), // 1-bit read port clock .RDEN(RDEN), // 1-bit read port enable .REGCE(REGCE), // 1-bit register enable input .SSR(SSR), // 1-bit synchronous output set/reset input .WRCLK(WRCLK), // 1-bit write port clock .WREN(WREN), // 1-bit write port enable .WRADDR(WRADDR), // 9-bit write port address input .RDADDR(RDADDR), // 9-bit read port address input .DI(DI), // 64-bit data input .DIP(DIP), // 8-bit parity data input .WE(WE) // 8-bit write enable input ); // End of RAMB36SDP_inst instantiation
每個(gè)36Kb簡(jiǎn)單雙口塊RAM(Simple dual-port block RAM)都能被配置為512x64(32Kb)大小的RAM和一個(gè)內(nèi)置的漢明糾錯(cuò)編碼(Hamming Error Correction)塊,由于要用到漢明糾錯(cuò)編碼,所以數(shù)據(jù)位寬需要多用到8-bit,這樣數(shù)據(jù)位寬就被擴(kuò)展到72-bit,當(dāng)數(shù)據(jù)位寬為72-bit,深度為512時(shí),RAM的大小剛好為36Kb(512 * 72 / 1024 = 36),其中漢明糾錯(cuò)編碼操作對(duì)用戶是不可見(jiàn)的。每次寫操作都會(huì)產(chǎn)生8-bit的保護(hù)位(原語(yǔ)中的ECCPARITY信號(hào)),這個(gè)8-bit的保護(hù)位在每次讀操作的過(guò)程中可以用來(lái)糾正任何單比特的錯(cuò)誤,或者檢測(cè)(但不能糾正)任何雙比特的錯(cuò)誤。ECCPARITY輸出信號(hào)沒(méi)有可選的輸出寄存器。原語(yǔ)中兩個(gè)狀態(tài)輸出信號(hào)(SBITERR和DBITERR)的組合指示了三種可能的讀操作結(jié)果:無(wú)錯(cuò)誤(No Error),糾正了單比特錯(cuò)誤(Signal Error Corrected)和檢測(cè)到了雙比特錯(cuò)誤(Double Error Detected)。在讀寫操作的ECC(Error Correcting Code)模式均開啟時(shí)(EN_ECC_READ = TRUE 并且 EN_ECC_WRITE = TRUE,EN_ECC_READ和EN_ECC_WRITE為原語(yǔ)的兩個(gè)參數(shù)),讀操作不能再存儲(chǔ)器陣列中直接糾正錯(cuò)誤,而只能把已經(jīng)糾正完畢的數(shù)據(jù)輸出給原語(yǔ)中的DO信號(hào)。ECC配置選項(xiàng)只有RAMB36SDP原語(yǔ)或FIFO36原語(yǔ)才支持。(此部分內(nèi)容參考ug190的107頁(yè)到155頁(yè))
Block RAM的ECC(Error Correcting Code)結(jié)構(gòu)如下圖所示
RAMB36SDP各個(gè)端口的定義如下表所示
端口名 |
方向 |
信號(hào)描述 |
DI[63:0] |
Input |
數(shù)據(jù)輸入總線 |
DIP[7:0] |
Input |
數(shù)據(jù)輸入奇偶校驗(yàn)總線 |
WRADDR[8:0] |
Input |
寫地址總線 |
RDADDR[8:0] |
Input |
讀地址總線 |
WREN |
Input |
寫使能。當(dāng)WREN=1時(shí),數(shù)據(jù)將被寫入存儲(chǔ)器,當(dāng)WREN=0,寫操作不使能。 |
RDEN |
Input |
讀使能。當(dāng)RDEN=1時(shí),數(shù)據(jù)將被從存儲(chǔ)器讀出,當(dāng)RDEN=0,讀操作不使能。 |
SSR |
Input |
同步設(shè)置/復(fù)位(Synchronous Set/Reset),這個(gè)信號(hào)用來(lái)復(fù)位輸出寄存器的值為SRVAL,SRVAL是RAMB36SDP原語(yǔ)的一個(gè)參數(shù)。這個(gè)信號(hào)不會(huì)影響存儲(chǔ)器存儲(chǔ)單元的內(nèi)容。 |
REGCE |
Input |
寄存器使能(Register Enable),端口輸出寄存器使能信號(hào)。 |
WE[7:0] |
Input |
8位的字節(jié)寫使能輸入,由于輸出數(shù)據(jù)總線為64-bit,一共為8個(gè)字節(jié),所以字節(jié)寫使能輸入為8位,詳細(xì)解釋見(jiàn)表后的內(nèi)容。 |
WRCLK |
Input |
寫操作的時(shí)鐘 |
RDCLK |
Input |
讀操作的時(shí)鐘 |
DO[63:0] |
Output |
數(shù)據(jù)輸出總線 |
DOP[7:0] |
Output |
數(shù)據(jù)輸出奇偶校驗(yàn)總線 |
SBITERR |
Output |
單比特錯(cuò)誤(Signal Bit Error)狀態(tài) |
DBITERR |
Output |
雙比特錯(cuò)誤(Double Bit Error)狀態(tài) |
ECCPARITY |
Output |
ECC編碼器輸出數(shù)據(jù)總線 |
字節(jié)寫使能(Byte-Writes):(此部分內(nèi)容參考pg058的第50頁(yè)到51頁(yè))
當(dāng)字節(jié)寫使能功能打開時(shí),WE總線的寬度為輸入數(shù)據(jù)總線DI中包含的字節(jié)個(gè)數(shù)。例如,輸入數(shù)據(jù)總線DI為64位,包含8個(gè)字節(jié),所以WE總線的寬度為8。其中WE總線的最高位對(duì)于輸入數(shù)據(jù)總線DI的最高位的字節(jié),WE總線的最低位對(duì)于輸入數(shù)據(jù)總線DI的最低位的字節(jié),在寫操作過(guò)程中,只有WE總線中為1的位對(duì)應(yīng)的字節(jié)才能被寫入存儲(chǔ)器中,為0的位保持原來(lái)的值不變。
假設(shè)輸入數(shù)據(jù)總線的寬度為24位,它包含3個(gè)字節(jié),所以WE的寬度為3,下圖是一個(gè)字節(jié)寫使能開啟時(shí)往RAM的0地址寫入數(shù)據(jù)的時(shí)序圖(假設(shè)RAM的初始值全部為0)
由上圖可知,當(dāng)WEA(也就是上文的WE)為3’b011時(shí),DINA數(shù)據(jù)24’hFF EE DD的后兩個(gè)字節(jié)會(huì)寫入存儲(chǔ)器的0地址,而存儲(chǔ)器0地址的最高字節(jié)保持00不變,所以第一次寫操作完畢以后存儲(chǔ)器0地址的數(shù)據(jù)為24’h00 EE DD;當(dāng)WEA(也就是上文的WE)為3’b010時(shí),DINA數(shù)據(jù)24’hCC BB AA的中間那個(gè)字節(jié)BB會(huì)寫入存儲(chǔ)器的0地址,而存儲(chǔ)器0地址的最高字節(jié)和最低字節(jié)則保持前一次的00和DD值不變,所以第二次寫操作完畢以后存儲(chǔ)器0地址的數(shù)據(jù)為24’h00 BB DD。后面幾次操作依次類推即可。
3.4 模塊srio_response_gen.v源碼分析
模塊srio_response_gen.v的作用是產(chǎn)生RapidIO響應(yīng)事務(wù)。RapidIO協(xié)議中只有NREAD、DOORBELL、MESSAGE以及NWRITE_R這幾種事務(wù)有響應(yīng)事務(wù)。
srio_response_gen.v源碼的第51行到72行定義了模塊的端口。log_clk和log_rst分別為邏輯層時(shí)鐘與復(fù)位,tresp和treq為兩個(gè)AXI4-Stream通道,tresp是響應(yīng)事務(wù)傳輸通道,treq是請(qǐng)求事務(wù)傳輸通道。源碼如下圖所示
第77行到90行定義了HELLO格式包頭中的FTYPE字段與TTYPE字段的值,這兩個(gè)字段的值與事務(wù)的類型有關(guān),源碼如下圖所示
第99行到100行定義了AXI4-Stream總線上有效數(shù)據(jù)的標(biāo)志,當(dāng)tvalid和tready同時(shí)為高時(shí),tdata上的數(shù)據(jù)為有效數(shù)據(jù)。源代碼如下圖所示
第161行到163行按照HELLO格式的時(shí)序要求,把tkeep信號(hào)賦值為8’hFF,把tuser信號(hào)由src_id和dest_id拼接而成,并在第一個(gè)有效時(shí)鐘發(fā)出去。源代碼如下圖所示
第193行到203行用來(lái)產(chǎn)生HELLO時(shí)序中的tready。源代碼如下圖所示
第205行到220行用來(lái)產(chǎn)生treq通道第一拍的標(biāo)志信號(hào),并把tdata中的數(shù)據(jù)按照HELLO格式的定義把對(duì)應(yīng)的關(guān)鍵字段剝離出來(lái),值得注意的是第218行優(yōu)先級(jí)字段prio為tdata重對(duì)應(yīng)的字段加1,原因是響應(yīng)事務(wù)的優(yōu)先級(jí)為請(qǐng)求事務(wù)的優(yōu)先級(jí)加1,上篇博客也提到過(guò)這一點(diǎn)。這部分源代碼如下圖所示
第224行到第235行用來(lái)生成有響應(yīng)事務(wù)的標(biāo)志,其中RapidiO協(xié)議中只有NREAD、DOORBELL、MESSAGE和NWRITE_R這幾種事務(wù)有對(duì)應(yīng)的響應(yīng)事務(wù)。這部分源代碼如下圖所示
第240行到274行與本地?cái)?shù)據(jù)的存儲(chǔ)有關(guān)。其中第240行到250行的邏輯用來(lái)產(chǎn)生數(shù)據(jù)存取使能位data_store_wen,本文第3.3節(jié)提到過(guò),只有地址字段的第23位到第16位為8’h12時(shí),寫事務(wù)的數(shù)據(jù)才能被存放到本地存儲(chǔ)器,原因就是第243行的判斷語(yǔ)句加上了這個(gè)判斷。第252行到260行的邏輯用來(lái)產(chǎn)生數(shù)據(jù)存儲(chǔ)的寫地址信號(hào)data_store_waddr。第262行到274行的邏輯用來(lái)產(chǎn)生數(shù)據(jù)存儲(chǔ)的讀地址信號(hào)data_store_raddr。源代碼如下圖所示
第276行到302行主要例化了一個(gè)RAMB36SDP用來(lái)存儲(chǔ)寫事務(wù)發(fā)送過(guò)來(lái)的數(shù)據(jù)。其中第276行用來(lái)產(chǎn)生數(shù)據(jù)存儲(chǔ)的讀使能標(biāo)志。源代碼如下圖所示
第307行到第335行是把請(qǐng)求事務(wù)的包頭(Header)信息存儲(chǔ)在RAM中。其中第307行到308行把請(qǐng)求事務(wù)中HELLO格式定義的各個(gè)字段進(jìn)行拼接作為RAM的輸入,第325行到第335行用來(lái)產(chǎn)生RAM的讀地址與寫地址。
第337行例化了第二個(gè)Block RAM,它用來(lái)存儲(chǔ)請(qǐng)求事務(wù)的HELLO格式信息。
第363行到第372行把從RAM中讀出來(lái)的數(shù)據(jù)對(duì)應(yīng)的字段剝離出來(lái)從而得到響應(yīng)事務(wù)HELLO格式對(duì)應(yīng)的字段。
第378行到第388行用來(lái)產(chǎn)生有效時(shí)鐘的總數(shù)number_of_data_beats以及有效時(shí)鐘計(jì)數(shù)器current_beat_cnt。這段邏輯與srio_request_gen.v中對(duì)應(yīng)的邏輯完全一致。源代碼如下圖所示
第390行到400行用來(lái)產(chǎn)生tlast信號(hào),發(fā)送最后一個(gè)數(shù)據(jù)時(shí),tlast信號(hào)拉高。
第402行和第403行用來(lái)產(chǎn)生響應(yīng)事務(wù)的包頭(Header),第404行到414行用來(lái)產(chǎn)生響應(yīng)事務(wù)的數(shù)據(jù),其中響應(yīng)事務(wù)的第一個(gè)有效時(shí)鐘用來(lái)發(fā)送包頭(Header),后面的有效時(shí)鐘用來(lái)發(fā)送數(shù)據(jù),這段邏輯也與srio_request_gen.v中對(duì)應(yīng)的邏輯類似。源代碼如下圖所示
第459行到第469行用來(lái)產(chǎn)生AXI4-Stream中的tvalid信號(hào),源代碼如下
至此,整個(gè)響應(yīng)事務(wù)的源代碼分析完畢,其余未分析到的代碼請(qǐng)自行分析。
3.5 模塊srio_quick_start.v源碼分析
模塊srio_quick_start.v的作用是產(chǎn)生維護(hù)事務(wù)(Maintenance Transaction)訪問(wèn)本地設(shè)備和遠(yuǎn)程設(shè)備的配置空間。維護(hù)事務(wù)采用的接口協(xié)議為AXI4-Lite,它是一種輕量級(jí)的AXI4協(xié)議,有地址總線與數(shù)據(jù)總線,常用來(lái)實(shí)現(xiàn)單個(gè)寄存器的讀寫。在分析srio_quick_start.v源碼之前首先分析一下maintenance_list.vh頭文件。
分析maintenance_list.vh頭文件
maintenance_list.vh頭文件主要定義了維護(hù)事務(wù)相關(guān)的字段,其中第1列為2-bit的保留位,第2列為1-bit的遠(yuǎn)程/本地控制位,第3列為24-bit的地址,第4列為讀/寫控制位,第5列為32-bit的數(shù)據(jù),第6列為4-bit的數(shù)據(jù)掩碼(DATA MASK),部分源代碼如下圖所示
分析srio_quick_start.v源文件
srio_quick_start.v源文件的第68行到第101行是接口定義。log_clk和log_rst分別為邏輯層的時(shí)鐘和復(fù)位。以maintr_*開頭的信號(hào)為AXI4-Lite通道的信號(hào),以u(píng)ser_*開頭的信號(hào)是用戶自定義的維護(hù)事務(wù)的相關(guān)字段,go變量用來(lái)在用戶定義和maintenance_list.vh頭文件定義的字段中進(jìn)行選擇
第105行到122行對(duì)maintenance_list.vh頭文件中的參數(shù)進(jìn)行了賦值,并引入了頭文件,源代碼如下圖所示。
第192行到229行主要用來(lái)構(gòu)建請(qǐng)求包,其本質(zhì)就是產(chǎn)生AXI4-Lite的協(xié)議把數(shù)據(jù)發(fā)出去。部分源代碼如下圖所示
第233行到386行例化了一個(gè)RAMB36SDP原語(yǔ),并用maintenance_list.vh頭文件中定義的數(shù)據(jù)進(jìn)行初始化。部分源代碼如下圖所示
第397行到416行主要負(fù)責(zé)響應(yīng)側(cè)的檢測(cè),通過(guò)maint_autocheck_error和maint_done指示檢測(cè)狀態(tài)。源代碼如下圖所示
至此,維護(hù)事務(wù)的代碼分析完畢,它的代碼邏輯相對(duì)來(lái)說(shuō)比較簡(jiǎn)單。
另外,例子工程中還有兩個(gè)模塊srio_report.v和srio_statistics.v,它們只在仿真有用,在硬件上實(shí)現(xiàn)時(shí)最好刪掉。這里不再作過(guò)多分析。只要理解了srio_request_gen.v與srio_response_gen.v,用RapidIO完成相關(guān)應(yīng)用就足夠了。
五、仿真
工程源碼分析完畢以后,接下來(lái)就可以開始仿真了。例子工程中的代碼一行都不要改,直接左鍵單擊Run Simulation,在彈出的菜單中點(diǎn)擊Run Behavioral Simulation,如下圖所示
接著會(huì)出現(xiàn)下面的滾動(dòng)框,在這個(gè)界面需要等待一會(huì),如下圖所示
上面的滾動(dòng)框運(yùn)行完畢以后就出現(xiàn)了波形界面,如下圖所示
然后再點(diǎn)擊下圖中圈出的小圖標(biāo)把波形復(fù)位一下,如下圖所示
復(fù)位波形以后在Tcl Console中輸入指令:log_wave –r /* 。輸入完畢以后按回車。這條指令的作用是記錄所有中間變量的波形,這樣后面要觀察任何變量的波形只需要把它拖到波形界面中它的波形就會(huì)自動(dòng)顯示出來(lái)而不需要重新仿真,大大節(jié)約了時(shí)間。如下圖所示
最后設(shè)置一個(gè)比較大的時(shí)間,我設(shè)置為10ms,然后點(diǎn)擊它左邊的按鈕開始仿真,大約20分鐘以后仿真會(huì)自動(dòng)結(jié)束,如下圖所示
仿真的過(guò)程中,在相應(yīng)的時(shí)間點(diǎn)上,Tcl Console中會(huì)打印出包的收發(fā)情況
最后仿真結(jié)束以后,重新回到波形界面可以看到波形都正常產(chǎn)生了。這里最重要的兩個(gè)信號(hào)就是link_initialized與port_initialized,當(dāng)他們?yōu)楦弑硎菊麄€(gè)鏈路初始化完畢。至此,整個(gè)仿真過(guò)程全部結(jié)束,下篇文章會(huì)詳細(xì)介紹每種事務(wù)的時(shí)序圖以及需要注意的一些細(xì)節(jié)。
六、總結(jié)
本節(jié)主要分析了一下請(qǐng)求事務(wù)與響應(yīng)事務(wù)的Verilog源碼,事實(shí)上,它們的源碼就是按照pg007_srio_gen2.pdf把HELLO格式與HELLO時(shí)序描述出來(lái)而已。當(dāng)然官方的這套源碼為了盡可能保證測(cè)試到核的所有功能,寫的比較混亂,但在實(shí)際項(xiàng)目中可以充分借鑒它的設(shè)計(jì)思想,然后根據(jù)你自己的需求對(duì)不需要的地方進(jìn)行修改來(lái)達(dá)到你的目標(biāo)。除此以外,HELLO格式的時(shí)序其通過(guò)一個(gè)狀態(tài)機(jī)來(lái)實(shí)現(xiàn)可能更加簡(jiǎn)潔易懂。總而言之,這套代碼具有很大的參考價(jià)值,但是要想把這個(gè)核玩透還是得自己多在項(xiàng)目中理解。
下篇文章將會(huì)教大家如何在Vivado抓出每種事務(wù)的時(shí)序來(lái)對(duì)各種RapidIO的交互過(guò)程有一個(gè)更加清晰的理解。
?
審核編輯 :李倩-
FPGA
+關(guān)注
關(guān)注
1630文章
21796瀏覽量
605426 -
模塊
+關(guān)注
關(guān)注
7文章
2731瀏覽量
47679 -
Xilinx
+關(guān)注
關(guān)注
71文章
2171瀏覽量
121995 -
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110296 -
源碼
+關(guān)注
關(guān)注
8文章
652瀏覽量
29412
原文標(biāo)題:【高速接口-RapidIO】5、Xilinx RapidIO核例子工程源碼分析
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論