ZYNQ ZCU102 SPI 接口实战:从MIO/EMIO选择到PS-PL协同自测

张开发
2026/4/18 21:20:28 15 分钟阅读

分享文章

ZYNQ ZCU102 SPI 接口实战:从MIO/EMIO选择到PS-PL协同自测
1. ZYNQ ZCU102 SPI接口开发全景解读第一次接触ZYNQ ZCU102的SPI接口时我和大多数工程师一样被MIO、EMIO、AXI_GPIO这些术语搞得晕头转向。这块评估板上的SPI控制器就像个多面手既可以通过PS端直接控制又能通过PL端灵活扩展但每种方式背后都藏着不同的硬件架构和设计哲学。ZCU102作为Xilinx的旗舰级评估平台其SPI接口的独特之处在于PS和PL的深度协同。PS端内置两个全功能SPI控制器最高支持50MHz时钟频率支持主从模式切换这在嵌入式领域相当实用。但真正让人又爱又恨的是它的扩展能力——通过EMIO可以将PS的SPI信号路由到PL侧再利用FPGA的可编程特性实现定制化功能。我在去年一个工业传感器项目中就利用这个特性在PL端添加了CRC校验模块完美解决了长距离传输的数据完整性问题。这里有个新手容易忽略的关键点ZYNQ的SPI控制器信号线数量会让人困惑。传统SPI只有4根线SCLK/MOSI/MISO/SS但ZCU102的EMIO接口会引出多达14根信号多出来的信号包括二次片选、中断请求、总线占用指示等高级功能信号。实际使用时如果只需要基础SPI功能只需连接核心的6根线即可其他信号可以悬空但必须在Vivado中正确配置。2. MIO/EMIO/AXI_GPIO三大接口深度对比2.1 MIOPS端的直连高速通道MIO(Multiuse I/O)是PS端的原生外设接口就像电脑主板上的原生USB接口。在ZCU102上54个MIO引脚可以直接连接SPI、I2C、UART等外设。我实测过MIO模式的SPI传输延迟能控制在10ns以内这是性能最优的方案。但MIO有两个致命限制引脚数量固定ZCU102只有54个且物理位置不可变。这就好比你的笔记本电脑只有3个USB口而且位置都在右侧用起来会很局促。具体到SPI应用MIO模式适合以下场景需要极致性能的场合外设数量较少且接口固定不需要PL端参与信号处理配置MIO时有个小技巧在Vivado的ZYNQ IP配置界面找到PS-PL Configuration PS Peripheral I/O Peripherals SPI0/SPI1勾选所需模式后下方会显示可用的MIO引脚组合。建议优先选择标注Recommended的组合这些经过官方验证最稳定。2.2 EMIO突破引脚限制的魔法当MIO不够用时EMIO(Extended MIO)就是救星。它本质上是通过PL端的可编程逻辑扩展出的虚拟MIO就像给电脑加了个USB扩展坞。在ZCU102上我经常用EMIO模式实现多路SPI设备控制——PS端SPI控制器PL端逻辑切换可以轻松管理8个以上SPI从设备。但EMIO有三大陷阱需要注意信号完整性PL端的走线延迟会比MIO大很多实测EMIO模式SPI时钟超过25MHz就会出现波形畸变管脚约束必须严格遵循开发板原理图比如ZCU102的Bank65/66只能支持1.8V电平信号线数量EMIO会引出全部14根SPI信号线但实际可能只需要其中6根这里分享一个血泪教训有次我忘记在约束文件中设置EMIO信号的IO Standard结果SPI通信随机出错。后来发现ZCU102的PL Bank电压是1.8V而我的约束文件默认是3.3V电平不匹配导致信号阈值异常。2.3 AXI_GPIOPL端的灵活之选AXI_GPIO则是完全不同的技术路线它通过AXI总线将PS端的控制指令传输到PL端由FPGA逻辑模拟SPI协议。这种方式最灵活但性能也最低。在我的测试中AXI_GPIO模拟的SPI时钟很难超过10MHz。适用场景包括需要非标准SPI时序要兼容老旧设备协议PL端已有相关处理逻辑性能对比表格特性MIOEMIOAXI_GPIO最大时钟频率50MHz25MHz10MHz延迟10ns15-30ns50ns引脚灵活性固定可编程完全自定义开发难度简单中等复杂典型用途高速设备多设备扩展特殊协议3. EMIO模式SPI全流程实战3.1 Vivado硬件平台搭建新建工程时务必选择ZCU102开发板预设模板能自动配置正确的芯片型号和时钟架构。在Block Design中添加ZYNQ Ultrascale MPSoC IP后重点配置以下参数在PS-PL Configuration中启用SPI0将SPI0 Mode设置为Master勾选SPI0 EMIO选项在Clock Configuration中确保SPI0参考时钟使能这时会看到14根EMIO信号线被引出包括spi0_sclk_outspi0_mosi_ospi0_miso_ispi0_ss_o[0:2]spi0_ss1_ospi0_ss2_o以及其他控制信号关键技巧即使只使用基础SPI功能也必须将所有输出信号(包括未使用的片选)分配到PL引脚否则生成比特流时会报错。我在早期项目中就踩过这个坑浪费了半天查错。3.2 管脚约束与硬件生成根据ZCU102原理图选择PL端的Bank65或Bank66的引脚支持1.8V电平。示例约束语句set_property PACKAGE_PIN AE12 [get_ports spi0_sclk_out] set_property IOSTANDARD LVCMOS18 [get_ports spi0_sclk_out] set_property PACKAGE_PIN AF12 [get_ports spi0_mosi_o] set_property IOSTANDARD LVCMOS18 [get_ports spi0_mosi_o] ...生成HDL Wrapper时选择Let Vivado manage wrapper and auto-update这样后续修改设计时会更方便。综合完成后务必检查时序报告中的SPI信号是否满足要求特别是建立保持时间。3.3 SDK软件编程要点在Vivado导出硬件后启动Xilinx SDK创建应用工程。关键代码结构如下#include xspi.h #include xspi_l.h #define SPI_DEVICE_ID XPAR_XSPI_0_DEVICE_ID static XSpi SpiInstance; int SpiInit() { XSpi_Config *ConfigPtr; ConfigPtr XSpi_LookupConfig(SPI_DEVICE_ID); if (ConfigPtr NULL) return XST_FAILURE; int Status XSpi_CfgInitialize(SpiInstance, ConfigPtr, ConfigPtr-BaseAddress); if (Status ! XST_SUCCESS) return XST_FAILURE; // 设置为主模式 XSpi_SetOptions(SpiInstance, XSP_MASTER_OPTION); XSpi_SetSlaveSelect(SpiInstance, 0x01); // 选择从设备0 // 启用SPI接口 XSpi_Enable(SpiInstance); return XST_SUCCESS; } void SpiTransfer(u8 *SendBuf, u8 *RecvBuf, int ByteCount) { XSpi_Transfer(SpiInstance, SendBuf, RecvBuf, ByteCount); }调试时强烈建议使用ILA集成逻辑分析仪抓取SPI信号波形。添加ILA IP时要监控以下信号spi0_sclk_outspi0_mosi_ospi0_miso_ispi0_ss_o[0]4. PS-PL协同调试技巧4.1 回环测试方案最可靠的验证方法是硬件回环将MOSI与MISO短接这样发送的数据会被原样返回。在ZCU102上可以用跳线帽连接J51扩展口的对应引脚。测试代码示例u8 TestPattern[] {0xAA, 0x55, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20}; u8 ReceiveBuffer[8]; int main() { if (SpiInit() ! XST_SUCCESS) { xil_printf(SPI Init Failed!\r\n); return -1; } SpiTransfer(TestPattern, ReceiveBuffer, 8); for (int i 0; i 8; i) { if (TestPattern[i] ! ReceiveBuffer[i]) { xil_printf(Mismatch at byte %d: Sent 0x%02X, Received 0x%02X\r\n, i, TestPattern[i], ReceiveBuffer[i]); return -1; } } xil_printf(SPI Loopback Test Passed!\r\n); return 0; }4.2 常见故障排查无数据返回检查物理连接确保MISO线正确连接用示波器检查SCLK信号是否正常确认片选信号在传输期间保持有效数据错位检查SPI模式(CPOL/CPHA)设置确认时钟极性配置与从设备匹配调整SDK代码中的时钟分频参数随机错误检查电源稳定性SPI对电源噪声敏感缩短走线长度或降低时钟频率在PL端添加输入延迟约束记得保存寄存器快照当出现异常时通过XSpi_GetStatus()和XSpi_ReadReg()获取控制器内部状态这比盲目猜测高效得多。

更多文章