本帖最后由 FPGA课程 于 2024-9-18 10:05 编辑
软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
1概述本方案基于XDMA IP搭建FPGA工程,并且以本课中已经编译好的驱动和测试程序为演示demo。 本方案内容作为通用的教程内容,适合XILINX各类支持PCIE通信的板卡。并且米联客在XDMA中使用了自己编写的FDMA控制IP,可以简单方便的完成数据之间的交换。 2系统构架本系统中演示的关键在于我们编写了一个uixdmairq的IP。该用来配合驱动处理中断,uixdmairq提供了AXI-LITE接口,上位机通过访问user空间地址读写uixdmairq的寄存器。该IP在user_irq_req_i输入的中断位,寄存中断位号,并且输出给XDMA IP ,当上位机的驱动响应中断的时候,在中断里面写uixdmairq 的寄存器,清除已经处理的中断。 另外本方案中通过AXI-BRAM来演示用户user空间的读写访问测试。
3XMDA概述Xilinx 提供的DMASubsystem for PCIExpressIP是一个高性能,可配置的适用于PCIE2.0,PCIE3.0的SG 模式 DMA,提供用户可选择的 AXI4 接口或者 AXI4-Stream接口。一般情况下配置成 AXI4 接口可以加入到系统总线互联,适用于大数据量异步传输,通常情况都会使用到 DDR,AXI4-Stream 接口适用于低延迟数据流传输。 XDMA 是SGDMA,并非Block DMA,SG 模式下,主机会把要传输的数据组成链表的形式,然后将链表首地址通过BAR 传送给XDMA,XDMA 会根据链表结构首地址依次完成链表所指定的传输任务。
AXI4、AXI4-Stream,必须选择一个,用于数据传输 AXI4-Lite Master可选,用于实现PCIE BAR地址到AXI4-lite 寄存器地址的映射,可以用于读写用户逻辑寄存器。 AXI4-Lite Slave可选,用来将XDMA 内部寄存器开放给用户逻辑,用户逻辑可以通过此接口访问 XDMA 内部寄存器,不会映射到BAR。 AXI4 Bypass接口,可选,用来实现PCIE 直通用户逻辑访问,可用于低延迟数据传输。 4基于XDMA的PCIE FPGA工程搭建
4.1XDMA IP配置
1:添加XDMA IP核
2:配置XDMA IP
双击XDMA IP进行配置 Mode:配置模式,选择 BASE配置 Lane Width:选择PCIE的通道数量对于MZ7035FC为8个通道,每个开发板支持通道数量不一样,通道数量越多通信速度越快,用户需要根据硬件的实际通达数量选择正确的通道数。 Max Link Speed:选择5.0GT/s 即PCIE2.0,对于ultrascale或者ultrascale+的FPGA可以支持PCIE3.0实现更高速度Reference Clock :100MHZ,参考时钟 100M DMA Interface Option:接口选择 AXI4 接口 AXI Data Width:128bit,即 AXI4 数据总线宽度为128bit AXI Clock :250M,即AXI4 接口时钟为250MHZ DMA Interface option 设置为AXI Memory Mapped方式
PCIE ID 配置,这里选择默认的配置就可以,默认的设备类型是Simple communication controllers
PCIE BAR 配置,这里面的配置比较重要,首先使能 PCIE to AXI Lite Master Interface ,这样可以在主机一侧通过PCIE 来访问用户逻辑侧寄存器或者其他 AXI4-Lite 总线设备映射空间选择 1M,当然用户也可以根据实际需要来自定义大小。 PCIE to AXI Translation:这个设置比较重要,通常情况下,主机侧PCIE BAR 地址与用户逻辑侧地址是不一样的, 这个设置就是进行BAR 地址到AXI 地址的转换,比如主机一侧 BAR 地址为0,IP 里面转换设置为0x44A00000, 则主机访问 BAR 地址 0 转换到AXI LIte 总线地址就是0x44A00000
PCIE to DMA Interface :选择64bit 使能
DMA Bypass 暂时不用
PCIE 中断设置
User Interrupts:用户中断,XDMA提供16条中断线给用户逻辑,这里面可以配置使用几条中断线。
Legacy Interrupt:XDMA支持Legacy中断,我们这么不选
MSI Capabilities:选择支持MSI中断 ,支持4个中断消息向量
注意:MSI 中断和 MSI-X 中断只能选择一个,否则会报错,如果选择了 MSI 中断,则可以选择 Legacy 中断, 如果选择了 MSI-X 中断,那么 MSI 必须取消选择,同时Legacy 也必须选择None。此 IP 对于7 系列设置有这个问题,如果使用Ultrascale 系列,则可以全部选择
MSI-X Capabilities:不选
Miscellaneous:选Extended Tag Field
Link Status Register:选Enable Slot Clock Configuration
配置DMA 相关内容
Number of DMA Read Channel(H2C)和Number of DMA Write Channel(C2H)通道数,对于PCIE2.0 来说最大只能选择2,也就是 XDMA 可以提供最多四个独立的写通道和四个独立的读通道,独立的通道对于实际应用中有很大的作用,在带宽允许的前提前,一个PCIE 可以实现多种不同的传输功能,并且互不影响。这里我们选择2 Number of Request IDs for Read (Write)channel :这个是每个通道设置允许最大的 outstanding 数量,按照默认即可
4.2完成自动连线
配置完成以后,点击 Run Block Auto,可以看到之前的配置信息,如果有发现和目标配置不一样的,需要手动 修改,点击 OK,完成配置。
配置完成后,VIVADO会自动进行必要的连线
到此为止,XDMA IP 配置就完成了。为了让XDMA和上位机可以密切配和工作,我们还要继续搭建其他部分的功能模块。 4.3基于图形设计的XDMA工程
4.4添加中断测试代码- `timescale 1ns / 1ps
- /*******************************MILIANKE*******************************
- *Company : MiLianKe Electronic Technology Co., Ltd.
- *WebSite:https://www.milianke.com
- *TechWeb:https://www.uisrc.com
- *tmall-shop:https://milianke.tmall.com
- *jd-shop:https://milianke.jd.com
- *taobao-shop1: https://milianke.taobao.com
- *Create Date : 2021/10/15
- *File Name : pcie_top.v
- *Description :
- *Declaration :
- *The reference demo provided by Milianke is only used for learning.
- *We cannot ensure that the demo itself is free of bugs, so users
- *should be responsible for the technical problems and consequences
- *caused by the use of their own products.
- *Copyright: Copyright (c) MiLianKe
- *All rights reserved.
- *Revision : 1.0
- *Signal description
- *1) _i input
- *2) _o output
- *3) _n activ low
- *4) _dg debug signal
- *5) _r delay or register
- *6) _s state mechine
- *********************************************************************/
- module pcie_top
- (
- output [14:0]DDR3_addr,
- output [2:0]DDR3_ba,
- output DDR3_cas_n,
- output [0:0]DDR3_ck_n,
- output [0:0]DDR3_ck_p,
- output [0:0]DDR3_cke,
- output [0:0]DDR3_cs_n,
- output [7:0]DDR3_dm,
- inout [63:0]DDR3_dq,
- inout [7:0]DDR3_dqs_n,
- inout [7:0]DDR3_dqs_p,
- output [0:0]DDR3_odt,
- output DDR3_ras_n,
- output DDR3_reset_n,
- output DDR3_we_n,
- input sysclk_p,
- input sysclk_n,
- input [7 :0]pcie_mgt_rxn,
- input [7 :0]pcie_mgt_rxp,
- output [7 :0]pcie_mgt_txn,
- output [7 :0]pcie_mgt_txp,
- input [0 :0]pcie_ref_clk_n,
- input [0 :0]pcie_ref_clk_p,
- input pcie_rst_n
- );
- wire sysclk;
- IBUFDS CLK_U(.I(sysclk_p),.IB(sysclk_n),.O(sysclk));
- wire axi_aclk;
- wire user_irq_en_o;
- reg [21:0]timer_cnt;
- reg timer_r1,timer_r2;
- reg [1:0]int_p;
- reg [3:0]user_irq_req_i;
- wire inter = !timer_r2 && timer_r1;
- always @(posedge axi_aclk)begin
- if(user_irq_en_o == 1 'b0)begin
- timer_cnt <= 22 'd0;
- end
- else begin
- timer_cnt <= timer_cnt + 1 'b1;
- end
- end
- always @(posedge axi_aclk)begin
- if(user_irq_en_o == 1 'b0)begin
- timer_r1 <= 1 'd0;
- timer_r2 <= 1 'd0;
- end
- else begin
- timer_r1 <= timer_cnt[20];
- timer_r2 <= timer_r1;
- end
- end
- always @(posedge axi_aclk)begin
- if(user_irq_en_o == 1 'b0)begin
- int_p[1:0] <= 4 'd0;
- user_irq_req_i <= 4 'd0;
- end
- else begin
- if(inter) int_p <= int_p + 1 'b1;
- user_irq_req_i <= 4 'd0;
- user_irq_req_i[int_p] <= 1 'b1;
- end
- end
- pcie_system pcie_system_i(
- .DDR3_addr(DDR3_addr),
- .DDR3_ba(DDR3_ba),
- .DDR3_cas_n(DDR3_cas_n),
- .DDR3_ck_n(DDR3_ck_n),
- .DDR3_ck_p(DDR3_ck_p),
- .DDR3_cke(DDR3_cke),
- .DDR3_cs_n(DDR3_cs_n),
- .DDR3_dm(DDR3_dm),
- .DDR3_dq(DDR3_dq),
- .DDR3_dqs_n(DDR3_dqs_n),
- .DDR3_dqs_p(DDR3_dqs_p),
- .DDR3_odt(DDR3_odt),
- .DDR3_ras_n(DDR3_ras_n),
- .DDR3_reset_n(DDR3_reset_n),
- .DDR3_we_n(DDR3_we_n),
- .pcie_mgt_rxn(pcie_mgt_rxn),
- .pcie_mgt_rxp(pcie_mgt_rxp),
- .pcie_mgt_txn(pcie_mgt_txn),
- .pcie_mgt_txp(pcie_mgt_txp),
- .pcie_ref_clk_n(pcie_ref_clk_n),
- .pcie_ref_clk_p(pcie_ref_clk_p),
- .pcie_rst_n(pcie_rst_n),
- .axi_aclk(axi_aclk),
- .user_irq_en_o(user_irq_en_o),
- .user_irq_req_i(user_irq_req_i),
- .sysclk(sysclk)
- );
- endmodule
复制代码
进行地址分配:
这里我们把挂在M_AXI上的DDR地址分配从0开始(对于widnows系统必须为0),M_AXI是需要进行DMA操作的。而M_AXI_LITE挂载的BRAM和uixdmairq中断控制单元是映射到用户BAR地址空间,这个地址就是前面我们XDMA IP里面设置的地址。默认情况下,需要设置uixdmairq中断控制单元的地址和XDMA里面设置的用户BAR地址空间一致。如下图0x44A0_0000。BRAM的地址空间0x44A01_0000。关于地址空间的具体含义,结合软件的使用会更加清晰,初学者暂且根据教程设置。
5硬件安装注意确保TF卡里面没有程序吗,或者拔掉TF卡。 先下载程序,调试阶段下载bit文件,然后再开电脑。这样才能正确识别和后续测试工作正常开展。
6编译安装驱动1.修改驱动,找到xdma-core.c的第4657行,将原来的:
- rc = pci_enable_msix(pdev, lro->entry, req_nvec);
修改为:
- #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
- rc = pci_enable_msix(pdev, lro->entry, req_nvec);
- #else
- rc = pci_enable_msix_range(pdev, lro->entry, req_nvec, req_nvec);
- #endif
2.修改驱动,找到xdma-core.c的第1016行,将原来的: 修改为:
- #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 1, 0)
- mmiowb();
- #endif
3.修改驱动,找到xdma-core.c的第1675、1683行,修改为下图所示:
4.驱动编译(本课APP_linux下的驱动是已经修改好的)
在准备加载驱动前,确保你的开发板已经下载PCIE工程的bit文件,而且已经重启过电脑。好了,现在加载驱动。
(每一次下载程序后重启都要再重新加载驱动,后面课程就不在说明)
7应用程序测试1.在终端执行命令:
./dma_from_device -d /dev/xdma0_c2h_0 -f ./test.bin -s 4096 -a 0 -c 1
./dma_to_device -d /dev/xdma0_h2c_0 -f ./test.bin -s 4096 -a 0 -c 1
-d:device 设备.
-f:file 文件
-s:size 大小
-a:addr 起始地址
-c:count
这两个操作分别是从板卡读 4096 Bytes 数据到文件 test.bin 以及从 test.bin 读出4096 Bytes 数据发送给板卡。
2.xdma中断测试
打开终端,输入以下命令: sudo ./pcie_irq
可以看到运行结果是 4 个中断事件,实际上 XMDA 最大支持 16 个中断事件。更多的中断时间可以更好的发挥
CPU 多核多线程的性能。
好了,到此 XDMA 的 PCIE 方案核心内容就已经讲完了。XILINX 官方给的资料往往没有细化,我们米联客已经对以上驱动稍加修改,以更好的支持中断。
|