• 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工程。

    二:前期准备

    1、pcie基础还是要有,尤其是协议部分。推荐一本电子书,很经典,请耐心读它(Addison.Wesley.PCI.Express.System.Architecture.eBook-LiB.chm)下载地址:http://download.csdn.net/download/yuzeren48/7723815

    2、pg054

    3、Vivado2018.2套件

    4、Windriver

    5、Visual studio 2010

    三:移植步骤

    1、在vivado中创建一个K7 pcie ipcore的example工程。

    2、在xilinx官网下载xapp1052.pdf与xapp1052.zip

    3、将1和2两个工程的代码融合并稍作修改,形成BMD工程,可选择64位宽(4x 2.5G )或128位宽(4x 5G),代码层级如下:

    4,关键代码分析

    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,但源码价格不菲哦。

    五、附件

    1、xapp1052 K7移植工程,附硬件代码注释和windows驱动说明(50元一份)

    2、xapp1052 K7移植工程(FIFO接口),附硬件代码注释和windows驱动说明以及测试程序(500元一份)

    3、支持XILINX全系列的多通道PCIe DMA IP核(价格详谈) 

    有需要请微信(330853172)联系

  • 相关阅读:
    STL-- vector中resize()和reserve()区别
    计算机网络--网络层
    计算机网络--数据链路层
    算法--排序算法
    数据结构--树--哈夫曼树
    数据结构--树--AVL树
    数据结构--树--二叉查找树
    数据结构--树--红黑树
    深入理解计算机系统读书笔记
    C++面试笔记--字符串
  • 原文地址:https://www.cnblogs.com/yuzeren48/p/10449766.html
Copyright © 2020-2023  润新知