xdma IP使用教程1-xdma ip核配置
xdma IP使用教程1-xdma ip核配置
- 1. xdma介绍
- 2. XDMA IP核配置
- 2.1 Basic
- 2.2 PCIE ID
- 2.3 PCIE BARS
- 2.4 PCIE MISC
- 2.5 PCIE DMA
大家好,跟大家好久不见了,最近一直在忙工作上的事情,没时间顾得上更新,今天更新下xdma ip核配置使用吧。
1. xdma介绍
对于每一位涉足FPGA加速卡、数据采集卡或任何需要与CPU进行高速数据交互的开发者来说,PCIe通信是必须跨越的一道坎。而Xilinx提供的XDMA IP核,正是帮助我们跨越这道坎的“瑞士军刀”。
它封装了PCIe的复杂性,提供了简单易用的AXI流或内存映射接口,直接对接用户逻辑。通过成熟的驱动程序,开发者可以像读写本地内存一样操作FPGA侧的缓存,实现极高吞吐量的DMA传输。
本博客旨在成为您上手XDMA的实用手册。我们将聚焦于工程实践,跳过繁冗的理论,直击配置要点、驱动调用和常见的“坑”,助您快速、高效地将XDMA集成到您的项目中,解决实实在在的数据传输难题。
2. XDMA IP核配置
首先,先找到xdma ip,打开IP Catelog,搜索XDMA,在PCIE选项卡下有一项DMA/Bridge Subsystem for PCI Express,这就是xdma。
打开xdma ip核,如图所示。
2.1 Basic
第一页配置如下:
重点关心以下几项:
Lane width:链路数,也就是我们经常说的几lane
参考时钟:一般为100mhz
axi数据宽度:64或128位
DMA通道接口:AXI-mm或axi-stream
其他选项默认即可。
2.2 PCIE ID
第二页配置如下:
重点关心以下几项:
- 设备ID:
- 厂商ID
2.3 PCIE BARS
第三页配置如下:
当数据宽度选择32位时,可选择3个bar寄存器,分别为bar0,bar1,bar2,对应的通道为DMA通道(这是默认通道),PCIE axi-lite通道和DMA旁路通道。
- PCIE to AXI translation:表示pcie的寄存器地址与axi的对应地址。举个例子,我们设置该值为0x00010000,当pcie的bar1空间地址为0时,对应axi-lite接口上的地址为0x00010000。同理,DMA bypass的地址也是一样。
2.4 PCIE MISC
第四页配置如下:
- Number of user interpts request(1-16):中断,最大支持16个中断;
- legacyinterupt setting:可以选择INTA,但一般选择MSI或者MSI-X
注意:MSI和MSI-X不能同时勾选,否则会报错。
其他的默认即可,没什么影响。
2.5 PCIE DMA
第五页主要配置DMA通道,其配置如下:
- DMA读通道数(H2C):1
- DMA写通道数(C2H):1
- 读通道请求ID数:32 (范围2-64)
- 写通道请求ID数:16 (范围2-32)
- AXI ID宽度:4
- 读bypass的描述符:0000
- 写bypass的描述符:0000
好了,XDMA IP已经配置完成了,是不是非常简单,那么配置完成了,再生成下IP核,就可以使用了。我们来看看例化后的接口。
xdma_0 your_instance_name (.sys_clk(sys_clk), // input wire sys_clk.sys_rst_n(sys_rst_n), // input wire sys_rst_n.user_lnk_up(user_lnk_up), // output wire user_lnk_up.pci_exp_txp(pci_exp_txp), // output wire [0 : 0] pci_exp_txp.pci_exp_txn(pci_exp_txn), // output wire [0 : 0] pci_exp_txn.pci_exp_rxp(pci_exp_rxp), // input wire [0 : 0] pci_exp_rxp.pci_exp_rxn(pci_exp_rxn), // input wire [0 : 0] pci_exp_rxn.axi_aclk(axi_aclk), // output wire axi_aclk.axi_aresetn(axi_aresetn), // output wire axi_aresetn.usr_irq_req(usr_irq_req), // input wire [0 : 0] usr_irq_req.usr_irq_ack(usr_irq_ack), // output wire [0 : 0] usr_irq_ack.msi_enable(msi_enable), // output wire msi_enable.msi_vector_width(msi_vector_width), // output wire [2 : 0] msi_vector_width.m_axi_awready(m_axi_awready), // input wire m_axi_awready.m_axi_wready(m_axi_wready), // input wire m_axi_wready.m_axi_bid(m_axi_bid), // input wire [3 : 0] m_axi_bid.m_axi_bresp(m_axi_bresp), // input wire [1 : 0] m_axi_bresp.m_axi_bvalid(m_axi_bvalid), // input wire m_axi_bvalid.m_axi_arready(m_axi_arready), // input wire m_axi_arready.m_axi_rid(m_axi_rid), // input wire [3 : 0] m_axi_rid.m_axi_rdata(m_axi_rdata), // input wire [63 : 0] m_axi_rdata.m_axi_rresp(m_axi_rresp), // input wire [1 : 0] m_axi_rresp.m_axi_rlast(m_axi_rlast), // input wire m_axi_rlast.m_axi_rvalid(m_axi_rvalid), // input wire m_axi_rvalid.m_axi_awid(m_axi_awid), // output wire [3 : 0] m_axi_awid.m_axi_awaddr(m_axi_awaddr), // output wire [63 : 0] m_axi_awaddr.m_axi_awlen(m_axi_awlen), // output wire [7 : 0] m_axi_awlen.m_axi_awsize(m_axi_awsize), // output wire [2 : 0] m_axi_awsize.m_axi_awburst(m_axi_awburst), // output wire [1 : 0] m_axi_awburst.m_axi_awprot(m_axi_awprot), // output wire [2 : 0] m_axi_awprot.m_axi_awvalid(m_axi_awvalid), // output wire m_axi_awvalid.m_axi_awlock(m_axi_awlock), // output wire m_axi_awlock.m_axi_awcache(m_axi_awcache), // output wire [3 : 0] m_axi_awcache.m_axi_wdata(m_axi_wdata), // output wire [63 : 0] m_axi_wdata.m_axi_wstrb(m_axi_wstrb), // output wire [7 : 0] m_axi_wstrb.m_axi_wlast(m_axi_wlast), // output wire m_axi_wlast.m_axi_wvalid(m_axi_wvalid), // output wire m_axi_wvalid.m_axi_bready(m_axi_bready), // output wire m_axi_bready.m_axi_arid(m_axi_arid), // output wire [3 : 0] m_axi_arid.m_axi_araddr(m_axi_araddr), // output wire [63 : 0] m_axi_araddr.m_axi_arlen(m_axi_arlen), // output wire [7 : 0] m_axi_arlen.m_axi_arsize(m_axi_arsize), // output wire [2 : 0] m_axi_arsize.m_axi_arburst(m_axi_arburst), // output wire [1 : 0] m_axi_arburst.m_axi_arprot(m_axi_arprot), // output wire [2 : 0] m_axi_arprot.m_axi_arvalid(m_axi_arvalid), // output wire m_axi_arvalid.m_axi_arlock(m_axi_arlock), // output wire m_axi_arlock.m_axi_arcache(m_axi_arcache), // output wire [3 : 0] m_axi_arcache.m_axi_rready(m_axi_rready) // output wire m_axi_rready
);