基于Xilinx FPGA XDMA的PCIE通信

本文介绍了如何使用Xilinx A7 FPGA通过PCIe接口实现与PC上位机的数据通信。重点讲述了开发流程,包括Xilinx的DMA Subsystem for PCIe IP核的配置和使用,以及如何通过DMA方式和BAR方式实现数据包的发送与接收、寄存器的读写。在测试中,实现了数据的正确传输并进行了验证。

                         

目录

                                             基于Xilinx FPGA XDMA的PCIE通信

0 概述

1 准备工作

2. 开发流程

3. 测试结果

4 总结

 

正文

0 概述

    最近因仪表项目需求,需要上位机PC端通过PCIE接口与FPGA功能子卡进行数据通信,故开始研究基于Xilinx A7 FPGA实现PCIE接口功能。

1 准备工作

    要实现上位机Host端与FPGA子卡设备端通过pcie接口通信,需要3个必备条件:

(1)上位机应用程序;

(2)pcie驱动程序;可以从Xilinx官网下载对应系统驱动,然后进行二次开发,添加用户所需的驱动函数

(3)FPGA子卡端PCIE逻辑程序;

需要阅读的Specification和User Guide如下:

1. PCI.Express.Base.Specification.v2.0 - PCIE总线协议说明书 

如果仅从项目应用角度而言,只需要通读一遍,有个大概印象,熟悉高频专业术语即可,不用花大量时间去啃,因为Xilinx官方会提供PCIE IP核,将底层逻辑都封装好,开发者只需关注用户开发逻辑即可。PS:当然,如果有时间,深入研究肯定更好。

2. DMA/Bridge Subsystem for PCI Express v4.1 (pg195)

xilinx官方用户手册,讲解PCIE XDMA IP核的用法

PS:以前用ISE开发软件的时候,由于Xilinx官方提供的PCIE DMA方式是基于xapp1052文档讲述的Demo例程,需要用户去理解Demo工程,并自行增加用户所需的功能逻辑,我那个时候研究了一段时间后,还是没有完全搞定,就搁置了。

现在Vivado开发软件提供的XDMA IP核封装的更简单,使用更非常方便,解决了我这种PCIE小白很多开发障碍,首推。

2. 开发流程

    (1)Xilinx 提供的 DMA Subsystem for PCIExpress IP 是一个高性能,可配置的适用于 PCIE2.0, PCIE3.0 的 SG 模式
DMA,提供用户可选择的 AXI4 接口或者 AXI4-Stream 接口。

PCIE XDMA IP核配置的关键参数为BAR参数设置。PCIE DMA interface软件已默认使能,用户可以通过使能PCIE to AXI_Lite Master接口与主机端

进行寄存器的读写操作。XDMA IP核是基于AXI 4.0总线进行接口封装的,需要用户对AXI总线基础知识有所了解更优。

    (2)基于XDMA IP核进行FPGA工程开发,选择Block Design开发方式(类似于ISE原理图开发方式),当然直接通过RTL逻辑开发方式也可以,

但是各个模块的接口信号需要自己去连接,太繁琐且容易出错,不如图形化设计方便。我是参考米联客/黑金开发板教程来设计的FPGA工程,主要实现

两个功能:

a. 主机端与FPGA设备端通过DMA方式,进行数据包的发送&接收功能;

b. 主机端与FPGA设备端通过BAR方式,进行寄存器的读写功能;

(3)接口说明如下:

Bram PORTA_0(write only), Bram PORTB_0(read only)这个双向接口是DMA写数据包和回读数据包接口,这么设计而不直接用Block Ram连接,是便于用户

增加自己的逻辑:例如用户通过Bram PORTA_0写入数据包内容,然后主机端通过 Bram PORTB_0回读数据包内容。这是常见的用法,比如FPGA子卡为一个数据采集卡,需要将实时采集的视频数据组包后,通过中断方式,通知主机将已准备好的数据包回读到PC端。

3. 测试结果

    用户通过Bram PORTA_0写入数据包内容:0x07_06_05_04_03_02_01_00(每个数据为64位位宽) ~ 0xff_fe_fd_fc_fb_fa_f9_f8,循环发送,共计512个数据。

   主机通过 Bram PORTB_0回读数据包内容,然后将回读的数据写入bin文件,进行数据验证。

上图为FPGA写入的数据包内容。FPGA抓取数据点位宽设置为32位,为了节省资源。可知,数据点从0x07_06_05_04_03_02_01_00开始。

 

上图为主机端回读的数据包内容。FPGA抓取数据点位宽设置为32位,为了节省资源。可知,起始数据点从0x07_06_05_04_03_02_01_00开始,有一个时钟的延时。由于上位机写入回读数据的bin文件格式需要用Ultra Editor来打开,就不贴图了。

 


4 总结

1. 参见上图可知,Bram PORTA_0_clk该时钟信号始终为0,这一点很奇怪,理论上应该与s_axi_clk。所以我在用户逻辑部分,对Bram PORTA_0端口操作,模块时钟选择的为axi_clk总线时钟。

2. BAR地址设置:PCIE to AXI Transiation为什么设置为0x44A0_0000,是可以FPGA端随意设置,还是由PCIE驱动端与FPGA端共同商定,设置为相同的地址即可,我抽空实测一下。

    经过实测可知,BAR地址PCIE to AXI Transiation设置是可以在FPGA端任意设置的,只需各个AXI总线子模块设置的地址范围不同即可。

 

 

 

 

 

 

### XDMA传统DMA的数据传输方法差异 #### 数据传输机制对比 传统的DMA(Direct Memory Access)允许外设直接访问系统的主存储器而无需CPU干预,从而提高数据传输效率。对于Block DMA而言,在每次启动新的数据块传输之前都需要由软件配置起始地址和长度等参数[^1]。 相比之下,XDMA(eXtensible Direct Memory Access),特别是针对PCI Express接口优化后的版本,则引入了更复杂的控制结构以适应现代高速串行总线的需求。例如,在链式DMA传输中,多个描述符被用来连续地表示待传送的不连续内存区域;这些描述符组成了一张表格,并且只需向硬件提供首个描述符的位置即可触发整个序列的操作[^2]。 这种设计不仅简化了编程模型,还显著提升了处理大规模非连续缓冲区的能力以及整体吞吐量表现。 #### 寄存器级实现方式的不同 在寄存器级别上,两者也存在明显差别。普通DMA通常具有较为简单的寄存器集用于设置源/目标地址、传输字节数等功能。然而,像SGDMA这样的高级形式则拥有专门负责管理描述符列表及其他特性的额外寄存器群组,比如`SGDMA Common Register Group`就包含了对scatter-gather操作至关重要的字段定义[^3]。 因此,当涉及到复杂场景下的高效资源利用时,基于扩展型架构构建起来的XDMA显然提供了更为灵活多样的解决方案选项。 ```cpp // 示例:初始化一个典型的DMA通道配置过程 void setup_dma_channel(DMA_Channel* channel, uint32_t src_addr, uint32_t dst_addr, size_t length){ // 配置基本属性... } // 对于XDMA来说,除了常规参数之外还需要准备描述符链表 struct Descriptor { void *next; /* 下一描述符指针 */ void *src_addr; /* 源地址 */ void *dst_addr; /* 目的地地址 */ int len; /* 当前描述符所代表的数据大小 */ }; void init_xdma_descriptor_chain(Descriptor **chain_head, ...){ // 构建描述符链... } ```
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值