1. 程式人生 > >【高速介面-RapidIO】6、Xilinx RapidIO核模擬與包時序分析

【高速介面-RapidIO】6、Xilinx RapidIO核模擬與包時序分析

提示:本文的所有圖片如果不清晰,請在瀏覽器的新建標籤中開啟或儲存到本地開啟

一、軟體平臺與硬體平臺

  軟體平臺:

         作業系統:Windows 8.1 64-bit

         開發套件:Vivado2015.4.2

  硬體平臺:

         評估板:ZYNQ-7 ZC706 Evaluation Board

二、介紹

  上篇文章的最後一小節已經對例子工程進行模擬並通過命令 log_wave –r /* 記錄了所有訊號的波形,這篇文章主要介紹RapidIO核的模擬以及包時序的分析。

       除錯SRIO核時必須對包在不同介面的傳輸過程有一個清晰的瞭解,能夠識別出不同介面上包的型別並正確的解析出包的內容。

       本文詳細的介紹了SRIO包(控制符號與資料字元)在不同介面上的組成與傳輸過程,並深入到邏輯層、傳輸層以及物理層來觀察RapidIO序列物理層包的傳輸細節。整個包與訊號分析的過程完全基於RapidIO提供的例子工程,例子工程的產生與原始碼的分析已經在上一篇文章《Xilinx RapidIO核例子工程原始碼分析》(連結:https://www.cnblogs.com/liujinggang/p/10091216.html)提到過,這裡不再贅述。最後,本文會利用RapidIO核做一個迴環測試(Loopback Test)的工程在ZC706上執行,由於RapidIO是一個付費的IP核,所以生成bit檔案需要License,沒有License的可以在官網(https://www.xilinx.com/products/intellectual-property/ef-di-srio-gen2.html#overview)申請一個30天的評估版License試用,評估版的License生成的bit檔案執行一段時間以後會自動失效,要想永久使用必須購買官方的License。

三、例子工程結構

       下圖整個例子工程的結構層次

 

       它由一個模擬頂層的testbench和兩個SRIO核頂層組成。其中頂層的testbench檔案srio_sim.v連線了兩個srio例子設計頂層,其中一個例子設計頂層叫做srio_example_top_primary,它代表請求方的RapidIO裝置;另一個例子設計頂層叫做srio_example_top_mirror,它代表響應方的RapidIO裝置。

       SRIO例子工程頂層檔案srio_example_top.v例化了SRIO核的所有元件以及需要在硬體上執行的必要模組。這些模組包括:

       1、時鐘域復位模組(srio_clk.v和srio_rst.v)

       2、配置結構(cfg_fabric.v)

       3、請求事務與響應事務生成模組(srio_resquest_gen.v和srio_response_gen.v)

       4、維護事務生成模組(srio_quick_start.v)

       頂層模組srio_example_top中例化了srio_quick_start模組,它與SRIO的維護埠相連,用來生成維護事務(Maintenance Transactions)。這個模組用來向本地(Local)或遠端(Remote)的配置暫存器空間傳送一組固定的指令集,使用者可以編輯maintenance_list.v來新增、修改或移除維護事務。

srio_request_gen在頂層模組srio_example_top進行例化,它用來產生I/O事務或訊息(MESSAGE)事務,但僅僅SRIO核支援的事務型別能被產生,這個模組也儲存了期望的響應事務並與實際接收到的響應事務進行對比用來確定整個事務互動過程的正確性。

srio_response_gen也在頂層模組srio_example_top進行例化,它用來產生請求事務對應的響應事務。

  整個例子工程結構層次的軟體框架如下圖所示,其中左邊的srio_example_top模組表示請求方的RapidIO裝置,而右邊的DUT Mirror表示響應方的RapidIO裝置,它們的內部結構完全相同,區別僅僅在於一個作為請求方而另一個為響應方。

 

       SRIO核的原理框圖以及介面如下圖所示

 

       為了方便說明,上圖每一個介面都用相應的數字標註出來。它們分別為

       Initiator/Target IO Port(介面1)

       例子工程中SRIO核全部為預設引數,所以埠型別預設被配置為Initiator/Target,在Initiator/Target介面型別中請求事務與響應事務在不同的AXI4-Stream通道上進行傳輸。SRIO核的埠型別也能被配置為Condensed I/O型別,在Condensed I/O介面型別中請求事務與響應事務在同一AXI4-Stream通道上進行傳輸,所以Condensed I/O相比於Initiator/Target型別來說介面更加精簡。本文仍然採用預設的Initiator/Target介面型別來分析每個包的傳輸過程。

       介面1的資料傳輸協議為AXI4-Stream協議,它的介面定義如下:

       s_axis_ireq_* 表示Initiator請求事務的傳輸通道(i = initiator ,req = request)

  m_axis_iresp_* 表示Initiator響應事務的傳輸通道(i = initiator ,resp = response)

  m_axis_treq_* 表示Target請求事務的傳輸通道(t = target ,req = request)

  s_axis_iresp_* 表示Target響應事務的傳輸通道(t = target , resp = response)

       Maintenance Port(介面2)

       介面2的資料傳輸協議為AXI4-Lite協議,用來傳輸維護事務。它的介面定義如下:

       s_axi_maintr_* 表示維護事務的傳輸埠(maintr = maintenance)

       LOG Configuration Fabric(介面3)

       介面3的資料傳輸協議為AXI4-Lite協議,它是邏輯層的配置結構埠,包括本地(Local)配置埠和遠端(Remote)配置埠。它的介面定義如下:

       s_axi_cfgl_* 表示本地配置埠(cfg = configuration,l = local)

  m_axi_cfgr_* 表示遠端配置埠(cfg = configuration,r = remote)

  LOG Transport Interface(介面4)

       介面4的資料傳輸協議為AXI4-Stream協議,它是邏輯層與Buffer的資料傳輸介面,包括髮送和接收兩個通道。它的介面定義如下:

       m_axis_buft_* 表示傳送埠(buf = buffer,t = transmit)

  s_axis_ bufr_* 表示接收埠(buf = buffer,r = receive)

  BUF Link Interface(介面5)

       介面5的資料傳輸協議為AXI4-Stream協議,它是Buffer層與物理層的資料傳輸介面,包括髮送和接收兩個通道。它的介面定義如下:

       m_axis_phyt_* 表示傳送埠(phy= physical,t = transmit)

  s_axis_ phyr_* 表示接收埠(phy = physical,r = receive)

  BUF Configuration Fabric(介面6)

       介面6的資料傳輸協議為AXI4-Lite協議,它是Buffer層的配置埠。它的介面定義如下:

       s_axi_bcfg_* 表示Buffer層配置埠(b = buffer,cfg = configuration)

  PHY Serial Interface(介面7)

       介面7為物理層序列鏈路介面,它是物理層資料與序列收發器(Serial Transceivers)資料交換通道,它的介面定義如下所示:

訊號

方向

功能

gttx_data[32*LW-1 : 0]

Output

傳送給序列收發器(Serial Transceivers)的資料

gttx_charisk[4*LW-1 : 0]

Output

gttx_data訊號中有效位元組指示訊號。當這個訊號某一位為0時,gttx_data中對應的位元組為包的有效位元組。

gttx_inhibit[LW-1:0]

Output

序列收發器的通道使能位。如果最低位(bit-0)為1,表示傳送通道0(Lane0)不使能,其餘依次類推

gtrx_data[32*LW-1:0]

Input

從序列收發器(Serial Transceivers)接收的資料

gtrx_charisk[4*LW-1:0]

Input

gtrx_data訊號中有效位元組指示訊號。當這個訊號某一位為0時,gttx_data中對應的位元組為包的有效位元組。

gtrx_chariscomma[4*LW-1:0]

Input

gtrx_data訊號中comma指示訊號。如果最低位(bit-0)為1,表示gtrx_data[7:0]是包含comma的字元,其餘依次類推

gtrx_disperr[4*LW-1:0]

Input

gtrx_data訊號中不一致錯誤(Disparity Error)指示訊號。如果最低位(bit-0)為1,表示gtrx_data[7:0]中存在不一致錯誤,其餘依次類推

gtrx_notintable[4*LW-1:0]

Input

gtrx_data訊號中not-in-table錯誤指示訊號。Table指的是8b/10b編碼解碼錶。如果最低位(bit-0)為1,表示gtrx_data[7:0]中8b/10b解碼錯誤,其餘依次類推

gtrx_chanbondseq[LW-1:0]

Input

序列收發器每個鏈路的通道繫結序列(Channel Bonding Sequence)指示訊號,如果最低位(bit-0)為1,表示鏈路0(Lane0)收到了一串通道繫結序列,其餘依次類推

gtrx_chanisaligned[LW-1:0]

Input

序列收發器每個鏈路的通道對齊(Channel Alignment)指示訊號,如果最低位(bit-0)為1,表示鏈路0(Lane0)已經實現了通道對齊,其餘依次類推

gtrx_chanbonden

Output

序列收發器通道繫結使能訊號

gtrx_reset_req

Input

序列請求復位訊號。例如,由於序列收發器接收通路彈性FIFO的上溢(overflow)或下溢(underflow),

gtrx_reset

Output

序列收發器的復位訊號

gtrx_reset_done[LW-1:0]

Input

序列收發器每個鏈路的復位完成指示訊號,如果最低位(bit-0)為1,表示鏈路0(Lane0)已經復位完成,其餘依次類推

  PHY Configuration Fabric(介面8)

       介面8的資料傳輸協議為AXI4-Lite協議,它是物理層(Physical)的配置埠。它的介面定義如下:

       s_axi_cfgp_* 表示物理層配置埠(cfg = configuration,p = physical)

  Transceiver Interface(介面9)

       介面9為序列收發器高速資料傳輸介面,每條序列資料傳輸線均為一對差分訊號。它的介面定義如下:

       srio_rxpN ,srio_rxnN:N為通道號,接收鏈路差分對,N的值為1、2或4。

       srio_txpN ,srio_txnN:N為通道號,傳送鏈路差分對,N的值為1、2或4。

四、SRIO核包時序分析

       上篇文章《Xilinx RapidIO核例子工程原始碼分析》(連結:https://www.cnblogs.com/liujinggang/p/10091216.html)的最後一小節已經詳細介紹了模擬的全部流程以及利用log_wave –r /*命令記錄所有訊號波形的方法,這裡不再贅述。這一節預設大家已經模擬完畢(模擬結束大約需要20min左右時間,模擬完畢記得儲存波形),並得到了模擬的波形,下面就對其中重要的波形進行分析。

       在分析之前,在重新回顧一下RapidIO序列物理層的包與控制符號的格式

       序列物理層的包:

 

  控制符號:

4.1 鏈路初始化與控制符號

  除錯SRIO的第一步是去檢測SRIO頂層模組(srio_example_top_primary)中的各個關鍵的控制訊號是否正確切換。這些訊號包括:復位訊號、時鐘鎖定訊號(clk_lock)、埠初始化訊號(port_initialized)、鏈路初始化訊號(link_initialized),埠錯誤訊號(port_error),mode_1x訊號(在2x和4x模式下,這個訊號為高表示SRIO核已經被訓練為1x模式,在1x模式下,這個訊號一直為高,當port_initialized為高時,這個訊號才有效)與埠解碼錯誤訊號(port_decode_error)等(除了這幾個訊號以外,其他訊號也可以觀察一下)。

  Step1、把srio_example_top_primary中的所有訊號全部選中,然後直接拖到右邊的波形視窗

 

  Step2、找到上面提到的幾個關鍵控制訊號,觀察它們的波形

 

       由上圖可以看出,控制訊號的波形均切換正確,其中最關鍵的兩個訊號是port_initialized訊號與link_initialized訊號,當它們為高時,分別表示埠和鏈路被成功初始化。

       下圖是時鐘訊號和復位訊號的時序細節,顯然,時鐘訊號與復位訊號的時序均正確。

 

  Step3、pg007_srio_gen2.pdf第119頁提到,當7個連續的error free控制符號被接收,並且15個連續的符號被髮送的時候,link_initialized訊號才被拉高,所以接下來看看link_initialized訊號拉高之前物理層是否接收了7個控制符號併發送了15個控制符號。

首先選中最左邊的srio_gen2_0_block_inst,然後把中間列出的以gt開頭的介面7的所有訊號拖到最右邊的波形視窗中,如下圖所示

 

       在link_initialized拉高之前,觀察gttx_data,gttx_charisk與gtrx_data,gtrx_charisk總線上的資料,建議把gttx_charisk與gtrx_charisk用二進位制顯示,當gttx_charisk與gtrx_charisk對應的位為0時,表明gttx_data與gtrx_data上的資料為有效資料(控制符號與包屬於有效資料)。當gttx_charisk與gtrx_charisk對應的位為1時,gttx_data與gtrx_data上的資料為空閒序列。如下圖所示,當link_initialized拉高之前gttx_data上傳送了15個連續的控制符號,gtrx_data上接收了7個連續的控制符號。

 

       下面把控制符號波形放大觀察控制符號各個欄位的細節,傳送與接收總線上的控制符號分別如下圖所示(gttx_charisk與gtrx_charisk對應的位為0時, gttx_data與gtrx_data上的資料為控制符號)

 

 

       上圖表明在link_initialized拉高之前,傳送與接收的控制符號為80f713,控制符號80f713前面的1c是/K28.0/,表示控制符號的起始位置。由於SRIO核預設使用的是短控制符號,所以這裡控制符號為24-bit。

  把80f713轉化為二進位制:80f713 = 1000_0000_1111_0111_0001_0011,各個欄位的對應關係如下圖所示

  當gttx_charisk與gtrx_charisk對應的位為1時,gttx_data與gtrx_data上的資料為/K/,/R/,/A/組成的空閒隨機序列(前面幾篇文章解釋過這個知識點),它們分別為特殊字元/K28.5/,/K29.7/,/K27.7/,轉化為16進製為bc,fd,fb,下圖是它們的波形

 

  整個初始化的過程著重需要關注的兩個訊號就是port_initialized和link_initialized,如果初始化失敗(port_initialized和link_initialized沒有被拉高),那麼首先必須檢查gttx_data與gtrx_data上是否收到了空閒序列/K28.5/,/K29.7/,/K27.7/,同時需要檢查是否存在編解碼錯誤,編解碼錯誤的判斷標誌是gtrx_notintable訊號,當它為1時表明存在編解碼錯誤。

4.2 SWRITE事務

  上篇文章已經分析過,例子工程會把instruction_list.vh中定義的事務按順序依次發出去。其中最先發送的是37個SWRITE事務,然後是19個NWRITE_R事務、 19個NWRITE事務、26個NREAD事務,2個DOORBELL事務,最後是17個MESSAGE事務。其中第一個傳送的事務是instruction_list.vh中第50行定義的SWRITE事務。如下圖所示

 

  下面以上圖第50行的SWRITE事務為例來說明整個SWRITE事務的傳輸過程。這個事務表示的是利用SWRITE事務往地址36’hCD0000600傳送16個位元組的資料。

       Step1、選中srio_example_top_primary,把中間列出的所有訊號全部拖到波形視窗中(拖到波形視窗前可以把之前波形視窗中的訊號全部刪掉)

 

       Step2、找到請求事務的傳輸通道ireq,並抓出事務的波形如下圖所示

 

  由於僅當tvalid和tready同時為高時,tdata上的資料才為有效資料,所以這個SWRITE一共消耗了三個有效時鐘週期,其中第一個時鐘週期傳送的是HELLO包頭,後面兩個時鐘週期分別傳送8個位元組的資料(第一個時鐘傳送的資料是0000000000000000,第二個時鐘傳送的資料是0101010101010101),一共16個位元組的資料,和instruction_list.vh中第50行定義完全一致,整個時序也與HELLO格式的時序完全吻合。

       Step3、對照HELLO格式解析包頭。包頭為006020fcd0000600,轉化為二進位制後與HELLO格式各個欄位對應關係如下所示:

 

  由上圖可知FTYPE欄位的值為6,表明確實是一個SWRITE事務

       Step4、SWRITE事務通道ireq通道(介面1)傳輸給SRIO核以後進入SRIO的邏輯層,邏輯層會給包新增傳輸層的資訊傳送給Buffer(介面3),然後Buffer會把資料傳送給物理層(介面5)。

       選中srio_gen2_0_block_inst,把中間的buft_*通道、phyt_*通道與gttx_*通道的訊號拖到右邊的波形視窗中,如下圖所示

 

       整個從邏輯層到傳輸層到物理層到吉位元收發器(Gigabit Transceiver)的波形如下圖所示,波形的細節這裡不再展開,大家可以自己抓出來觀察。

 

       Step5、ireq通道的SWRITE請求事務經過邏輯層,傳輸層和物理層到達吉位元收發器(Gigabit Transceiver),吉位元收發器的資料通道gttx_data[31:0](介面7)波形如下圖所示

 

  由上圖可知,整個序列物理層的包為:7c96f004_b04600ad_d0000600_00000000_00000000_01010101_01010101_e8d30000_7c96f203。(00000000和01010101的寬度為兩個有效時鐘)這個包的含義如下:

       7c96f004中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),96f004轉化為二進位制為:

  96f004 = 1001_0110_1111_0000_0000_0100

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  b04600ad_d0000600_00000000_00000000_01010101_01010101_e8d30000是SWRITE事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

  上圖中data欄位是傳輸的00000000_00000000_01010101_01010101這16個位元組資料的二進位制碼,因為它的二進位制碼太長了所以我直接用data替代。由於本次傳輸的位元組小於80個位元組,所以SWRITE事務的最後面的三個欄位不存在,大家可以抓一下資料量為256個位元組的SWRITE包,當資料量大於了80位元組,後面的三個欄位也會有資料。

       包最後面的7c96f203中7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),96f203轉化為二進位制為:

  96f203= 1001_0110_1111_0010_0000_0011

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

  至此,SWRITE事務全部分析完畢。

4.3 NWRITE_R事務

  本小節以instruction_list.vh中第72行定義的NWRITE_R事務為例來說明整個NWRITE_R事務的傳輸過程。如下圖所示,這個事務表示的是利用NWRITE_R事務往地址36’ h004550002傳送6(size+1)個位元組的資料。

 

       Step1、為了方便快速的找到上圖的NWRITE_R事務,建議選中srio_request_gen模組,並把request_address變數拖到波形視窗中,並把這個變數用Unsigned Decimal(無符號10進位制)格式顯示。看過上篇《Xilinx RapidIO核例子工程原始碼分析》文章的應該知道這個變數是instruction的索引值,當這個變數為37的時候就表示37(0~36)個SWRITE事務全部發送完畢,下個事務就是instruction_list.vh中第72行定義的NWRITE_R事務。

 

  Step2、鎖定request_address為37的位置,找到請求事務的傳輸通道ireq,並觀察事務的波形如下圖所示

 

  由上圖可知第一個有效時鐘傳輸的HELLO格式包頭資料為:2555205004550002。傳送的資料是afafafafafafafaf。包頭與HELLO包格式的對應關係如下圖所示

 

  由上圖可知FTYPE = 5,TTYPE = 5,這兩個欄位唯一的確定了這是一個NWRITE_R事務。

  Step3、ireq通道的NWRITE_R請求事務經過邏輯層,傳輸層和物理層到達吉位元收發器(Gigabit Transceiver),吉位元收發器的資料通道gttx_data[31:0](介面7)波形如下圖所示

 

  由上圖可知,整個序列物理層的包為:7c98f009_d84500ad_59250455_0000afaf_afafafaf_afafad15_7c17f21e。這個包的含義如下:

       7c98f009中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),98f009轉化為二進位制為:

  98f009= 1001_1000_1111_0000_0000_1001

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  d84500ad_59250455_0000afaf_afafafaf_afafad15是NWRITE_R事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

  上圖中data欄位是傳輸的afafafaf_afafafaf這16個位元組資料的二進位制碼,因為它的二進位制碼太長了所以我直接用data替代。由於本次傳輸的總位元組數為8位元組的整數倍,所以NWRITE_R事務的後面可選的logical 0 pad(opt)沒有資料。

       細心的人在這裡可能發現了一個奇怪的現象:在HELLO格式中,address欄位為36’ h004550002,其中高兩位為保留位,所以address一共只有34-bit有效位,size欄位為5,表示往36’ h004550002地址中寫6(size+1)個位元組的資料。但是上面序列物理層的包中address欄位的值為0000_0100_0101_0101_0000_0000_0000_0,傳送的資料個數為8個位元組(afafafaf_afafafaf)。出現這種現象的原因為:

       HELLO格式address欄位指向的儲存空間的最小單元是1個位元組,而序列物理層中的address欄位指向的儲存空間最小單元實際上是8個位元組,address後面的xambsb欄位是序列物理層的最高兩位地址擴充套件欄位,所以序列物理層的包可訪問的儲存空間大小為2^34=16G,這也是HELLO格式中address欄位位寬為34-bit的原因(關於這部分的內容我在《RapidIO協議概述》也提到過)。正因為HELLO格式address欄位與序列物理層address欄位所指向的儲存空間最小單元不同,所以pg007_srio_gen2.pdf中第78頁才給出了一個HELLO格式size,addr與有效位元組的對應關係表,如下所示

 

  本例中size=5,addr[2:0] = 2,對應於上圖中紅框圈出來的情況。所以往36’ h004550002地址中寫6(size+1)個位元組的資料對序列物理層來說就是往36’ h004550000地址中寫8個位元組的資料,高6個位元組(上圖中灰色區域)為有效資料。

  包最後面的7c17f21e中7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),17f21e轉化為二進位制為:

  17f21e = 0001_0111_1111_0010_0001_1110

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

  Step4、例子工程中例化了srio_example_top_primary與srio_example_top_mirror兩個實體,srio_example_top_primary實體的srio_txp0和srio_txn0連線到srio_example_top_mirror實體的srio_rxp0和srio_rxn0。因此,srio_example_top_mirror的gtrx_data上的資料應該和上一步分析的srio_example_top_primary實體的gttx_data完全相同。

  選中srio_example_top_mirror的srio_gen2_0_block_inst,把gtrx_data與gtrx_charisk兩個訊號拖到右邊的視窗中,如下圖所示

 

       觀察srio_example_top_primary的gttx_data與srio_example_top_mirror的gtrx_data,如下圖所示,可以看到兩者完全相同,僅僅存在一個延時。

 

  Step5、srio_example_top_mirror模組的grrx_data接收到資料以後,將會把grrx_data的資料按照與傳送過程完全相反的操作傳到邏輯層,最終邏輯層的資料將會通過srio_example_top_mirror模組的treq介面輸出。

  選中srio_example_top_mirror,把treq通道的所有訊號拖到右邊的波形視窗中

 

  下圖是srio_example_top_mirror模組treq通道的波形

 

  可知treq通道的包頭資料為2555205004550002,與srio_example_top_primary模組ireq通道傳送的包頭資料完全一樣。這也證明整個鏈路工作正常。

4.4 NWRITE_R的響應事務

  由於NWRITE_R事務是一個有響應的寫事務,所以當發起方(Initiator)往目標方(Target)傳送一個NWRITE_R事務以後,發起方(Initiator)還要接收目標方(Target)的發回響應事務。響應包的資料會出現在srio_example_top_primary模組的tresp通道,下圖是srio_example_top_primary模組的tresp通道的時序圖

 

  由上圖可知iresp_tdata的資料為:25d0400000000000。與HELLO包格式的對應關係如下圖所示

 

  由上圖可知FTYPE = 13,所以這是一個響應事務,prio欄位變成了2,而NWRITE_R欄位的prio欄位為1,這是因為響應事務的prio為請求事務的prio+1,(這個知識點前兩篇文章都提到過)

       事實上,響應事務的一整套傳輸流程為:目標方(Target)發回的響應事務被srio_example_top_primary模組的序列差分訊號線接收到達Serial Transceivers,Serial Transceivers在把接收的資料通過gtrx_data通道(介面7)傳到物理層,物理層把接收的包經過處理以後通過phyr_*通道(介面5)把資料發給Buffer層,Buffer層對資料進行二次處理以後把資料通過bufr_*通道(介面4)傳給邏輯層,邏輯層再把資料傳輸給I/O埠(介面1),這樣就得到了上圖HELLO格式的響應包。大家可以把gtrx_data、phyr_*通道、bufr_*通道和I/O埠的波形全部抓出來觀察一下,方法和上節介紹傳送流程的抓取過程完全一樣。這裡我只抓一下gtrx_data通道的資料,並分析響應事務序列物理層包格式各個欄位的含義。

  gtrx_data通道的資料如下圖所示

 

  由上圖可知,整個響應事務序列物理層的包為:7c83f00f_388dadad_00255540_7c83f208

       7c83f00f中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),83f00f轉化為二進位制為:

  83f00f = 1000_0011_1111_0000_0000_1111

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  388dadad_00255540是NWRITE_R響應事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

  由於NWRITE_R的響應事務不帶資料,所以沒有data欄位。target TID欄位的值為16進位制的25,也就是10進位制的37,與傳送的NWRITE_R請求事務target TID值完全相同。FTPYE欄位的值為13,說明這是一個響應事務,整個響應事務的包正是NWRITE_R事務的響應包。

       7c83f208中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),83f208轉化為二進位制為:

  83f208= 1000_0011_1111_0010_0000_1000

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

4.5 NWRITE事務

  本小節以instruction_list.vh中第94行定義的NWRITE事務為例來說明整個NWRITE事務的傳輸過程。如下圖所示,這個事務表示的是利用NWRITE事務往地址36’ hDE0000600傳送16(size+1)個位元組的資料。

 

  Step1、為了方便快速的找到上圖的NWRITE事務,建議選中srio_request_gen模組,並把request_address變數拖到波形視窗中,並把這個變數用Unsigned Decimal(無符號10進位制)格式顯示。看過上篇《Xilinx RapidIO核例子工程原始碼分析》文章的應該知道這個變數是instruction的索引值,當這個變數為56的時候就表示37(0~36)個SWRITE事務全部發送完畢,19個NWRITE_R事務也全部發送完畢,下個事務就是instruction_list.vh中第94行定義的NWRITE事務。鎖定request_address為56的位置,找到請求事務的傳輸通道ireq,並觀察事務的波形如下圖所示

 

  由上圖可知第一個有效時鐘傳輸的HELLO格式包頭資料為:385420fde0000600。後兩個有效時鐘傳送的資料分別是c2c2c2c2c2c2c2c2和c3c3c3c3c3c3c3c3。包頭與HELLO包格式的對應關係如下圖所示

 

  由上圖可知FTYPE = 5,TTYPE = 4,這兩個欄位唯一的確定了這是一個NWRITE_R事務。srcTID的值為16進位制的38,也就是10進位制的56,與request_address的值相等,因為程式碼裡面就是直接把request_address的值賦給了srcTID。

  Step2、ireq通道的NWRITE請求事務經過邏輯層,傳輸層和物理層到達吉位元收發器(Gigabit Transceiver),吉位元收發器的資料通道gttx_data[31:0](介面7)波形如下圖所示

 

  由上圖可知,NWRITE序列物理層包的資料為:

  7c93f010_c84500ad_4b38e000_0605c2c2_c2c2c2c2_c2c2c3c3_c3c3c3c3_c3c362a2_7c13f20e。包的各個欄位解釋如下:

       7c93f010中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),93f010轉化為二進位制為:

  93f010= 1001_0011_1111_0000_0001_0000

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  c84500ad_4b38e000_0605c2c2_c2c2c2c2_c2c2c3c3_c3c3c3c3_c3c362a2是NWRITE事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

  細心的同學馬上會發現wrsize欄位的值居然為11(2進位制1011,16進位制b),address欄位的值為e000_0600。而instruction_list.vh中第94行定義的size欄位的值為15,address欄位的值為36’hDE0000600。似乎邏輯層的包到達物理層以後size欄位和address兩個欄位都出現了錯誤。出現這種現象的原因如下:

       前面幾篇文章也多次提到過,address後面的兩個欄位wdptr和xamsbs兩個欄位是有作用的,xamsbs欄位是地址欄位的高兩位擴充套件位。由於HELLO格式address欄位的有效位數是34-bit,所以在當address欄位的值為36’hDE0000600,有效的address欄位的值為34’h 1E0000600,當我們把序列物理層xamsbs欄位的01拼接在序列物理層address欄位前面得到的地址就和先前定義的地址是一致的了。

       至於wrsize欄位的值為11,這是因為後面的wdptr欄位的值變成了1,RapidIO_Rev_2.2_Specification的第35頁表4-4已經列出了所有wrsize與wdptr欄位的組合,當wdptr=1,wrsize=11是,位元組的總個數是16,這也和我們之前在instruction_list.vh中的定義是一致的。

 

       7c13f201中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),13f201轉化為二進位制為:

  13f201= 0001_0011_1111_0010_0000_0001

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

4.6 NREAD事務

  本小節以instruction_list.vh中第120行定義的NREAD事務為例來說明整個NREAD事務的傳輸過程。如下圖所示,這個事務表示的是利用NREAD事務往地址36’ h0000023F0傳送8(size+1)個位元組的資料。

 

  Step1、為了方便快速的找到上圖的NREAD事務,建議選中srio_request_gen模組,並把request_address變數拖到波形視窗中,並把這個變數用Unsigned Decimal(無符號10進位制)格式顯示。看過上篇《Xilinx RapidIO核例子工程原始碼分析》文章的應該知道這個變數是instruction的索引值,當這個變數為78(37+19+19+3=78)的時候就表示傳送的是上圖第120行的NREAD事務(之所以不選擇第123行的讀事務是因為它讀的資料量太大了,截圖的時候不方便)。鎖定request_address為78的位置,找到請求事務的傳輸通道ireq,並觀察事務的波形如下圖所示

 

       NREAD請求事務不帶任何資料,只包含一個HELLO格式的包頭,包頭的資料為:4e242070000023f0。各個欄位的對應關係如下圖所示

 

  FTYPE=2,TTYPE=4,這兩個欄位唯一的確定了這是一個NREAD事務包。其他欄位也與之前在instruction_list.vh中第120行定義的完全相同。

       Step2、接下來再看看NREAD事務序列物理層的包格式,這個包在155610ns的位置,下圖是NREAD事務序列物理層包格式的時序圖

 

  由上圖可知,整個序列物理層的包為:7c92f014_b84200ad_4b4e0000_23f09c5a_7c92f213。這個包的含義如下:

       7c92f014中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),92f014轉化為二進位制為:

  92f014= 1001_0010_1111_0000_0001_0100

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  b84200ad_4b4e0000_23f09c5a是NREAD事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

       FTYPE = 2,TTYPE = 4,這兩個值確定了這個包是一個NREAD事務包。rdsize=11(二進位制的1011),wdptr=0,通過查RapidIO_Rev_2.2_Specification第34頁的表可知資料量為8個位元組,與instruction_list.vh中第120行定義的完全相同。wdptr與rdsize的對應關係表如下所示

 

  7c92f213中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),92f213轉化為二進位制為:

  92f213= 1001_0010_1111_0010_0001_0011

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

4.7 NREAD響應事務

  由於NREAD事務是一個有響應的事務,且響應事務中攜帶讀到的資料。所以當發起方(Initiator)往目標方(Target)傳送一個NREAD事務以後,發起方(Initiator)還要接收目標方(Target)的發回響應事務。響應事務通過gtrx_data通道接收。響應事務序列物理層包時序如下圖所示,這個響應包在157370ns的位置

 

  由上圖可知,00000000這個資料傳輸了2個時鐘週期,所以整個響應事務序列物理層的包為:7c8af01e_708dadad_804e0000_00000000_0000469c_7c8af219

       7c83f00f中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),83f00f轉化為二進位制為:

  83f00f = 1000_0011_1111_0000_0000_1111

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  708dadad_804e0000_00000000_0000469c是NREAD響應事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

       FTYPE=13表示這是一個響應事務,TTYPE=8表示這個響應事務攜帶資料,target TID的值為16進位制的4e(10進位制的78),與請求事務剛好對應上,data欄位是8個位元組的00,由於並沒有儲存器,所以讀出來的資料全部是0。

       7c8af219中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),8af219轉化為二進位制為:

  8af219= 1000_1001_1111_0010_0001_1001

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

       響應事務序列物理層的包經過物理層、傳輸層和邏輯層到達iresp通道,iresp通道的時序如下圖所示

 

  iresp通道一共有兩個有效資料,分別為HELLO格式包頭4ed8400000000000和0000000000000000。HELLO格式包頭4ed8400000000000各個欄位的對應關係如下圖所示

 

       FTYPE = 13,TTYPE = 8表示這是一個攜帶資料的響應事務,響應事務的prio欄位的值為請求事務prio欄位的值加1。

4.8 MAINTENANCE事務

  頂層模組srio_example_top.v中例化的srio_quick_start模組與SRIO IP核的維護埠相連用來產生維護事務。維護事務在maintenance_list.vh標頭檔案中定義,使用者可以通過編輯maintenance_list.vh標頭檔案來新增、修改或移除維護事務。下圖是例子工程中定義的所有維護事務

 

       維護事務有本地(Local)和遠端(Remote)兩種型別,區分這兩種維護事務是通過maintr_araddr訊號的高八位的值來確定的。如下圖所示

 

  由上圖可知,maintr_araddr的[31:24]位用來區分本地維護事務和遠端維護事務,

  當 maintr_araddr=01xxxxxx,表示的是遠端(Remote)維護事務。

  當 maintr_araddr=00xxxxxx,表示的是本地(Local)維護事務。

  maintr_araddr的[23:0]位是讀操作的偏移地址。

       下圖是一個維護事務的時序圖

 

  由上圖可知,紅色框出來的部分是一個讀維護事務,由於maintr_araddr的高8位[31:24]為8’h00,所以這是一個本地(Local)讀維護事務。maintr_araddr的[23:0]位為24’h000000,所以這個本地(Local)讀維護事務訪問的是邏輯層的能力暫存器(Capability Register Space)空間,且暫存器的偏移地址為24’h000000。

  SRIO核暫存器空間的分佈如下圖所示

 

       下圖是維護埠(介面2)和邏輯層配置埠(介面3)的時序圖

 

 

  當 maintr_araddr=01000000,表示的是邏輯層的遠端(Remote)維護事務。邏輯層I/O埠發起的維護事務會通過邏輯層、傳輸層到物理層轉化為序列物理層的包通過高速序列收發器(Serial Transceiver)發出去。下圖是一個遠端維護事務序列物理層包的時序,這個包在96680ns的位置

 

  由上圖可知,維護事務序列物理層的包為:7c82f00b_104800ff_18010000_0060dead_beefdead_beefbe6e_7c82f20c

       7c82f00b中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),82f00b轉化為二進位制為:

  82f00b = 1000_0010_1111_0000_0000_1011

  它是一個包起始控制符號,各個欄位的對應關係如下圖所示

 

  104800ff_18010000_0060dead_beefdead_beefbe6e是維護事務序列物理層的包,把它轉化為二進位制後各個欄位的對應關係如下圖所示

 

  FTYPE = 8,TTYPE = 1,表明這是一個寫請求的維護事務。上圖中data欄位表示的是dead_beefdead_beef這8個位元組的資料。

       7c82f20c中的7c是特殊字元/K28.3/,它是一個包界定符(Packet Deliminator Control Symbol),82f20c轉化為二進位制為:

  82f20c = 1000_0010_1111_0010_0000_1100

  它是一個包結束控制符號,各個欄位的對應關係如下圖所示

 

4.9 DOORBELL事務與MESSAGE事務

       門鈴(DOORBELL)事務與訊息(MESSAGE)事務的分析方法與之前幾種方法完全一樣,大家可以自己按照上面的流程先找到HELLO格式的包,對照HELLO格式各個欄位的定義進行分析,然後找到序列物理層的包對照序列物理層的包格式再次分析就能明白整個事務的互動過程了。其實對於使用者來說,序列物理層是SRIO IP核幫我們設計好的,所以在實際專案中使用的時候只需要關注HELLO格式的包與時序就可以了。

五、(選讀)SRIO核在ZC706上回環(Loopback)測試

       通過Vivado模擬以後大家應該對使用SRIO核有了一個基本瞭解。如果你手頭有自己做的開發板並且有SRIO的License的話你可以利用SRIO在硬體上做一個迴環測試。

       所謂SRIO的迴環測試就是把SRIO的srio_txp0和srio_rxp0在硬體上連線起來,把srio_txn0和srio_rxn0在硬體上連線起來,讓SRIO的包自發自收。如下圖所示

 

       由於我手頭有一塊Xilinx的ZC706評估板,所以這個迴環測試我會在ZC706上完成。

       ZC706上的FPGA型號為XC7Z045,它的上面BANK109、BANK110、BANK111和BANK112為MGT BANK,如下圖所示

其中BANK112與PCIe介面相連(後面有空會寫PCIe介面),所以RapidIO不能使用這個BANK。BANK109與BANK110與FMC介面相連,無法使用同軸線或光纖環回,所以這兩個BANK也不能使用。因此RapidIO只剩下BANK111可用,而且BANK111有一個通道已經通過C653和C652環回上了,這樣就省去了自己用光纖或同軸線去環回。接下來最重要的就是給BANK111輸入一個125MHz的參考時鐘。

這個125MHz的時鐘可以從臨近的BANK“借”一個,比如可以通過軟體配置SI5324產生一個125MHz時鐘,儘管SI5324輸出的時鐘並不在BANK111上,但是這個125MHz仍然可以被BANK111“借”用。但是這種方法需要寫軟體配置SI5324,比較麻煩,所以不推薦。

下面介紹另外一種得到這個125MHz時鐘的方法:由於BANK111上有一路時鐘是連線到SMA介面上的,所以這個125MHz時鐘可以用外部的訊號源接入,但是如果你沒有訊號源的話也沒事,這個125MHz時鐘可以通過FPGA內部的Clocking Wizard產生。

       ZC706評估板的結構圖如下圖所示

 

  可以看到上圖用紅色橢圓圈出來的9號和10號兩個SMA介面對,10號SMA介面就是連線到BANK111上的一個參考時鐘,所以我們只需要用FPGA中的Clocking Wizard IP核用ZC706的200MHz系統時鐘得到125MHz的時鐘輸出到9號SMA介面對,然後用同軸線把9號SMA介面對和10號介面對相連就可以了。由於Clocking Wizard IP核輸出的時鐘是單端時鐘,所以還必須用OBUFDS原語把這個125MHz單端時鐘變成差分時鐘輸出到9號SMA介面對。

  有了125MHz的參考時鐘以後,接下來就只需要修改例子工程的頂層srio_example_top_srio_gen2_0程式碼,新增9號SMA介面對的引腳定義,修改例子工程的物理約束就可以了。還有一個訊號就是srio_example_top_srio_gen2_0頂層程式碼中的sim_train_en在硬體上執行時必須置0。修改完成以後就可以生成bit檔案下載到ZC706上觀察現象了,還可以用ILA抓一下I/O通道的波形,沒有問題的話抓出來的波形和之前模擬的波形是完全一樣的。

六、總結

       整個RapidIO系列部落格到此就全部寫完了,最後提供兩個模擬的建議:

       1、上文我抓的包傳輸資料量都比較少,主要是方便我截圖,傳輸的資料量比較大的時候,整個包的總位元組數會超過80個位元組,在資料量超過80位元組的情況下包中會出來兩個迴圈冗餘校驗碼(CRC碼),這個在《RapidIO序列物理層的包與控制符號》提到過,大家可以自己把包的資料量改的大一點觀察一下資料量大於80位元組的情況。

       2、由於例子工程中測試的比較全面,所以一共發了很多包,這樣導致找包的時候非常難找,這裡提供一個小技巧,你只需要把srio_request_gen_srio_gen2_0.v模組中的第359行instruction的索引值request_address改成一個固定的數,那麼就只會連續不斷的發一種包,看波形的時候就會非常方便,缺點是每修改一次就需要重新模擬,所以比較耗費時間。

 

七、參考資料

       1、Xilinx_Answer_50166。下載連結:https://china.xilinx.com/Attachment/Xilinx_Answer_50166_SRIO_Debugging_Packet_Analysis_Guide_ver1.pdf

  2、RapidIO™ Interconnect Specification,下載連結 https://pan.baidu.com/s/1ek-3AAhetLAcxTuOE2IyMg

  3、pg007_srio_gen2,下載地址 https://china.xilinx.com/support/documentation/ip_documentation/srio_gen2/v4_0/pg007_srio_gen2.pdf