ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vivado中AXI Memory Mapped to PCIe IP核实战指南:从配置到调试

Vivado中AXI Memory Mapped to PCIe IP核实战指南:从配置到调试 1. 为什么要在 Vivado 里折腾 AXI Memory Mapped to PCI Express如果你手头有一块带 PCIe 硬核的 FPGA 开发板又恰好需要让上位机Host能像读写本地内存一样直接访问 FPGA 内部的寄存器或 BRAM那AXI Memory Mapped to PCI Express IP核基本就是你绕不开的一个东西。Xilinx现 AMD在 Vivado 里提供的这个 IP本质上是一个协议桥一端是 PCIe 的 Transaction Layer另一端是 AXI4 的 Memory Mapped 接口。它把 PCIe 的 TLP 包翻译成 AXI 的读写事务反过来也一样。你不需要自己去写复杂的 PCIe 事务层逻辑只要把 AXI 接口接到你的用户逻辑上Host 侧通过 BAR 空间映射就能直接访问。这个 IP 解决的核心问题是地址映射与协议转换。PCIe 和 AXI 是两套完全不同的总线协议PCIe 是包传输、基于 TLP、有复杂的配置空间和 BAR 机制AXI4 是通道分离、带突发长度和 ID 标记的片上总线。如果没有这个桥你得手动处理 TLP 解析、地址译码、读写通道握手工作量巨大且极易出错。用了这个 IP 之后你只需要关心 AXI 侧的时序和地址分配PCIe 侧的链路训练、配置空间枚举都由 IP 和 Host 的枚举流程自动完成。适合读这篇内容的人有一定 Vivado 使用基础、了解 AXI4 协议基本握手、正在做 PCIe 数据采集卡或加速卡项目的 FPGA 工程师。如果你连 AXI 的 VALID/READY 都没搞明白建议先去补一下 AXI4 的基础否则后面调起来会很痛苦。2. IP核的核心架构与关键参数拆解2.1 内部结构到底长什么样这个 IP 的内部并不是一个简单的协议转换器它包含几个关键模块PCIe 集成块调用硬核或软核、AXI 桥接逻辑、配置管理单元、以及BAR 地址译码与命中逻辑。当你例化这个 IP 时Vivado 会根据你选的 PCIe 配置Gen1/Gen2/Gen3、x1/x2/x4/x8、Root Port 还是 Endpoint生成对应的硬核包装。数据流向是这样的Host 发起一个 Memory Read/Write TLP经过 PCIe 链路到达 FPGA 硬核硬核把 TLP 交给 IP 内部的 AXI 桥。桥接逻辑解析 TLP 的地址判断命中哪个 BAR然后转换成 AXI4 的读或写事务发到 AXI 接口上。反过来AXI 侧的响应数据被封装回 Completion TLP 发回 Host。整个过程对用户逻辑透明你只需要在 AXI 侧响应读写请求就行。注意这个 IP 只支持 AXI4 Memory Mapped 接口不支持 AXI Stream。如果你需要流式数据传输得用 AXI DMA 或者 AXI Stream 到 Memory Mapped 的转换器。2.2 关键参数怎么选在 Vivado 的 IP 配置界面里有几个参数直接决定了你后续能不能跑通PCIe 配置方面Device/Port Type 选 Endpoint绝大多数场景Link Speed 根据你的板子和 Host 能力选。这里有个坑如果你选了 Gen3 x8但 Host 侧只支持 Gen2链路会协商到 Gen2不会报错但带宽减半。所以最好先确认 Host 的 PCIe 版本。Reference Clock Frequency 一般是 100MHz但有些板子用 125MHz选错了链路训练直接失败。BAR 配置方面这是最容易出问题的地方。每个 BAR 可以配置成 32 位或 64 位地址空间大小从 4KB 到 256MB 不等。我的经验是如果只是访问几个寄存器给 4KB 或 8KB 就够了如果要映射大块 BRAM 或 DDR至少给 1MB 以上。BAR 的地址空间大小必须是 2 的幂次Vivado 会自动帮你算但你得心里有数。AXI 接口方面Address Width 要和你的 BAR 空间匹配。比如你 BAR0 配了 1MB那 AXI 地址位宽至少 20 位。Data Width 一般选 64 位或 128 位取决于你的用户逻辑带宽需求。ID Width 决定了能支持多少个 Outstanding 事务默认 4 位够用但如果你的 Host 并发读写很多可以加到 6 位。参数推荐值说明Device/Port TypeEndpoint除非你做 Root PortLink SpeedGen2 x4兼容性好带宽够用Reference Clock100MHz看板子晶振BAR0 Size64KB-1MB寄存器小缓存AXI Data Width64/128匹配用户逻辑AXI ID Width4-6影响并发能力2.3 地址映射的逻辑BAR 地址映射是 Host 侧软件和 FPGA 侧硬件之间的契约。Host 在枚举时会读取 BAR 的 Size 寄存器然后分配一段物理地址给它。FPGA 侧 IP 会根据 BAR 的命中结果把 PCIe 地址转换成 AXI 地址。这里的关键是地址偏移Host 访问 BAR0 基地址 0x1000IP 会把它转换成 AXI 地址 0x1000假设 BAR0 的 AXI 基地址是 0。所以你需要在用户逻辑里按照这个偏移来分配寄存器地址。如果你有多个 BAR每个 BAR 可以映射到不同的 AXI 地址段。比如 BAR0 映射到寄存器区BAR1 映射到 BRAM 区BAR2 映射到 DDR 区。这样 Host 侧软件可以用不同的基地址来访问不同功能块逻辑清晰。3. Vivado 工程搭建与 IP 集成实操3.1 创建工程与 IP 例化打开 Vivado新建工程选好你的 FPGA 型号。这里注意不是所有 FPGA 都带 PCIe 硬核。Artix-7 部分型号有Kintex-7 和 Virtex-7 基本都有Zynq 系列要看具体型号。选错型号后面 IP 根本出不来。在 Block Design 里添加 IP搜索 AXI Memory Mapped to PCI Express。双击配置按照上一节的参数选好。配置完成后IP 会生成几个关键接口PCIe 差分对连到板子的 GT 引脚、时钟和复位、AXI 主接口连到你的用户逻辑、配置管理接口可选用于访问配置空间。实操心得在 Block Design 里连线时PCIe 的参考时钟和复位一定要接对。参考时钟一般来自板子的专用时钟芯片复位可以用 IP 输出的复位信号。如果复位极性搞反了链路训练会一直失败。3.2 时钟与复位处理这个 IP 对时钟和复位的要求比较严格。参考时钟必须是差分或单端取决于板子频率误差不能超过 ±300ppm。AXI 时钟是 IP 输出的用户时钟频率取决于 PCIe 链路速度和位宽。比如 Gen2 x4AXI 时钟一般是 125MHz 或 250MHz。复位方面IP 有一个perst_n输入来自 PCIe 插槽的复位信号还有一个user_reset输出。perst_n 是 Host 发来的全局复位必须接。user_reset 是 IP 内部逻辑复位完成后输出的可以用来复位你的用户逻辑。我一般会把 user_reset 再同步几拍确保时序稳定。// 复位同步示例 reg [2:0] rst_sync; always (posedge aclk) begin rst_sync {rst_sync[1:0], user_reset}; end wire user_rst_n ~rst_sync[2];3.3 AXI 接口连接与地址分配IP 的 AXI 主接口需要连到你的用户逻辑。如果你有多个从设备得加一个 AXI Interconnect 或者 SmartConnect。地址分配在 Address Editor 里做Vivado 会自动帮你分配但你可以手动调整。这里有个细节AXI 地址位宽和 BAR 大小的关系。假设 BAR0 配了 64KB那 AXI 地址只需要 16 位就能覆盖。但 IP 输出的 AXI 地址位宽可能是 32 位或 64 位高位补零。你在用户逻辑里做地址译码时只需要关心低位。// 简单的地址译码示例 always (posedge aclk) begin if (s_axi_awvalid s_axi_awready) begin case (s_axi_awaddr[15:12]) 4h0: reg_sel 0; 4h1: reg_sel 1; // ... endcase end end3.4 生成比特流与固化工程综合、实现、生成比特流。如果这一步报错常见原因有引脚约束不对PCIe 差分对没分配到正确的 GT 引脚、时序不满足AXI 时钟频率太高、DRC 错误比如 RTSTAT-2通常是 GT 复位没接对。生成比特流后你可以通过 JTAG 下载到 FPGA 验证。但 PCIe 设备通常需要 Host 在枚举时就能看到所以最好把比特流固化到 Flash 里让 FPGA 上电自动加载。固化步骤生成 MCS 文件用 Vivado 的 Hardware Manager 烧到 Flash。注意固化前一定要确认比特流是最终版本因为固化后修改需要重新烧录 Flash比较麻烦。4. 上位机驱动与 BAR 空间访问4.1 Host 侧识别设备FPGA 加载比特流后Host 启动时会枚举 PCIe 设备。在 Linux 下用lspci能看到设备在 Windows 下设备管理器里会出现未知设备因为没装驱动。你需要根据 Vendor ID 和 Device ID 来识别。Vendor ID 一般是 Xilinx 的 0x10EEDevice ID 可以在 IP 配置里改。如果 Host 没识别到设备先检查链路训练是否成功。在 Vivado 的 Hardware Manager 里可以看到 PCIe 链路状态LTSSM 状态应该是 L0。如果不是检查参考时钟、复位、差分对极性。4.2 BAR 空间读写测试在 Linux 下可以用devmem或者自己写一个简单的字符设备驱动来访问 BAR 空间。最简单的方法是mmapBAR 的物理地址到用户空间然后直接读写。// Linux 用户空间 mmap BAR 示例 int fd open(/sys/bus/pci/devices/0000:01:00.0/resource0, O_RDWR); void *bar0 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); uint32_t val *(volatile uint32_t *)(bar0 0x100); *(volatile uint32_t *)(bar0 0x100) 0xDEADBEEF;Windows 下需要写一个简单的 WDF 驱动或者用 WinDriver 这类工具。如果只是调试可以用 Xilinx 提供的 PCILib 或者自己写一个基于SetupDi和MmMapIoSpace的小工具。4.3 性能优化与带宽测试BAR 空间访问的带宽受限于 PCIe 链路速度和 TLP 开销。Gen2 x4 的理论带宽是 2GB/s实际能到 1.2-1.5GB/s。如果你需要更高带宽考虑用AXI DMA做块数据传输而不是单个寄存器读写。测试带宽的方法在 FPGA 侧放一个 BRAMHost 侧连续写大块数据用clock_gettime测时间。或者用 Xilinx 的AXI Traffic GeneratorIP 在 FPGA 侧产生流量Host 侧只做少量控制。实操心得如果带宽远低于预期先检查 AXI 接口的 Outstanding 能力。ID Width 太小会导致并发事务受限带宽上不去。另外Host 侧的读写顺序也会影响尽量用连续地址的大块传输。5. 常见问题与排查技巧实录5.1 链路训练失败现象Host 看不到设备Vivado Hardware Manager 里 LTSSM 状态不是 L0。排查思路检查参考时钟频率和极性用示波器量一下检查 perst_n 复位信号应该是低电平复位检查差分对引脚分配TX/RX 不能接反检查 GT 的电源和参考时钟是否正常避坑技巧有些板子的 PCIe 参考时钟是 100MHz但 IP 默认是 125MHz选错了链路训练直接失败。另外如果板子有 PCIe 时钟缓冲芯片确认它是否被正确配置。5.2 BAR 空间访问返回全 F现象Host 读 BAR 空间返回 0xFFFFFFFF。排查思路检查 BAR 是否被正确枚举lspci -v看 BAR 地址是否分配检查 AXI 接口是否有响应用 ILA 抓一下检查地址译码逻辑Host 访问的偏移是否在你的译码范围内避坑技巧如果 AXI 接口没有响应IP 会返回一个错误 CompletionHost 侧可能读到全 F。用 ILA 抓 AXI 的 VALID/READY 信号看是否有握手。5.3 时序不收敛现象Implementation 报时序违例WNS 为负。排查思路检查 AXI 时钟频率是否太高试着降频检查用户逻辑的时序路径加流水线检查 IP 的约束是否完整特别是 GT 的约束避坑技巧PCIe 的 GT 约束很复杂Vivado 会自动生成但如果你手动改了引脚分配约束可能会丢。建议用 IP 自带的 XDC 文件不要手动改。问题可能原因解决方法链路训练失败参考时钟错误检查频率和极性BAR 读全 FAXI 无响应用 ILA 抓握手信号时序违例时钟太快降频或加流水线固化后不工作Flash 配置错误检查 MCS 文件和烧录地址带宽低Outstanding 不足增加 AXI ID Width5.4 固化后设备不识别现象JTAG 下载能识别固化到 Flash 后 Host 看不到设备。排查思路检查 Flash 的烧录地址是否正确检查 FPGA 的配置模式引脚是否设置为 Master SPI检查比特流是否包含 PCIe 硬核的配置避坑技巧有些板子的 Flash 是 3.3V 的但 FPGA 配置电压是 1.8V需要电平转换。另外固化后第一次启动可能比较慢等几秒钟再枚举。6. 进阶应用与扩展思路6.1 多 BAR 映射与功能分区如果你的设计有多个功能块可以用多个 BAR 来分区。比如 BAR0 映射寄存器BAR1 映射 BRAMBAR2 映射 DDR。这样 Host 侧软件可以用不同的基地址访问逻辑清晰也方便权限管理。在 IP 配置里每个 BAR 可以独立设置大小和类型。注意 BAR 的总数有限制一般最多 6 个。如果 BAR 不够用可以用一个 BAR 映射一大块地址空间然后在 FPGA 内部做二级译码。6.2 与 AXI DMA 配合做高速数据传输BAR 空间访问适合寄存器配置和少量数据传输。如果需要高速数据采集比如 ADC 数据连续上传用AXI DMA更合适。DMA 可以在 FPGA 侧主动发起 AXI 读写把数据搬到 DDR 或 BRAM然后 Host 通过 BAR 空间读取状态寄存器知道数据准备好了再批量读取。这种架构下AXI Memory Mapped to PCI Express IP 负责 Host 和 FPGA 之间的控制通道AXI DMA 负责数据通道。两者配合既能灵活控制又能高带宽传输。6.3 调试技巧与 ILA 使用调试 PCIe 相关设计ILA是必不可少的。你可以在 AXI 接口上插 ILA抓读写事务的地址、数据、握手信号。Vivado 的 ILA 支持触发条件设置比如地址等于某个值时触发非常方便。另外Xilinx 提供了PCIe 调试工具可以在 Hardware Manager 里查看链路状态、配置空间、BAR 命中情况。如果链路训练失败这些工具能帮你快速定位问题。实操心得ILA 的采样深度有限抓大量数据时容易溢出。建议先用触发条件缩小范围或者用 AXI Traffic Generator 产生特定模式的流量方便分析。6.4 从 Gen2 升级到 Gen3 的注意事项如果你需要更高带宽可以从 Gen2 升级到 Gen3。但 Gen3 的参考时钟要求更严格一般是 100MHz 或 125MHz抖动要小。另外Gen3 的 GT 约束更复杂建议直接用 IP 生成的约束不要手动改。升级后AXI 时钟频率会提高时序收敛难度增加。可能需要加流水线或者降低用户逻辑的复杂度。带宽测试时Gen3 x4 的理论带宽是 4GB/s实际能到 2.5-3GB/s。7. 个人实操体会与建议我在多个数据采集项目里用过这个 IP踩过的坑主要集中在参考时钟配置和BAR 地址译码上。有一次板子的参考时钟是 125MHz但 IP 默认 100MHz链路训练一直失败查了半天才发现是时钟频率不对。还有一次 BAR 大小配了 4KB但用户逻辑的地址译码用了 16 位导致高位地址被忽略Host 访问越界。我的建议是先在 Block Design 里把最小系统跑通只连 PCIe 和 AXI 接口不放用户逻辑用 ILA 抓 AXI 信号确认 Host 能读写 BAR 空间。然后再逐步加功能。这样出问题容易定位。另外固化前一定要在 JTAG 模式下充分测试包括链路训练、BAR 读写、带宽测试。固化后如果出问题排查起来麻烦得多。Flash 烧录地址和配置模式也要仔细核对不同板子的 Flash 型号和容量可能不一样。最后如果你用的是 Zynq 或 Zynq MPSoCPCIe 的配置方式略有不同PS 侧需要配置 AXI 接口和中断。但核心逻辑是一样的理解了 AXI Memory Mapped to PCI Express 的工作原理迁移到其他平台也不难。
返回列表