PCIE_DMA實例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

PCIE_DMA實例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

一:前言

這段時間有個朋友加微信請求幫忙調試一塊PCIe採集卡。該採集卡使用xilinx xc7k410t作控制器,上位機爲XP系統,原有的驅動和測試軟件都是基於xapp1052寫的。衆所周知,Xilinx升級到7系列後,原來的pcie ip核trn接口通通轉換成了axis接口,這可愁壞了以前用xapp1052的朋友,一會兒很差用了,如何把xapp1052移植到K7系列FPGA上,貌似頗有市場。博主搜了如下XILINX官網,發現V3.3版本的xapp1052已經可以在K7上使用了。但畢竟只是一個示例工程,數傳接口並不友好。針對專門作採集卡的朋友,博主提供了一個由FIFO做爲用戶接口的BMD工程。windows

二:前期準備

一、pcie基礎仍是要有,尤爲是協議部分。推薦一本電子書,很經典,請耐心讀它(Addison.Wesley.PCI.Express.System.Architecture.eBook-LiB.chm)下載地址:http://download.csdn.net/download/yuzeren48/7723815微信

二、pg054app

三、Vivado2018.2套件ide

四、Windriver函數

五、Visual studio 2010post

三:移植步驟

一、在vivado中建立一個K7 pcie ipcore的example工程。測試

二、在xilinx官網下載xapp1052.pdf與xapp1052.zipthis

三、將1和2兩個工程的代碼融合並稍做修改,造成BMD工程,可選擇64位寬(4x 2.5G )或128位寬(4x 5G),代碼層級以下:spa

4,關鍵代碼分析.net

1)、BMD_EP_MEM-Control/Status Registers 全部的用戶狀態寄存器在模塊BMD_EP_MEM中。咱們一切的DMA傳輸首先是要控制這 些寄存器,而後進行DMA傳輸,傳輸完成後在讀取狀態寄存器的值獲取傳輸狀態。

2)、EP_RX_ENGINE-Target 這個模塊的功能在EP_RX_ENGINE裏面實現,負責接收讀寫TLP命令,而且提交完成讀 寫內存的完成響應。EP_RX_ENGINE裏面,Target接收PC發過來的32bit不帶數據的存儲 器讀請求和帶1個DW字的32bit 存儲器寫請求。控制狀態寄存器就是經過Target讀寫。

3)、EP_RX_ENGINE-Rx引擎 Rx引擎除了負責接PC讀寫存儲器請求,也要完成開發板發出的讀內存請求的完成響應 (DMA傳輸)。

4)、BMD_EP_MEM-Tx引擎 Tx引擎除了負責接發送DMA數據到PC,也要發送PC發送的讀寫TLP包的完成響應。

5)、BMD_EP_MEM-Control/Status Registers 全部的用戶狀態寄存器在模塊BMD_EP_MEM中。咱們一切的DMA傳輸首先是要控制這 些寄存器,而後進行DMA傳輸,傳輸完成後在讀取狀態寄存器的值獲取傳輸狀態。

6)、Interface 總線接口,pcie-app_7x就是包含了BMD全部的總線接口。

7)、AXI4-Stream轉BMD協議接口 axi_trn_rx模塊和axi_trn_tx實現了最新的AXI4-Stream協議轉BMD協議。有讀者可能 會懷疑轉換的協議可能影響傳輸效率,實際上不會有任何效率的犧牲,由於這裏是FPGA直 接完成了協議的轉換,沒有任何的延遲。

筆者對關鍵邏輯部分代碼作了很是詳細的註釋,讀者可在文末根據需求自行購買。

5,上位機軟件代碼分析

裝好windriver後,咱們能夠在windriver安裝目錄下找到BMD工程對應的驅動文件

使用VS2010打開後,文件目錄以下,如需獲取每一個C文件中函數的功能定義,請在文末購買相應資料。

運行該測試程序,並打開VIVADO工程抓包,看上去是V5的測試代碼,但能夠經過輸入VendorID和DeviceID來找到咱們本身的板卡。

 

在4x GEN1(2.5G)的狀況下,作連續讀寫測試,實測PCIe寫帶寬約爲840MB/s,PCIe讀帶寬約爲761MB/s,基本上接近滿帶寬了。

4、工程化範例

以上工程就是xapp1052在K7上的移植測試,但對於作工程應用的朋友來講,這個工程並不實用,全部DMA讀寫的數據都是根據咱們用戶本身配置的一個patten寄存器固定死的,若是要把FIFO中的數據經過xapp1052 DMA傳輸到系統內存,則須要修改部分源代碼。這裏,博主有償爲你們提供了一個FIFO接口的BMD工程。

用戶接口以下:

