這段時間有個朋友加微信請求幫忙調試一塊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,基本上接近滿帶寬了。
以上工程就是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,但源碼價格不菲哦。
一、xapp1052 K7移植工程,附硬件代碼註釋和windows驅動說明(50元一份)
二、xapp1052 K7移植工程(FIFO接口),附硬件代碼註釋和windows驅動說明以及測試程序(500元一份)
三、支持XILINX全系列的多通道PCIe DMA IP核(價格詳談)
有須要請微信(330853172)聯繫