一、軟件平臺與硬件平臺
軟件平臺:
操作系統:Windows 8.1 64-bit
開發套件:Vivado2015.4.2
硬件平臺:
評估板:ZYNQ-7 ZC706 Evaluation Board
二、打開例子工程
1、新建工程,并在IP Catalog中找到Serial RapidIO Gen2
2、雙擊Serial RapidIO Gen2進入核的配置界面,所用參數全部保持默認,然后直接點擊OK
3、在彈出的的對話框中直接點擊Generate
4、在彈出的對話框中點擊OK
5、等待srio_gen2_0核綜合完畢,可能會花幾分鐘的時間
6、IP核綜合完畢以后,單擊srio_gen2_0,并點擊鼠標右鍵,在彈出的菜單欄中單擊Open IP Example Design…
7、在彈出的的對話框中選擇例子工程的存放目錄(這個目錄可任意選擇),然后單擊OK
8、等一段時間以后例子工程就會自動打開
三、例子工程詳解
3.1 工程概述
RapidIO核的例子工程的仿真頂層代碼里面例化了兩個實體,一個叫做srio_example_top_primary,另外一個叫做srio_example_top_mirror,如下圖所示
其中每個例化實體都能被配置為發送支持的包類型,檢測接收包失配以及上報鏈路的仿真細節。下表列出了例子工程中各個主要模塊的功能簡介
文件名 |
功能 |
srio_example_top.v |
例子工程的頂層模塊 |
srio_request_gen.v |
生成請求事務的模塊 |
instruction_list.vh |
這是一個Verilog頭文件,里面定義了120個事務,它被包含在srio_request_gen.v模塊中,srio_request_gen.v模塊會把里面的所有事務依次發出去 |
srio_response_gen.v |
這個模塊用來產生有響應事務的響應包 |
srio_condensed_gen.v |
當IP核的端口配置為Condensed I/O模式時,這個文件才會出現在例子工程中。它用來產生Condensed I/O模式的請求事務。 |
srio_quick_start.v |
這個模塊與IP核的維護端口相連,用來發起維護事務。 |
maintenance_list.vh |
這是一個Verilog頭文件,里面定義了一些維護事務,它被包含在srio_quick_start.v模塊中,srio_quick_start.v模塊會把里面的所有維護事務依次發出去用來配置相關寄存器 |
srio_report.v |
在仿真時,這個模塊用來產生包接收和發送的時間戳,在硬件上運行的時候這個模塊可以刪除 |
srio_statistics.v |
|
srio_sim.v |
srio_sim.v是仿真頂層文件,它例化了兩個核,分別是primary和mirror,并把它們連接到一起用于仿真。它也包含了上報測試是否成功的機制與超時(timeout)功能。 |
3.2 工程結構
例子工程的頂層模塊例化了所有核的所有組件和在硬件上執行所需要的例子代碼,整個工程的結構如下圖所示。
整個結構包括時鐘模塊,復位模塊,配置結構以及產生RapidIO事務的激勵模塊。
srio_quick_start模塊在頂層srio_example_top.v中例化,它與IP核的維護端口相連用來產成維護事務,維護事務在maintenance_list.vh中進行定義,用戶可以根據需要編輯maintenance_list.vh文件來添加,修改和移除維護事務。
srio_request_gen.v模塊也在頂層srio_example_top.v中例化,它用來產生I/O事務與消息事務。這個模塊也存儲了期望的響應并把接收的響應與期望值進行比較。
srio_response_gen.v模塊也在頂層srio_example_top.v中例化,它用來為接收到的請求事務生成對應的響應事務。
通過上圖可以看出,產生I/O事務一共有兩種方式:第一種是通過例子工程中自帶的srio_request_gen.v產生I/O事務;第二種是通過頂層模塊中Initiator和Target的resquest/response接口自己編寫代碼產生I/O事務。同理,產生維護事務也有兩種方式:第一種是通過例子工程中自帶的srio_quick_start.v模塊產生維護事務;第二種是通過頂層模塊中的維護接口自己編寫代碼產生維護事務。I/O事務的端口類型是AXI4-Stream類型,維護事務的端口類型是AXI4-Lite類型。
默認情況下,由于例子工程的頂層srio_example_top.v模塊中,VALIDATION_FEATURES與QUICK_STARTUP兩個參數均被設置為1,如下圖所示
所以,例子工程是采用自帶的srio_request_gen.v和srio_quick_start.v分別產生I/O事務與維護事務,另外,推薦注釋掉外部接口以節省管腳和改善時序。
如果要使用外部接口產生I/O事務,那么需要設置參數VALIDATION_FEATURES=0,并且取消頂層模塊srio_example_top.v中外部接口(axis_ireq_*,axis_tresp_*, axis_iresp_*, axis_treq_*, axis_iotx_*, axis_iorx_*)的注釋。如果要使用外部接口產生維護事務,那些需要設置參數QUICK_STARTUP=0,并且取消頂層模塊srio_example_top.v中外部接口(axis_maintr_*)的注釋。使用外部接口的工程結構如下圖所示
3.3 工程分析
I/O事務與維護事務
默認情況下,例子工程會使用srio_request_gen.v模塊和srio_quick_start.v模塊來產生I/O事務與維護事務。其中instruction_list.vh頭文件定義了待發送的I/O事務,maintenance_list.vh頭文件定義了待發送的維護事務。
當核被復位以后,maintenance_list.vh中的維護事務可以對核進行配置,維護事務可以在maintenance_list.vh進行添加、修改或移除。當沒有處理器時,srio_quick_start.v模塊可以用來管理公共的維護事務。當核復位以后,這是一種比較好的配置核的方法。
srio_request_gen.v模塊和srio_response_gen.v模塊可以用來產生I/O事務,srio_request_gen.v模塊可以用來產生定義在instruction_list.vh中的I/O請求事務。instruction_list.vh中的I/O事務可以被添加、修改或移除,I/O事務的順序是隨機的,但是每次重新仿真時都是按照相同的順序產生的。而且,只有IP核端口支持的事務才能被產生。srio_request_gen.v模塊還可以追蹤期望的響應并且比較接收的響應與期望值,這在仿真的時候可以很方便的確定事務的收發情況。
srio_response_gen.v模塊用來產生接收到的請求所對應的目標響應I/O事務。如果寫事務目標地址的第23位到16位為8’h12(address[23:16]=8’h12),那么數據負載會被存儲在本地存儲器。不需要響應的寫事務會被丟棄,并且srio_response_gen.v模塊不會響應SWRITE事務。如果讀事務目標地址的第23位到16位為8’h12(address[23:16]=8’h12),那么數據將會從實際地址讀出。對于那些地址不滿足第23位到16位為8’h12(address[23:16]=8’h12)的事務,srio_response_gen.v模塊將以地址遞增的方式寫入I/O事務攜帶的數據。響應會根據接收到的請求的順序依次產生,所以不會有無序的事務產生。在所有的情況中,響應事務的優先級等于請求事務的優先級加1。
注意:每個srio_request_gen.v模塊會消耗一個塊RAM(Block RAM),每個srio_response_gen.v模塊會消耗兩個塊RAM(Block RAM)。
配置結構
配置空間分布在RapidIO核的所有塊中,配置結構的參考設計在例子設計的cfg_fabric模塊中,用來管理每個塊配置空間的訪問情況。塊(Block)的配置模塊在配置總線(AXI4-Lite)上是作為從機存在的,cfg_fabric模塊是作為主機存在的。維護事務的讀寫操作是從本地或者遠程被發起,它是通過邏輯層的配置主端口接入配置模塊,配置模塊會把讀寫事務送入對應的塊中,但如果地址不在各自配置寄存器的有效范圍內,配置模塊不會移交任何讀寫事務。往非法的空間寫事務會被丟棄,讀非法的空間將返回0。
時鐘模塊
例子設計的時鐘模塊與IP核的時鐘模塊是相同的。srio_clk模塊有1個MMCM_ADV,1個IBUFDS和3個或4個BUFGs組成,在2x或4x模式,其中一個BUFGs將被轉化為BUFGMUX。srio_clk模塊會根據配置的不同產生合適的參考頻率與用戶時鐘。
復位模塊
srio_rst模塊會把每個時鐘域里面的異步復位信號轉化為一個脈沖擴展的同步復位信號。當被用戶設計調用的時候,srio_rst模塊會用一個狀態機強制對核重新初始化。
四、工程源碼分析
3.1 頂層模塊srio_example_top.v源碼分析
頂層模塊srio_example_top.v源碼的端口定義如下
頂層模塊包含5個參數:SIM_VERBOSE,VALIDATION_FEATURES,QUICK_STARTUP,STATISTICS_GATHERING和C_LINK_WIDTH。
SIM_VERBOSE設為1時,可以利用srio_report.v模塊生成不可綜合的報告。為0時,此功能被屏蔽。
VALIDATION_FEATURES設為1時,選擇例子工程中的srio_request_gen.v和srio_response_gen.v產生相應的請求事務與響應事務對IP核的功能進行測試。為0時,選擇外部的用戶接口由用戶自己編寫請求事務與響應事務的代碼對IP進行測試。
QUICK_STARTUP設為1時,選擇例子工程中的srio_quick_start.v產生相應的維護事務對IP核的配置空間進行訪問。為0時,選擇外部的維護接口由用戶自己編寫維護事務的代碼對IP核的配置空間進行訪問。
STATISTICS_GATHERING設為1時,可以利用srio_statistics.v模塊搜集IP的性能細節,這個模塊是可綜合的,可以通過Chipscope或ILA進行訪問。為0時,此功能被屏蔽。
頂層模塊的差分時鐘sys_clkp和sys_clkn就是IP核配置界面第一頁的參考時鐘,由于例子工程中采用的全部是默認參數,所以這里這個時鐘為125MHz,這個時鐘可以由FPGA外部的有源晶振或鎖相環芯片輸出。
sys_rst為IP核的復位信號,高電平有效。
差分信號srio_rxn0和srio_rxp0為串行接收數據信號,srio_txn0和srio_txp0為串行發送數據信號。
sim_train_en信號是一個用來減少仿真時間的控制信號,仿真時把這個信號置1可以加快仿真速度,但是代碼在硬件上運行時這個信號必須賦值為0。
led0是led指示信號,可以把port_initialized和link_initialized兩個信號接到led0中,這樣在硬件上執行時可以方便觀察鏈路狀態。
頂層模塊srio_example_top.v中的第466行到第590行例化了RapidIO核,部分源碼如下圖所示
第612行到631行是例化了srio_report.v模塊用來收集ireq接口的統計信息。除此以外,還例化了3個srio_report.v模塊用來收集iresp,treq,tresp接口的統計信息。下圖是收集ireq統計信息的源代碼。源碼如下圖所示
第637行到684行srio_request_gen.v模塊用來生成請求事務。這個模塊有7個參數,分別為SEND_SWRITE,SEND_NWRITER,SEND_NWRITE,SEND_NREAD,SEND_FTYPE9,SEND_DB和SEND_MSG。當他們設置為1時,srio_request_gen.v模塊將會把instruction_list.vh模塊中對應的事務發送給SRIO IP核。部分源碼如下圖所示
第779行到804行例化了srio_response_gen.v模塊,這個模塊用來產生響應事務。部分源碼如下圖所示
第890行到937行例化了srio_quick_start.v模塊,這個模塊產生維護事務來訪問配置空間。部分源碼如下圖所示
第944行到988行例化了srio_statistics.v模塊,這個模塊用來收集統計信息,它是一個可綜合的模塊。部分源碼如下圖所示
3.2 模塊srio_request_gen.v源碼分析
模塊srio_request_gen.v的作用是產生RapidIO請求事務,上篇文章《Xilinx RapidIO核詳解》(鏈接:https://www.cnblogs.com/liujinggang/p/10072115.html)已經提到過,RapidIO核為了簡化包的構建過程,設計了一種精簡的包格式——HELLO格式來完成包的構建,然后按照HELLO格式的時序把數據發送給RapidIO核,RapidIO核會把HELLO格式的包轉化為標準的RapidIO串行物理層的包。這樣,用戶在設計請求事務的Verilog代碼時只需要對HELLO格式的包與時序有所了解,而不需要過多的關注RapidIO的協議與RapidIO包格式。這里重新復習一下HELLO格式的包結構與HELLO格式的時序。
HELLO格式的包結構如下圖所示:
HELLO格式的時序圖如下圖所示:
事實上,整個srio_request_gen.v源代碼的核心就是先構建HELLO格式的包,然后把包頭(Header)和數據按照HELLO格式的時序傳給RapidIO核就可以了。下面詳細分析一下。
分析instruction_list.vh頭文件
在分析srio_request_gen.v源代碼之前先來分析一下instruction_list.vh頭文件。因為srio_request_gen.v文件中包含了instruction_list.vh頭文件,instruction_list.vh頭文件中定義了srio_request_gen.v將要發送的所有事務。
instruction_list.vh頭文件的第1行到第9行定義了事務的個數以及所有事務的總個數,每種事務的個數由一個控制變量進行選擇,源碼如下:
第11行到50行是37個SWRITE事務(流寫事務),其中第1列的12位數據是由8-bit的保留位(SWRITE事務沒有srcTID字段),1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(SWRITE事務沒有TTYPE字段),第4列的36-bit數據是由最高2-bit的保留位和34-bit的address字段組成,第5列是8-bit保留字段(SWRITE事務沒有size字段),不管這個字段的值為多少,目標設備都會把這個值當做0來處理。源代碼如下圖所示
第52行到72行是19個NWRITE_R事務(帶響應的寫事務),其中第1列的12位數據是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數據是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個字段的值為實際的數據量減1。比如size=0,表示實際傳輸的數據量為1。源代碼如下圖所示
第74行到94行是19個NWRITE事務(寫事務),其中第1列的12位數據是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數據是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個字段的值為實際的數據量減1。比如size=0,表示實際傳輸的數據量為1。源代碼如下圖所示
第96行到123行是26個NREAD事務(讀事務),其中第1列的12位數據是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit數據是由最高2-bit的保留位和34-bit的address字段組成,第5列是size字段,這個字段的值為實際的數據量減1。比如size=0,表示實際傳輸的數據量為1。源代碼如下圖所示
第125行到128行是兩個DOORBELL事務(門鈴事務),其中第1列的12位數據是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(DOORBELL事務沒有TTYPE字段),第4列的36-bit數據是由最高4-bit的保留位,8-bit的信息高8位,8-bit的信息低8位以及最后的16-bit保留位組成。第5列是8-bit保留字段(DOORBELL事務沒有size字段)。源代碼如下圖所示
第130行到148行是17個MESSAGE事務(消息事務),其中第1列的12位數據是由4-bit的msglen,4-bit的msgseg,1-bit的保留位,2-bit的prio和1-bit的CRF組成,第2列是FTYPE字段,第3列是保留字段(MESSAGE事務沒有TTYPE字段),第4列的36-bit數據是由最高26-bit的保留位,6-bit的mailbox字段,2-bit的保留位以及2-bit的ltr組成。第5列是8-bit的size字段。源代碼如下圖所示
第150行到152行是1個Data Streaming事務,這是Xilinx定義的第9類事務,由于這種事務用的不多,我自己也不太了解,所以這里就不進行分析了。源代碼如下圖所示
分析srio_request_gen.v源碼
在分析完畢instruction_list.vh頭文件以后接下來開始著手分析srio_request_gen.v源碼。分析過程中始終要記住的一點是:srio_request_gen.v的核心功能就是組裝HELLO包頭并把包頭和數據按照HELLO格式的時序發送出去。
srio_request_gen.v源碼的第50行到92行是參數與接口的定義。它包含7個參數,分別為SEND_SWRITE、SEND_NWRITER、SEND_NWRITE、SEND_NREAD、SEND_DB、SEND_FTYPE9和SEND_MSG,它們的默認值被設置為0,但是在頂層模塊中例化的時候,它們的值分別被設置為1、1、1、1、0、1、1。如下圖所示
根據上面分析instruction_list.vh頭文件可知,如果上面的7個參數為1的話,各個事務的個數應該由instruction_list.vh頭文件中NUM_SWRITES、NUM_NWRITERS、NUM_NWRITES、NUM_NREADS、NUM_DBS、NUM_MSGS和NUM_FTYPE9決定。
接下來就是端口的定義,其中log_clk與log_rst均由IP輸出,log_clk的頻率與鏈路線速率和鏈路寬度有關,具體的對應關系在上篇文章中能找到。接下來就是設備ID,目的ID以及源ID的定義。然后定義了ireq與iresp,它們都采用了AXI4-Stream協議。link_initialized信號由IP核輸出,當它為高時表明鏈路成功初始化。以user_*開頭的幾個變量可以方便用戶自定義HELLO格式包頭中的各個字段。
第96到110行定義了HELLO格式包頭中的FTYPE字段與TTYPE字段的值,這兩個字段的值與事務的類型有關,源碼如下圖所示
第120行定義了一個memory類型變量,綜合的時候ram的類型為分布式ram,121行導入了instruction_list.vh頭文件,126行定義的變量可以看做AXI4-Stream總線上數據有效的標志位,當這個信號為高時,AXI4-Stream總線上tdata上的數據為有效數據。源代碼如下圖所示
第178行到205行用來初始化事務列表,instruction[ii]存放的是instruction_list.vh頭文件中定義的各個事務的相關字段值,源代碼如下圖所示
第208到第219行是一些簡單的賦值操作。其中第208行的val_ireq_tkeep和val_ireq_tuser是根據HELLO格式的時序要求賦值的,HELLO格式的時序要求tkeep為8’hFF,tuser在第一個有效的時鐘(log_clk)周期內由src_id與dest_id拼接而成。第213行和第217行的go變量用來選擇HELLO格式包頭各個字段由用戶定義還是由instruction_list.vh定義。第219行的header_beat變量就是HELLO格式的包頭,在第一個有效時鐘(log_clk)周期,tdata上的數據必須為header_beat。源代碼如下圖所示
第266行到288行主要用來產生有效時鐘計數器current_beat_cnt與有效時鐘計數總數number_of_data_beats。當AXI4_Stream總線的tvalid和tready信號同時為高時,時鐘為有效時鐘,current_beat_cnt加1,當檢測到tlast信號為高時表明最后一個數據已發送完畢,所以把current_beat_cnt清0。由于tdata的寬度為64-bit,也就是8個字節,所以有效時鐘計數總數number_of_data_beats為current_size右移3位。源代碼如下圖所示
第294行到306行用來產生AXI4_Stream總線中tlast信號,tlast為高時表明發送的是最后一個數據,所以tlast信號相當于一幀數據的邊界。
第307行到328行用來產生AXI4_Stream總線中的tdata信號,當有效時鐘計數器current_beat_cnt為0時,tdata為包頭header_beat,包頭header_beat后面是待發送的數據data_beat,例子工程為了簡單起見,發送的數據是累加數,每個累加數為8-bit,然后把每個累加數拼接8次作為待發送的數據,也就是說,待發送的數據為64’h0000000000000000,64’h0101010101010101,64’h0202020202020202,……..,后面以此類推。
第330行到345行主要用來產生AXI4_Stream總線中的tvalid信號,同時也產生了一些其他的標志信號。至此,整個AXI4_Stream總線中的所有信號的邏輯都編寫完畢,并且整個邏輯都是完全符合HELLO格式的時序。代碼的核心部分全部分析完畢。
第351行到第371行與數據的存儲相關。每當current_beat_cnt的值為0時,request_address變量加1, request_address也被賦給了tid,也就是說request_address也是事務ID值,同時request_address也是instruction的索引值。源代碼如下圖所示
第382行到第406行例化了一個RAMB36SDP原語,RAMB36SDP是一個大小為36Kb的簡單雙口Block RAM(SDP=Simple Dual Port)。它的作用是把請求事務的tid,current_ftype和current_size寫入RAM中存起來,對于有響應的事務,RapidIO會收到一個響應事務,收到響應事務事務以后可以把存放在RAMB36SDP中的數據讀出來與響應事務中對應的字段進行對比從而對整個事務的交互過程的正確性進行一個初步判斷。關于RAMB36SDP原語的詳細解釋請閱讀下一小節。源代碼如下圖所示
第458行到482行就是把存儲在RAM中請求事務的tid,current_ftype和current_size與響應事務對應的字段進行對比,在仿真時給出對應的提示信息。
至此,整個產生請求事務的代碼全部分析完畢,其他未分析到的代碼大家自己嘗試分析。
3.3 RAMB36SDP原語分析
RAMB36SDP是一個大小為36Kb的簡單雙口Block RAM(SDP=Simple Dual-Port),它其實是Virtex-5系列FPGA的一個原語,Vivado里面并沒有RAMB36SDP的語法模板,ISE中才有它的語法模板,如下圖所示
RAMB36SDP原語的完整代碼如下所示
// 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
每個36Kb簡單雙口塊RAM(Simple dual-port block RAM)都能被配置為512x64(32Kb)大小的RAM和一個內置的漢明糾錯編碼(Hamming Error Correction)塊,由于要用到漢明糾錯編碼,所以數據位寬需要多用到8-bit,這樣數據位寬就被擴展到72-bit,當數據位寬為72-bit,深度為512時,RAM的大小剛好為36Kb(512 * 72 / 1024 = 36),其中漢明糾錯編碼操作對用戶是不可見的。每次寫操作都會產生8-bit的保護位(原語中的ECCPARITY信號),這個8-bit的保護位在每次讀操作的過程中可以用來糾正任何單比特的錯誤,或者檢測(但不能糾正)任何雙比特的錯誤。ECCPARITY輸出信號沒有可選的輸出寄存器。原語中兩個狀態輸出信號(SBITERR和DBITERR)的組合指示了三種可能的讀操作結果:無錯誤(No Error),糾正了單比特錯誤(Signal Error Corrected)和檢測到了雙比特錯誤(Double Error Detected)。在讀寫操作的ECC(Error Correcting Code)模式均開啟時(EN_ECC_READ = TRUE 并且 EN_ECC_WRITE = TRUE,EN_ECC_READ和EN_ECC_WRITE為原語的兩個參數),讀操作不能再存儲器陣列中直接糾正錯誤,而只能把已經糾正完畢的數據輸出給原語中的DO信號。ECC配置選項只有RAMB36SDP原語或FIFO36原語才支持。(此部分內容參考ug190的107頁到155頁)
Block RAM的ECC(Error Correcting Code)結構如下圖所示
RAMB36SDP各個端口的定義如下表所示
端口名 |
方向 |
信號描述 |
DI[63:0] |
Input |
數據輸入總線 |
DIP[7:0] |
Input |
數據輸入奇偶校驗總線 |
WRADDR[8:0] |
Input |
寫地址總線 |
RDADDR[8:0] |
Input |
讀地址總線 |
WREN |
Input |
寫使能。當WREN=1時,數據將被寫入存儲器,當WREN=0,寫操作不使能。 |
RDEN |
Input |
讀使能。當RDEN=1時,數據將被從存儲器讀出,當RDEN=0,讀操作不使能。 |
SSR |
Input |
同步設置/復位(Synchronous Set/Reset),這個信號用來復位輸出寄存器的值為SRVAL,SRVAL是RAMB36SDP原語的一個參數。這個信號不會影響存儲器存儲單元的內容。 |
REGCE |
Input |
寄存器使能(Register Enable),端口輸出寄存器使能信號。 |
WE[7:0] |
Input |
8位的字節寫使能輸入,由于輸出數據總線為64-bit,一共為8個字節,所以字節寫使能輸入為8位,詳細解釋見表后的內容。 |
WRCLK |
Input |
寫操作的時鐘 |
RDCLK |
Input |
讀操作的時鐘 |
DO[63:0] |
Output |
數據輸出總線 |
DOP[7:0] |
Output |
數據輸出奇偶校驗總線 |
SBITERR |
Output |
單比特錯誤(Signal Bit Error)狀態 |
DBITERR |
Output |
雙比特錯誤(Double Bit Error)狀態 |
ECCPARITY |
Output |
ECC編碼器輸出數據總線 |
字節寫使能(Byte-Writes):(此部分內容參考pg058的第50頁到51頁)
當字節寫使能功能打開時,WE總線的寬度為輸入數據總線DI中包含的字節個數。例如,輸入數據總線DI為64位,包含8個字節,所以WE總線的寬度為8。其中WE總線的最高位對于輸入數據總線DI的最高位的字節,WE總線的最低位對于輸入數據總線DI的最低位的字節,在寫操作過程中,只有WE總線中為1的位對應的字節才能被寫入存儲器中,為0的位保持原來的值不變。
假設輸入數據總線的寬度為24位,它包含3個字節,所以WE的寬度為3,下圖是一個字節寫使能開啟時往RAM的0地址寫入數據的時序圖(假設RAM的初始值全部為0)
由上圖可知,當WEA(也就是上文的WE)為3’b011時,DINA數據24’hFF EE DD的后兩個字節會寫入存儲器的0地址,而存儲器0地址的最高字節保持00不變,所以第一次寫操作完畢以后存儲器0地址的數據為24’h00 EE DD;當WEA(也就是上文的WE)為3’b010時,DINA數據24’hCC BB AA的中間那個字節BB會寫入存儲器的0地址,而存儲器0地址的最高字節和最低字節則保持前一次的00和DD值不變,所以第二次寫操作完畢以后存儲器0地址的數據為24’h00 BB DD。后面幾次操作依次類推即可。
3.4 模塊srio_response_gen.v源碼分析
模塊srio_response_gen.v的作用是產生RapidIO響應事務。RapidIO協議中只有NREAD、DOORBELL、MESSAGE以及NWRITE_R這幾種事務有響應事務。
srio_response_gen.v源碼的第51行到72行定義了模塊的端口。log_clk和log_rst分別為邏輯層時鐘與復位,tresp和treq為兩個AXI4-Stream通道,tresp是響應事務傳輸通道,treq是請求事務傳輸通道。源碼如下圖所示
第77行到90行定義了HELLO格式包頭中的FTYPE字段與TTYPE字段的值,這兩個字段的值與事務的類型有關,源碼如下圖所示
第99行到100行定義了AXI4-Stream總線上有效數據的標志,當tvalid和tready同時為高時,tdata上的數據為有效數據。源代碼如下圖所示
第161行到163行按照HELLO格式的時序要求,把tkeep信號賦值為8’hFF,把tuser信號由src_id和dest_id拼接而成,并在第一個有效時鐘發出去。源代碼如下圖所示
第193行到203行用來產生HELLO時序中的tready。源代碼如下圖所示
第205行到220行用來產生treq通道第一拍的標志信號,并把tdata中的數據按照HELLO格式的定義把對應的關鍵字段剝離出來,值得注意的是第218行優先級字段prio為tdata重對應的字段加1,原因是響應事務的優先級為請求事務的優先級加1,上篇博客也提到過這一點。這部分源代碼如下圖所示
第224行到第235行用來生成有響應事務的標志,其中RapidiO協議中只有NREAD、DOORBELL、MESSAGE和NWRITE_R這幾種事務有對應的響應事務。這部分源代碼如下圖所示
第240行到274行與本地數據的存儲有關。其中第240行到250行的邏輯用來產生數據存取使能位data_store_wen,本文第3.3節提到過,只有地址字段的第23位到第16位為8’h12時,寫事務的數據才能被存放到本地存儲器,原因就是第243行的判斷語句加上了這個判斷。第252行到260行的邏輯用來產生數據存儲的寫地址信號data_store_waddr。第262行到274行的邏輯用來產生數據存儲的讀地址信號data_store_raddr。源代碼如下圖所示
第276行到302行主要例化了一個RAMB36SDP用來存儲寫事務發送過來的數據。其中第276行用來產生數據存儲的讀使能標志。源代碼如下圖所示
第307行到第335行是把請求事務的包頭(Header)信息存儲在RAM中。其中第307行到308行把請求事務中HELLO格式定義的各個字段進行拼接作為RAM的輸入,第325行到第335行用來產生RAM的讀地址與寫地址。
第337行例化了第二個Block RAM,它用來存儲請求事務的HELLO格式信息。
第363行到第372行把從RAM中讀出來的數據對應的字段剝離出來從而得到響應事務HELLO格式對應的字段。
第378行到第388行用來產生有效時鐘的總數number_of_data_beats以及有效時鐘計數器current_beat_cnt。這段邏輯與srio_request_gen.v中對應的邏輯完全一致。源代碼如下圖所示
第390行到400行用來產生tlast信號,發送最后一個數據時,tlast信號拉高。
第402行和第403行用來產生響應事務的包頭(Header),第404行到414行用來產生響應事務的數據,其中響應事務的第一個有效時鐘用來發送包頭(Header),后面的有效時鐘用來發送數據,這段邏輯也與srio_request_gen.v中對應的邏輯類似。源代碼如下圖所示
第459行到第469行用來產生AXI4-Stream中的tvalid信號,源代碼如下
至此,整個響應事務的源代碼分析完畢,其余未分析到的代碼請自行分析。
3.5 模塊srio_quick_start.v源碼分析
模塊srio_quick_start.v的作用是產生維護事務(Maintenance Transaction)訪問本地設備和遠程設備的配置空間。維護事務采用的接口協議為AXI4-Lite,它是一種輕量級的AXI4協議,有地址總線與數據總線,常用來實現單個寄存器的讀寫。在分析srio_quick_start.v源碼之前首先分析一下maintenance_list.vh頭文件。
分析maintenance_list.vh頭文件
maintenance_list.vh頭文件主要定義了維護事務相關的字段,其中第1列為2-bit的保留位,第2列為1-bit的遠程/本地控制位,第3列為24-bit的地址,第4列為讀/寫控制位,第5列為32-bit的數據,第6列為4-bit的數據掩碼(DATA MASK),部分源代碼如下圖所示
分析srio_quick_start.v源文件
srio_quick_start.v源文件的第68行到第101行是接口定義。log_clk和log_rst分別為邏輯層的時鐘和復位。以maintr_*開頭的信號為AXI4-Lite通道的信號,以user_*開頭的信號是用戶自定義的維護事務的相關字段,go變量用來在用戶定義和maintenance_list.vh頭文件定義的字段中進行選擇
第105行到122行對maintenance_list.vh頭文件中的參數進行了賦值,并引入了頭文件,源代碼如下圖所示。
第192行到229行主要用來構建請求包,其本質就是產生AXI4-Lite的協議把數據發出去。部分源代碼如下圖所示
第233行到386行例化了一個RAMB36SDP原語,并用maintenance_list.vh頭文件中定義的數據進行初始化。部分源代碼如下圖所示
第397行到416行主要負責響應側的檢測,通過maint_autocheck_error和maint_done指示檢測狀態。源代碼如下圖所示
至此,維護事務的代碼分析完畢,它的代碼邏輯相對來說比較簡單。
另外,例子工程中還有兩個模塊srio_report.v和srio_statistics.v,它們只在仿真有用,在硬件上實現時最好刪掉。這里不再作過多分析。只要理解了srio_request_gen.v與srio_response_gen.v,用RapidIO完成相關應用就足夠了。
五、仿真
工程源碼分析完畢以后,接下來就可以開始仿真了。例子工程中的代碼一行都不要改,直接左鍵單擊Run Simulation,在彈出的菜單中點擊Run Behavioral Simulation,如下圖所示
接著會出現下面的滾動框,在這個界面需要等待一會,如下圖所示
上面的滾動框運行完畢以后就出現了波形界面,如下圖所示
然后再點擊下圖中圈出的小圖標把波形復位一下,如下圖所示
復位波形以后在Tcl Console中輸入指令:log_wave –r /* 。輸入完畢以后按回車。這條指令的作用是記錄所有中間變量的波形,這樣后面要觀察任何變量的波形只需要把它拖到波形界面中它的波形就會自動顯示出來而不需要重新仿真,大大節約了時間。如下圖所示
最后設置一個比較大的時間,我設置為10ms,然后點擊它左邊的按鈕開始仿真,大約20分鐘以后仿真會自動結束,如下圖所示
仿真的過程中,在相應的時間點上,Tcl Console中會打印出包的收發情況
最后仿真結束以后,重新回到波形界面可以看到波形都正常產生了。這里最重要的兩個信號就是link_initialized與port_initialized,當他們為高表示整個鏈路初始化完畢。至此,整個仿真過程全部結束,下篇文章會詳細介紹每種事務的時序圖以及需要注意的一些細節。
六、總結
本節主要分析了一下請求事務與響應事務的Verilog源碼,事實上,它們的源碼就是按照pg007_srio_gen2.pdf把HELLO格式與HELLO時序描述出來而已。當然官方的這套源碼為了盡可能保證測試到核的所有功能,寫的比較混亂,但在實際項目中可以充分借鑒它的設計思想,然后根據你自己的需求對不需要的地方進行修改來達到你的目標。除此以外,HELLO格式的時序其通過一個狀態機來實現可能更加簡潔易懂。總而言之,這套代碼具有很大的參考價值,但是要想把這個核玩透還是得自己多在項目中理解。
下篇文章將會教大家如何在Vivado抓出每種事務的時序來對各種RapidIO的交互過程有一個更加清晰的理解。
?
審核編輯 :李倩-
FPGA
+關注
關注
1629文章
21754瀏覽量
604203 -
模塊
+關注
關注
7文章
2717瀏覽量
47555 -
Xilinx
+關注
關注
71文章
2168瀏覽量
121662 -
Verilog
+關注
關注
28文章
1351瀏覽量
110148 -
源碼
+關注
關注
8文章
645瀏覽量
29273
原文標題:【高速接口-RapidIO】5、Xilinx RapidIO核例子工程源碼分析
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論