module  pcie_app_7x#(
   parameter C_DATA_WIDTH = 64,            // RX/TX interface data width
   // Do not override parameters below this line 
   parameter KEEP_WIDTH = C_DATA_WIDTH / 8  ,             // TKEEP width
   parameter REM_WIDTH  = (C_DATA_WIDTH == 128) ? 2 : 1 // trem/rrem width
    
)(

  input                         user_clk,
  input                         user_reset,
  input                         user_lnk_up, 

  // Tx
  input  [5:0]                  tx_buf_av,
  input                         tx_cfg_req,
  input                         tx_err_drop,
  output                        tx_cfg_gnt,

  input                         s_axis_tx_tready,
  output  [C_DATA_WIDTH-1:0]    s_axis_tx_tdata,
  output  [KEEP_WIDTH-1:0]      s_axis_tx_tkeep,
  output  [3:0]                 s_axis_tx_tuser,
  output                        s_axis_tx_tlast,
  output                        s_axis_tx_tvalid, 
  
  // Rx
  output                        rx_np_ok,
  output                        rx_np_req,
  input  [C_DATA_WIDTH-1:0]     m_axis_rx_tdata,
  input  [KEEP_WIDTH-1:0]       m_axis_rx_tkeep,
  input                         m_axis_rx_tlast,
  input                         m_axis_rx_tvalid,
  output                        m_axis_rx_tready,
  input    [21:0]               m_axis_rx_tuser,

  // Flow Control
  input  [11:0]                 fc_cpld,
  input  [7:0]                  fc_cplh,
  input  [11:0]                 fc_npd,
  input  [7:0]                  fc_nph,
  input  [11:0]                 fc_pd,
  input  [7:0]                  fc_ph,
  output [2:0]                  fc_sel,  


  // CFG
  input  [31:0]                 cfg_do,
  input                         cfg_rd_wr_done,
  output [31:0]                 cfg_di,
  output [3:0]                  cfg_byte_en,
  output [9:0]                  cfg_dwaddr,
  output                        cfg_wr_en,
  output                        cfg_rd_en,

  output                        cfg_err_cor,
  output                        cfg_err_ur,
  output                        cfg_err_ecrc,
  output                        cfg_err_cpl_timeout,
  output                        cfg_err_cpl_abort,
  output                        cfg_err_cpl_unexpect,
  output                        cfg_err_posted,
  output                        cfg_err_locked,
  output [47:0]                 cfg_err_tlp_cpl_header,
  input                         cfg_err_cpl_rdy,
  output                        cfg_interrupt,
  input                         cfg_interrupt_rdy,
  output                        cfg_interrupt_assert,
  output [7:0]                  cfg_interrupt_di,
  input  [7:0]                  cfg_interrupt_do,
  input  [2:0]                  cfg_interrupt_mmenable,
  input                         cfg_interrupt_msienable,
  input                         cfg_interrupt_msixenable,
  input                         cfg_interrupt_msixfm,
  output                        cfg_turnoff_ok,
  input                         cfg_to_turnoff,
  output                        cfg_trn_pending,
  output                        cfg_pm_wake,
  input   [7:0]                 cfg_bus_number,
  input   [4:0]                 cfg_device_number,
  input   [2:0]                 cfg_function_number,
  input  [15:0]                 cfg_status,
  input  [15:0]                 cfg_command,
  input  [15:0]                 cfg_dstatus,
  input  [15:0]                 cfg_dcommand,
  input  [15:0]                 cfg_lstatus,
  input  [15:0]                 cfg_lcommand,
  input  [15:0]                 cfg_dcommand2,
  input   [2:0]                 cfg_pcie_link_state,

  output [1:0]                  pl_directed_link_change,
  input  [5:0]                  pl_ltssm_state,
  output [1:0]                  pl_directed_link_width,
  output                        pl_directed_link_speed,
  output                        pl_directed_link_auton,
  output                        pl_upstream_prefer_deemph,
  input  [1:0]                  pl_sel_link_width,
  input                         pl_sel_link_rate,
  input                         pl_link_gen2_capable,
  input                         pl_link_partner_gen2_supported,
  input  [2:0]                  pl_initial_link_width,
  input                         pl_link_upcfg_capable,
  input  [1:0]                  pl_lane_reversal_mode,
  input                         pl_received_hot_rst,

  output [63:0]                 cfg_dsn,
//user port
  output [63:0]                 RX_FIFO_DATA_o,
  output                        RX_FIFO_WR_o,
  input  [63:0]                 TX_FIFO_DATA_i,
  output                        TX_FIFO_RD_o, 
  output [7:0]                  pcie_tap
)

 

這個接口能夠直接連在xilinx的PCIe IP核接口上,用戶接口對於作數據採集卡的朋友很是友好。這裏作一個利用XAPP1052 經過FIFO採集數據的例子。爲了驗證數據的方便,咱們在開發板上經過一個計數器計數,把計數的值發送到上位機上。測試結果以下:

另外須要補充一點,這個工程在DMA寫數據,也就是FPGA寫數據到PC的時候,沒有任何問題。可是在DMA讀數據的時候,也就是FPGA從PC端讀大量數據的時候,會出現返回的數據包亂序的現象。這是xapp1052的通病,對於作採集卡的朋友,這個問題並沒有影響,由於不須要從PC端讀數據。若是有朋友須要讀寫都正確無誤的PCIe DMA工程,可單獨聯繫我,本人有全套PCIe DMA源代碼,可用於各類系列的FPGA,但源碼價格不菲哦。

5、附件

一、xapp1052 K7移植工程,附硬件代碼註釋和windows驅動說明(50元一份)

二、xapp1052 K7移植工程(FIFO接口),附硬件代碼註釋和windows驅動說明以及測試程序(500元一份)

三、支持XILINX全系列的多通道PCIe DMA IP核(價格詳談) 

有須要請微信(330853172)聯繫

相關文章
相關標籤/搜索