
1. 璞致PZSDR系列板卡的整体设计思路与选型逻辑第一次拿到璞致PZSDR系列板卡的时候我下意识地先翻到背面看电源树和时钟架构因为一块SDR板卡能不能跑出标称的带宽八成取决于这两块。PZSDR系列的核心组合是ZYNQ AD9361这个搭配在业内不算新鲜但璞致把它做成了一个系列覆盖不同通道数和不同FPGA规模这就值得拆开聊聊了。1.1 为什么是ZYNQ而不是FPGA独立ARM很多人第一反应是做SDR直接用一颗大容量FPGA加一颗独立的ARM处理器不就行了逻辑上没错但实际落地时会发现几个很现实的问题。第一是接口带宽和延迟。FPGA和ARM之间如果走SPI或低速并口AD9361的采样数据要经过FPGA打包、再通过总线传给ARM做协议栈处理这个链路在窄带场景下勉强够用但一旦跑到几十兆的瞬时带宽瓶颈立刻暴露。ZYNQ的AXI HP接口直接挂在PL和PS之间的片上互联上理论带宽可以到GB/s级别AD9361的I/Q数据流通过DMA搬进DDRPS端几乎感觉不到搬运的延迟。第二是开发效率。ZYNQ的PS端是硬核ARM Cortex-A97010/7020或A53UltraScale系列跑Linux或者裸机都行。你可以在PL里做射频前端的高速采样和数字下变频在PS里跑网络协议栈、上位机通信、甚至Qt界面。这种软硬协同的模式比FPGA独立ARM的方案省掉了一整套片间通信的调试工作。第三是功耗和面积。PZSDR系列很多型号是面向便携或嵌入式场景的ZYNQ单芯片方案在PCB面积和功耗上都比双芯片方案有优势。尤其是7020这个级别PL资源够做两通道AD9361的接口逻辑和简单的DDCPS端跑个轻量级Linux绰绰有余。注意选ZYNQ不代表PL资源可以随便挥霍。AD9361的LVDS接口在双通道全速模式下会吃掉不少IO和逻辑资源如果你还要在PL里做FFT或者滤波7020可能会比较紧张这时候就要考虑更大规模的型号或者优化逻辑。1.2 AD9361在宽频射频中的角色定位AD9361这颗射频捷变收发器在业内被称为“万能射频前端”不是没有道理的。它的频率覆盖范围从70MHz到6GHz通道带宽可调支持TDD和FDD两种模式双发双收。对于PZSDR系列来说AD9361负责的是从天线到数字基带之间的所有模拟和混合信号处理。具体来说AD9361内部集成了接收链路LNA、混频器、跨阻放大器、模拟低通滤波器、ADC。ADC是12位采样率最高可以到61.44MSPS。发射链路DAC、模拟低通滤波器、混频器、PA驱动器。DAC同样是12位。频率合成器两个独立的LO分别给RX和TX支持快速跳频。自动增益控制可以在手动和自动模式之间切换AGC的响应时间可以配置。在PZSDR板卡上AD9361的配置通常通过SPI接口由ZYNQ的PS端或者PL端来完成。初始化流程涉及大量的寄存器写入这也是很多新手最容易卡住的地方。1.3 异构架构带来的实际优势把ZYNQ和AD9361放在一起最大的好处是数据流和控制流可以分开处理。AD9361的I/Q数据通过LVDS或CMOS接口进入PLPL里做数字下变频、抽取、打包然后通过DMA搬进DDR。PS端只需要从DDR里读已经处理好的基带数据做协议解析或者网络转发。控制流方面PS通过SPI配置AD9361的寄存器通过GPIO控制射频开关和增益引脚。这种分工带来的直接好处是PS端的软件工程师不需要关心射频时序PL端的逻辑工程师不需要关心网络协议。两边的接口就是AXI总线和DMA描述符边界清晰调试起来也容易定位问题。我在实际项目中遇到过一种情况AD9361的RX PLL一直锁不定同时CP OVRG HIGH被置位。这个问题如果放在FPGA独立ARM的架构里排查起来要同时看FPGA的SPI时序和ARM的驱动但在ZYNQ上我只需要在PS端用示波器抓SPI的波形确认寄存器写入是否正确然后检查AD9361的参考时钟是否稳定。最后发现是参考时钟的抖动太大换了一颗低相噪的晶振就解决了。2. 核心硬件细节与AD9361初始化实操要点2.1 电源树与时钟架构的坑PZSDR系列板卡的电源设计比较讲究AD9361对电源噪声非常敏感尤其是1.3V的模拟电源和1.8V的接口电源。璞致在板子上用了多颗LDO和DC-DC组合具体型号不同批次可能有差异但整体思路是模拟电源用LDO数字电源用DC-DC。时钟方面AD9361需要一个参考时钟通常是40MHz或者30.72MHz。这个时钟的质量直接决定了RX/TX PLL能不能锁定以及EVM能不能做上去。我实测过用普通的晶振和用低相噪的TCXO接收灵敏度能差3到5个dB。提示如果你拿到板子后发现AD9361初始化失败先别急着改代码用频谱仪或者相噪仪测一下参考时钟的相位噪声。如果10kHz偏移处的相噪差于-140dBc/HzPLL锁定的概率会明显下降。2.2 AD9361初始化流程拆解AD9361的初始化是一个比较长的寄存器写入序列官方提供了初始化脚本但直接照搬往往会出问题。我一般把初始化分成几个阶段复位和时钟使能先给AD9361一个软复位然后使能内部时钟。基带PLL配置设置BBPLL的频率通常是采样率的整数倍。RF PLL配置设置RX和TX的LO频率。通道配置设置采样率、带宽、增益模式。校准触发RX和TX的校准等待校准完成。每一步都有对应的寄存器其中最容易出问题的是RF PLL的VCO校准。如果VCO校准失败RX PLL就不会锁定同时CP OVRG HIGH会被置位。这时候读0x247寄存器往往会看到0x80这个值表示PLL锁定失败。我踩过的坑是初始化脚本里的参考时钟频率和板子上的实际晶振频率不一致。比如脚本里写的是40MHz但板子上焊的是30.72MHz结果PLL的分频比算错怎么都锁不定。后来养成习惯每次拿到新板子先用示波器测一下参考时钟的实际频率再改脚本。2.3 SPI配置的时序要求AD9361的SPI接口支持4线模式时钟极性、相位、位序都可以配置。璞致PZSDR系列通常把SPI挂在ZYNQ的PS端用Linux的spidev或者裸机SPI控制器来驱动。SPI的时钟频率不能太高AD9361的SPI最高支持50MHz但实际用下来10MHz到20MHz比较稳。如果跑太高写入的数据容易出错表现为某些寄存器读回来和写进去的值不一致。注意每次写AD9361寄存器后最好读回来确认一下。尤其是初始化阶段如果某个关键寄存器写失败后面所有的配置都会错位。我一般会在代码里加一个校验函数写完之后立即读回不匹配就报错。2.4 数据接口的LVDS与CMOS选择AD9361的数据接口可以配置成LVDS或者CMOS。LVDS的速率更高适合高采样率场景但布线要求也更高。CMOS接口简单一些但速率受限。PZSDR系列板卡通常把数据接口接到ZYNQ的PL端用SelectIO资源来接收。如果用的是LVDS模式需要在PL里做IDDR或者ISERDES来解串。如果是CMOS模式直接当普通IO处理就行。我个人的经验是如果采样率超过30.72MSPS优先用LVDS。CMOS在这个速率下数据和时钟的偏斜会变得很难调眼图容易闭合。LVDS虽然布线麻烦一点但时序余量更大。3. 从裸机到Linux的完整实操流程3.1 裸机环境下的AD9361驱动移植很多新手是从裸机开始接触ZYNQ的因为裸机没有操作系统层的干扰调试起来更直接。璞致官方通常会提供裸机版本的AD9361驱动但往往不完整需要自己补一些东西。裸机下的初始化流程大致是这样的// 伪代码示例 void ad9361_init(void) { spi_init(); // 初始化SPI控制器 ad9361_reset(); // 硬件复位 ad9361_spi_write(0x3F, 0x01); // 软复位 delay_ms(1); ad9361_spi_write(0x3F, 0x00); // 退出复位 // 配置BBPLL ad9361_spi_write(0x10, 0x00); // 设置分频比 // ... 更多寄存器配置 ad9361_calibrate(); // 触发校准 }裸机的好处是你可以用JTAG单步调试看每一个寄存器写入后的返回值。坏处是所有的延时都要自己实现而且没有文件系统配置参数改起来比较麻烦。提示裸机下调试AD9361建议先用一个简单的SPI读写测试确认SPI控制器工作正常。然后再跑完整的初始化脚本。如果SPI都不通后面都是白搭。3.2 Linux下的驱动与设备树配置到了Linux环境AD9361的驱动通常是基于IIO子系统的。内核里已经有ad9361的驱动但需要正确配置设备树。设备树里需要描述SPI控制器节点AD9361的SPI从设备节点时钟源GPIO控制引脚复位、使能、增益切换等一个典型的设备树片段是这样的spi0 { status okay; ad9361: ad93610 { compatible adi,ad9361; reg 0; spi-max-frequency 10000000; clocks clk40m; clock-names ad9361_ext_refclk; reset-gpios gpio0 10 GPIO_ACTIVE_LOW; // ... 其他配置 }; };设备树配好之后加载驱动应该能在/sys/bus/iio/devices/下看到对应的设备节点。然后可以用iio_info或者直接读写sysfs来配置采样率和带宽。我遇到过的问题是设备树里的时钟频率和实际晶振不一致导致驱动算出来的分频比错误PLL锁不定。后来在驱动里加了一个打印把实际计算出的频率打出来和示波器测的对比才发现问题。3.3 ZYNQ的DMA配置与数据搬运AD9361的数据流进入PL后需要通过DMA搬进DDR。ZYNQ的PS端有内置的DMA控制器PL端也可以用AXI DMA IP。璞致PZSDR系列通常用的是AXI DMA配置成Scatter-Gather模式可以连续搬运大量数据。DMA的配置要点描述符链提前在DDR里分配好描述符每个描述符指向一块接收缓冲区。中断DMA完成一个描述符后触发中断PS端在中断里处理数据。缓存一致性如果PS端开了MMU和CacheDMA搬进来的数据需要做Cache Invalidate否则读到的可能是旧数据。注意ZYNQ的DMA和Cache的交互是个大坑。我见过很多人调试时发现数据不对最后发现是Cache没刷新。建议在DMA接收路径上要么把缓冲区配置成非缓存要么在读取前手动Invalidate。3.4 上位机通信方案选型PZSDR板卡和上位机的通信方式有几种选择方案带宽延迟复杂度适用场景千兆以太网中中低通用数据采集USB 2.0低低中低速控制USB 3.0高低高高带宽数据流PCIe极高极低高实时处理如果只是做控制和小批量数据传输千兆以太网就够了。如果要传原始I/Q数据USB 3.0或者PCIe更合适。璞致的一些高端型号支持PCIe可以直接插在工控机上带宽和延迟都很好。我在一个项目里用的是千兆以太网PS端跑Linux用TCP把打包好的I/Q数据发给上位机。实测下来持续吞吐能到600Mbps左右对于20MHz带宽的信号来说够用了。4. 常见问题排查与避坑经验实录4.1 AD9361初始化失败速查表现象可能原因排查方法解决方案0x247读出0x80RX PLL未锁定检查参考时钟频率和相噪更换低相噪晶振确认频率CP OVRG HIGH置位电荷泵过压检查VCO校准是否完成重新触发校准降低参考时钟抖动SPI读写不一致SPI时序问题降低SPI时钟检查CPHA/CPOL调整SPI模式加校验接收数据全零数据接口未使能检查LVDS/CMOS配置确认ENSM模式检查FDD/TDD发射无输出TX衰减过大检查TX增益配置调整TX衰减寄存器4.2 ZYNQ烧写与固化常见问题ZYNQ的烧写和固化是另一个高频问题区。很多人问ZYNQ 7020使用JTAG固化Flash时必须使用DDR吗答案是不一定但大多数情况下需要。因为FSBLFirst Stage Boot Loader在初始化DDR之前只能使用OCMOn-Chip Memory。如果你的BOOT.bin比较大OCM装不下就必须初始化DDR把FSBL搬到DDR里运行。璞致PZSDR系列的BOOT.bin通常包含FSBL、PL比特流和应用程序体积不小所以基本都要用DDR。固化步骤大致是在Vivado里生成FSBL和BOOT.bin。用JTAG下载FSBL到ZYNQ。通过FSBL把BOOT.bin写入QSPI Flash。断电把启动模式改成QSPI重新上电。提示固化之前一定要确认QSPI Flash的型号和容量不同型号的擦除命令可能不一样。我遇到过Flash型号不匹配写进去的数据读出来全是0xFF。4.3 裸机USB通信方案ZYNQ的PS端有USB控制器裸机下可以用libusb来做通信。但裸机没有操作系统libusb的移植比较麻烦需要自己实现USB协议栈的一部分。一个更简单的方案是用ZYNQ的USB控制器配置成Device模式自己写一个简单的USB类驱动。比如CDC-ACM类上位机不需要装驱动就能识别成串口。虽然带宽不高但胜在简单可靠。如果非要跑libusb建议先在Linux下验证USB通信正常再把相关的代码移植到裸机。裸机下要注意中断处理和DMA的配合USB的传输描述符要提前分配好。4.4 Qt在ZYNQ上的串口库编译有些项目需要在ZYNQ上跑Qt界面同时用串口和外部设备通信。Qt的SerialPort库在ZYNQ上编译时需要注意交叉编译工具链的配置。我一般这样做在Ubuntu上安装ZYNQ的交叉编译工具链。下载Qt源码配置时加上-serialport选项。指定交叉编译器的路径和sysroot。编译安装到目标文件系统。编译过程中最容易出错的是sysroot的路径。如果sysroot里缺少某些库的头文件编译会失败。建议先把ZYNQ的根文件系统挂载到本地作为sysroot。注意Qt的SerialPort库依赖Linux的termios裸机下没有这个接口所以裸机不能用Qt的SerialPort。裸机下要么自己写串口驱动要么用PL端的UART。4.5 实操心得与避坑清单最后分享几条我在PZSDR系列板卡上踩过的坑和总结的经验参考时钟是命门AD9361的所有性能都建立在参考时钟的质量上。不要在这上面省钱一颗好的TCXO能省掉后面无数调试时间。SPI写后必读每次写关键寄存器后读回校验能提前发现80%的配置问题。DMA和Cache要一起考虑ZYNQ的Cache一致性问题是调试数据通路时的头号杀手。先跑通再优化不要一上来就追求最高采样率和最大带宽先用低速率把整个链路跑通再逐步提高。保留调试串口无论项目多紧张都要留一个UART作为调试输出关键时刻能救命。电源纹波要实测AD9361对电源纹波敏感用示波器实测一下1.3V和1.8V的纹波超过10mV就要考虑加滤波。我在实际使用中发现璞致PZSDR系列的硬件底子是不错的但配套的软件和文档有时候不够细致很多配置需要自己摸索。好在ZYNQ和AD9361的生态比较成熟社区里能找到大量的参考设计和讨论。遇到问题的时候先搜一下有没有人遇到过类似的情况往往能省下不少时间。这个板子后续还可以往几个方向扩展一是加装射频前端模块比如PA和LNA扩展覆盖范围二是在PL里实现更多的数字信号处理逻辑比如信道化接收三是把PS端的软件升级成更完整的协议栈支持更多的通信标准。这些就留到以后有机会再聊了。