PCIe XDMA数据传输:三种工作模式详解(ARM发起 → FPGA自主)
1 引言
在使用Xilinx XDMA IP核进行PCIe高速数据传输时,很多工程师会问一个问题:FPGA能否主动发起数据传输? 答案是:当然可以! 但这里面的“主动”有不同的层次和实现方式。
本文将结合我们实际调试的经验和Xilinx官方手册PG195,详细讲解XDMA C2H(Card to Host,即FPGA到主机)传输的三种工作模式
2 ARM发起:标准AXI4-MM模式
这是我们之前调试时最常用的方式,也是XDMA最经典的用法。
2.1 工作原理
ARM(主机驱动)提交C2H描述符,明确指定:从FPGA的哪个地址读多少字节,放到主机的哪个缓冲区。
XDMA作为Master,主动去读取FPGA侧RAM中的数据。
FPGA端的XDMA接口必须配置为AXI4-MM(内存映射)模式,XDMA作为Master,后面的RAM作为Slave。
配置见下图:
2.2 数据传输流程
ARM驱动创建描述符链表,写入寄存器启动DMA。
H2C方向,XDMA通过AXI4写通道将数据写入FPGA RAM
当FPGA有数据要传给驱动端,数据会被先放在FPGA的RAM中,然后以中断的方式通知驱动。
驱动收到中断后,通过AXI4读通道从RAM读取数据(C2H方向)。
整个传输由ARM主动发起,FPGA始终处于被动响应状态,数据必须先存放在RAM中,ARM发起读请求才能取走。
2.3 仿真验证
从仿真波形可以看到,AXI4写通道和读通道是分开的,数据需要先存入RAM,等待读请求到来才能输出。
3 FPGA主动触发:AXI4-Stream模式
严格意义上,这种模式不能叫“FPGA发起”,因为DMA的配置(描述符、目的地址等)仍然由ARM提前完成。但FPGA确实可以主动把数据放到总线上,而不需要等待ARM逐个发读请求。
3.1 工作原理
ARM驱动提前配置好C2H通道的描述符和主机缓冲区,然后启动DMA引擎,使其处于“待命”状态。
FPGA内部的用户逻辑将数据直接推送到AXI4-Stream接口上。
XDMA检测到Stream接口上有有效数据后,自动将数据搬运到主机预先指定的缓冲区。
当数据量达到描述符设定的长度后,XDMA发送中断通知主机。
此时XDMA必须作为Slave端使用,因此其用户侧接口必须配置为AXI4-Stream模式。
3.2 仿真验证
从仿真图可以清晰看到:M_AXIS_H2C收到数据后,S_AXIS_C2H立即将数据转发出去,几乎没有延迟。这是因为驱动已经提前配置好了目的地址,XDMA硬件可以自主完成后续搬运。
4 绝对的FPGA发起:Descriptor Bypass模式
前两种模式本质上是ARM决定传输参数(源地址、目的地址、数据长度),FPGA只是被动执行或“半自动”触发。那么,有没有办法让FPGA完全自主决定一次DMA传输的所有细节呢?
有!这就是Descriptor Bypass模式。
4.1 工作原理
在Vivado中配置XDMA IP时,勾选“Descriptor Bypass for Write (C2H)”或“Descriptor Bypass for Read (H2C)”。
使能后,XDMA会多出两组接口:
c2h_dsc_byp_*和h2c_dsc_byp_*。FPGA内部的用户逻辑通过这组接口,动态构建并提交一个完整的描述符,包括:
主机目的地址(64位)
FPGA源地址(64位,对于Stream接口可能无效)
传输长度(32位)
控制标志(停止、相邻描述符数量等)
FPGA给一个
load脉冲,XDMA接收这个描述符后,立即按照描述符的要求发起一次DMA传输。
配置如下图所示:
4.2 仿真验证
从仿真波形可以看到,FPGA先向描述符Bypass接口写入地址、长度等信息,然后拉高load信号,随后XDMA即开始执行对应的数据传输。
官方手册参考
详细的时序和寄存器定义请参考 PG195
5 官方驱动与测试脚本对应关系
Xilinx官方提供的Linux驱动仓库位于:
https://github.com/Xilinx/dma_ip_drivers/tree/master/XDMA/linux-kernel/tests
其中包含的测试脚本与上述三种模式的对应关系如下:
| 工作模式 | 对应测试脚本 | 说明 |
|---|---|---|
| 模式一:ARM发起(AXI4-MM) | dma_memory_mapped_test.sh | 这也是我们之前测试用的脚本 |
| 模式二:FPGA主动触发(AXI4-Stream) | dma_streaming_test.sh | 用于验证Stream模式下的自动数据泵 |
| 模式三:Descriptor Bypass | 无独立脚本,需手动修改 | 可通过修改dma_streaming_test.sh,使能Bypass功能(需要设置对应寄存器) |
6 总结
回到最初的问题:FPGA能否主动发起PCIe传输?
在标准AXI4-MM模式下:FPGA是被动的,传输由ARM发起。
在AXI4-Stream模式下:FPGA可以“主动”把数据推上总线,但传输参数仍由ARM预设,可视为半主动。
在Descriptor Bypass模式下:FPGA可以完全自主决定源地址、目的地址和数据长度,是真正的主动发起。
选择哪种模式取决于你的应用需求:
如果你需要按需读取FPGA RAM中的块数据,用模式一。
如果你需要连续、高速的数据流上传,用模式二。
如果你需要动态、灵活的DMA控制,用模式三。
希望这篇文章能帮助你理清XDMA C2H传输的几种方式,并在实际项目中灵活选用。
