拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Zynq-7000 XC7Z010核心板硬件设计实战:从电源到DDR3的完整方案

Zynq-7000 XC7Z010核心板硬件设计实战:从电源到DDR3的完整方案

前阵子帮客户做了一块基于Xilinx Zynq-7000系列XC7Z010的Linux核心板,从需求评审到出样机前后折腾了两个月。这块板子定位很明确:低成本、低功耗、跑Linux、带千兆网和USB,用于工业网关产品。XC7Z010这种PS+PL双架构的芯片,板级设计和纯FPGA或者纯ARM都不一样,电源、启动、DDR3布线各有各的讲究。这篇直接把核心板硬件设计的完整思路和实操细节整理出来,适合正在做Zynq方案选型、画板子遇到瓶颈、或者想评估核心板定制可行性的硬件工程师参考。

1. 项目概述与整体架构设计

1.1 为什么选XC7Z010而不是Z-7020或纯FPGA

XC7Z010在Zynq-7000家族里属于入门型号,但资源比我最早预想的要够用得多。PS端集成双核ARM Cortex-A9,主频最高到866MHz,跑Linux跑轻量级工业协议栈完全没问题。PL端有28K逻辑单元,80个DSP48E1 Slice,Block RAM总量240KB左右,做一些简单接口扩展、协议解析、并行信号采集够用。CLG400封装只有400个引脚,板级设计难度比Z-7020的FBGA484低不少,PCB面积和布线压力都小。

选型时主要卡在两个点:一个是DDR接口宽度。XC7Z010的PS DDR接口在CLG400封装下只有16位,Z-7020同样也是16位,再往上Z-7030才有32位。如果应用只是跑Linux系统、存视频流或者做中等规模的协议缓存,16位DDR完全够用,读写带宽大约能达到4GB/s的理论上限,实际跑千兆网和USB2.0的吞吐绰绰有余。另一个是引脚数量。核心板不需要引出太多PL IO,我们最终只引了40对差分对和30多个单端IO,CLG400绰绰有余,剩下引脚全部做电源和地,供电质量反而更好。

我后来在量产时对比过,XC7Z010单颗芯片价格比Z-7020便宜接近40%,对于网关类产品来说代价差异非常敏感。如果未来需要扩展更大的逻辑资源,PCB布局上只要保留兼容位,可以直接替换,因为Z-7020是兼容封装的(CSG325不行,但FBGA484和CLG400部分管脚兼容性要仔细核对封装图,这点后面会提)。

1.2 核心板整体架构与模块划分

核心板本质上是把Zynq最小系统做成一个可复用的模块,通过板对板连接器(B2B)引出所有需要的IO和电源,底板只需要负责供电、连接器和应用外设。我们的架构划分为六个模块:电源管理、DDR3存储、启动配置与QSPI Flash、PS外设接口(RGMII千兆网、USB2.0、UART、SD卡)、JTAG调试电路、以及PL侧可扩展IO。整体方案如下:

模块关键器件接口/规格
电源输入5V/3A DCB2B连接器输入
DDR32片512MB 16bit DDR3L1GB容量,16位总线
QSPI Flash1片128Mbit启动镜像+FPGA bitstream
千兆网RGMII PHY10/100/1000M自适应
USBULPI PHYUSB2.0 Host/Device
UARTRS232/RS485电平可选调试串口
SD卡MicroSD卡座系统启动/数据存储
JTAGPS_JTAG接口调试ARM和PL

这个架构基本覆盖了Linux核心板的标配需求。设计上有一点很关键:把DDR3、QSPI Flash、时钟和电源放在核心板上,把PHY芯片、连接器、RS232收发器这些可以根据应用灵活变动的器件尽量放到底板。这样核心板的验证工作可以一次性做完,底板端设计错误的概率会小很多。PHY芯片放在底板实际上也是可以的,但考虑到千兆网信号走B2B连接器容易引入串扰,最终把PHY放到了核心板上,只把RJ45网口和网络变压器放到底板。

2. 电源系统设计:多路电源轨与上电时序

2.1 Zynq-7000电源轨到底需要多少路

Zynq-7000的电源比传统FPGA复杂,因为它有PS和PL两套供电体系,而且部分引脚电压要求不同。XC7Z010正常工作时,至少需要六种电压:

电源轨电压供给对象
VCCPINT1.0VPS端内部逻辑
VCCPAUX1.8VPS端辅助电路
VCCPLL1.8VPS端锁相环
VCCINT1.0VPL端内部逻辑
VCCAUX1.8VPL端辅助电路
VCCBRAM1.0VPL端Block RAM
VCCO_DDR1.5V/1.35VPS DDR接口
VCCO_MIO3.3V/1.8VMIO Bank电压

我用的DDR3L设计,所以VCCO_DDR取1.35V。VCCPINT和VCCINT电压完全相同,可以共用一个电源芯片的同一路输出,VCCBRAM也通常一起接,这样能减少一路电源。VCCPAUX和VCCPLL在参考设计中可以各自独立,但很多成熟方案会把它们合并成一路1.8V,前提是源头输出能力足够且去耦到位。我这次采用三路主电源加一路DDR专用电源的简化方案:3.3V(MIO Bank和外设)、1.8V(AUX/PLL/PL辅助)、1.0V(INT/PINT/BRAM)、1.35V(DDR3L),外加DDR VTT和VREF。

这里有个容易踩的坑:VCCPAUX和VCCPLL如果合并供电,要确认PLL的噪声敏感度。VCCPLL直接给PS内部的PLL供电,纹波要求在20mV以内,如果和VCCPAUX共用同一路,必须保证该电源的纹波足够低。我用的是MPS的开关电源加LC滤波后再分两路进芯片,实测纹波在10mV左右,满足要求。如果条件允许,VCCPLL独立用一个小LDO会省心很多,代价是PCB面积稍大。

2.2 电源芯片选型与上电时序控制

上电时序是Zynq硬件设计里最容易被忽略的细节。Xilinx要求VCCPINT先于VCCPAUX上电,VCCPINT上电时间不能比VCCPAUX晚超过一个特定窗口(ug585里的建议是VCCPINT不晚于VCCPAUX上电后100ms),同时VCCO_DDR需要在DDR接口初始化前稳定。PL侧虽然没有PS那么严格,但VCCINT最好也先于VCCAUX。最稳妥的做法是让1.0V先起来,然后1.8V,最后3.3V和1.35V,用电源监控芯片统一控制。

我用的是MPS的同步降压芯片,每个模块的EN引脚通过电阻分压连接到前级电源的输出,做一个简单的级联使能,实现顺序上电。1.0V的芯片作为源头,EN接电源输入端的延时RC;1.8V的EN由1.0V输出控制;3.3V和1.35V的EN由1.8V输出控制。另外在每个电源轨上加了TPS3808电压监控芯片,当电压掉出阈值时输出复位信号,接PS_POR_B和PS_SRST_B。这样设计的好处是,不用额外程序员去写电源控制逻辑,纯硬件级联就能满足上电时序,成本也低。

上电时序的验证方法很简单,用四通道示波器同时测1.0V、1.8V、3.3V和1.35V的波形,按开机按钮抓取上升沿顺序,确认1.0V最先稳定。同时要在空载和满载条件下分别测试,因为负载变化可能导致某一路电压上升变慢,打破时序要求。

2.3 去耦电容配置的实操心得

Zynq这么高密度的BGA芯片,去耦电容不是随便放几个就完事的。XC7Z010的CLG400封装焊盘间距只有0.5mm,电容必须尽可能靠近对应电源引脚。我采用的是“三级去耦”策略:芯片背面每个电源焊盘周围放置0.1uF和0.01uF的0402电容,中频去耦用1uF/10uF的0805电容分布在芯片四周,低频去耦在PCB板边或B2B连接器附近放置470uF钽电容。

很多设计翻车就翻在电容布局上,原理图里电容画了一堆,实际PCB上离电源引脚太远,寄生效应对高频纹波完全失效。放置0.1uF电容时,必须保证过孔到电容焊盘的距离最短,最好是让电源过孔先打过孔到电容再到芯片引脚,而不是让电流绕一圈再回到芯片。这个细节对Zynq这种功耗较高且内核频率较高的芯片特别重要,我们第一批板子就吃过这个亏,PL逻辑稍微跑起来,核心电压纹波就飙到40mV,系统偶发死机,后来重新调整电容布局才解决。

3. DDR3存储系统设计:16位总线也能跑得很稳

3.1 DDR3L容量计算与颗粒选型

XC7Z010的PS DDR控制器支持16位DDR3/DDR3L,最高支持到DDR3-1066速率。我们最终采用两片8bit的DDR3L颗粒,每片容量512MB,组成1GB 16位总线的方案。单颗16bit颗粒也支持,但两颗8bit颗粒的散热更均匀,而且采购灵活,坏一颗换一颗也不会整板报废。

选型时要注意,DDR3L的标准电压是1.35V,兼容1.5V的DDR3。Zynq-7000的DDR控制器在硬件设计时通过VREF和VCCO_DDR电压来配置,不能混用。另外颗粒的地址线映射要仔细核对Zynq的DDR地址映射表。CLG400封装的Z-7010支持的地址线数量有限,DDR_A[14:0]、BA[2:0]全部引出,容量上限是单片4Gb(512MB)级别的颗粒,两片就能到1GB,再大的容量需要核对地址线是否足够。

DDR的VREF电路做一个简单的电阻分压就能用。VREFCA接两个1kΩ 1%精度的电阻,从VDD_IN分压得到0.675V(DDR3L时),分压点靠近DDR颗粒放置,加一个0.1uF去耦电容。ZQ引脚接240Ω±1%电阻到GND,这个电阻必须靠近DDR颗粒,误差大了会影响输出驱动强度校准,DDR初始化时可能报错。ODT引脚连接到Zynq的PS_DDR_ODT,由控制器动态控制,这一点比早期纯FPGA方案简单很多。

3.2 DDR3布线关键参数与等长策略

DDR3布线是整个核心板最有技术含量的环节,尤其是16位总线在两层板内完成等长控制。我的叠层方案是六层板,信号走L1、L3、L6三层,L2、L5为完整GND平面,L4为电源平面。DDR数据线全部走在L1顶层,地址控制线走在L3内层,尽量不让DDR信号换层,减少过孔带来的阻抗不连续。

数据线按字节通道分组,DQS和对应的DQ在同一层紧邻走线,实现时钟和数据的同步。等长要求如下:

信号组等长约束参考标准
DQ[7:0]与DQS0/DM0同一组内±10mil布线相对长度
DQ[15:8]与DQS1/DM1同一组内±10mil布线相对长度
地址/控制线(A/BA/CAS/RAS/WE/CS)相对DDR_CLK ±20mil布线相对长度
DDR_CLK_P/N差分对内等长,±5mil差分长度
CLK与DQ组之间不做硬性要求,但建议DQ组相对CLK在±500mil内系统总长

这个等长策略来源是DDR3-1066时序计算的结果。数据DQS和DQ是源同步,要求组内等长,因为读取时控制器用DQS采样DQ;地址和控制线是共同时钟同步,所以要和CLK对齐。DQS差分对内长度误差如果超过5mil,在1066速率下会引起明显的时序抖动,这个必须卡死。

阻抗方面,单端线控制50Ω,DQS差分对控制100Ω。L1层走线宽度5mil配5mil间距,参考L2地平面,阻抗大概在50Ω左右。DQS差分线宽5mil,间距8mil,差分阻抗约100Ω。这些参数在投板前让板厂做阻抗测试条确认。

3.3 DDR3端接与电源完整性处理

DDR3地址和控制信号采用fly-by拓扑,末端需要加VTT端接电阻,VTT电压等于VDD的一半。我用TPS51200产生VTT和VREF,这个芯片集成度高,能提供2A的VTT电流,而且输出电压精度好。VTT和VREF的PCB走线要单独规划,VTT是电源层的一部分,不能和信号线共用,否则会产生噪声耦合。

VREF在DDR3设计中要求特别干净,任何毛刺都可能导致DDR初始化不稳定。我单独加了RC滤波,VREF走线避开所有开关电源和DDR数据线。实际调试中发现,VREF走线如果和VTT在相邻层平行走线超过3cm,DDR偶发报错概率明显增加。后来把VREF走线离VTT层至少隔一层地才彻底解决。

还有一个小细节:Zynq的PS_DDR_Z引脚需要接240Ω电阻到GND,这个电阻必须是1%精度,我遇到过一批5%精度的库存电阻,导致DDR校准失败,换回1%电阻就正常了。量不大但很影响生产效率。

4. 启动配置与时钟系统:核心板“大脑”的启动机制

4.1 Boot Mode引脚拨码设计

Zynq的启动模式由MIO[6:2]五个引脚的电平决定,硬件上我直接做了4位拨码开关,分别控制MIO2、MIO3、MIO4、MIO5,MIO6用电阻固定拉低。参考ug585的标准设置:MIO[6:2]=5‘b00000时选择JTAG启动,5’b00001时选择QSPI启动,5‘b00010时选择SD启动。这样拨码开关拨到对应位置就能选择启动介质。

启动模式引脚电平在MIO Bank的VCCO决定,我用的3.3V供电,所以上拉电阻统一接3.3V。特别注意MIO[6:2]不能接大电容或长走线,否则上电瞬间电平不稳定,可能导致芯片识别错启动模式。我在每个引脚上拉电阻选10kΩ,下拉选10kΩ,走线尽量短,实测上电后50ms内启动模式锁存完毕。

4.2 QSPI Flash电路与启动镜像

QSPI Flash选用128Mbit的N25Q128,供电电压3.3V,与MIO Bank 500的VCCO匹配。Zynq的QSPI接口占用MIO[1:6],实际使用MIO1到MIO6共6个引脚:CS、CLK、DQ0、DQ1、DQ2、DQ3。上电后Zynq从QSPI的第一个扇区读取启动镜像,因此QSPI Flash布局要尽量靠近MIO引脚,减少走线长度。

QSPI信号线的布线要求不算苛刻,但CS、CLK、DQ之间的等长还是要控制。因为QSPI时钟在双倍速率模式下可达100MHz以上,CS信号在命令阶段延迟不能太大。我按等长要求做到±200mil以内,实测单倍速率和双倍速率模式都能稳定启动。

调试阶段建议保留JTAG启动优先权。我设计的是拨码开关在JTAG档位时,QSPI的CS引脚保持高电平不激活,JTAG调试器可正常初始化芯片,避免插上JTAG时芯片先从QSPI启动导致调试器连不上。这个小设计在开发阶段省了不少时间。

4.3 PS与PL侧时钟树设计

Zynq的PS端需要外部提供PS_CLK,频率范围30MHz到60MHz,我选用33.333MHz有源晶振。这个频率可以内部PLL倍频出CPU的866MHz运行频率,也能为DDR控制器提供稳定的参考时钟。PS_CLK的走线越短越好,走内层包地,避免被边缘的开关电源噪声干扰。

PL端的时钟我采用了一个可选的差分晶振焊盘,频率125MHz,可以给PL的逻辑提供稳定时钟。不过更多时候PL时钟可以由PS的FCLK_CLK0输出直接提供,这样能省掉一路晶振。我在核心板上保留了125MHz差分晶振位置,通过0Ω电阻选择到底是外部晶振还是PS产生时钟。实际项目中PSoC的PL只做低速接口逻辑,用PS FCLK_CLK0输出50MHz就足够了。

RTC时钟部分Zynq内部有RTC模块,需要32.768kHz外部晶振。很多人会省略这个晶振,我建议工业产品至少保留焊盘,因为RTC在很多应用里有重要作用。我的设计里用了无源32.768kHz晶振,并联两个负载电容到GND,PCB布局时靠近PS的RTC引脚。如果确定不用RTC,这个晶振可以不贴,不影响系统启动。

5. 外设接口电路设计:MIO引脚分配与PHY芯片选型

5.1 MIO引脚规划总表

Zynq的MIO引脚可以灵活配置为多种外设接口,但一旦PCB定板,引脚分配就不能改了。所以原理图阶段的MIO规划必须先想清楚。我使用的分配方案:

MIO引脚范围功能分配电平域
MIO[1:6]QSPI Flash3.3V
MIO[10:11]UART0(调试串口)3.3V
MIO[16:27]GEM0 RGMII(千兆网)3.3V
MIO[28:39]USB0 ULPI3.3V
MIO[40:45]SD03.3V
MIO[48:49]UART1(应用串口)3.3V
MIO[7:9]/[12:13]/[46:47]GPIO/拨码/状态LED3.3V

MIO引脚的bank供电必须和外部器件电平匹配。我统一采用3.3V作为所有MIO Bank的VCCO,方便和PHY芯片、USB PHY、RS232收发器直接连接。如果某个外设需要1.8V电平,比如某些低功耗PHY,那就需要单独规划MIO bank电压,不能混用。

5.2 RGMII千兆网PHY接口设计

千兆网是核心板的重要功能,我选用KSZ9031RNX作为PHY芯片,支持RGMII接口,和Zynq的GEM0直接连接。RGMII的数据线包括TXD[3:0]、RXD[3:0]、TX_CTL、RX_CTL、TXC、RXC,共12根信号线。数据线走线保持等长,RXC和TXC采用差分时钟走线形式但实际是单端时钟,所以按50Ω阻抗走线,注意包地。

RGMII有一个关键坑:千兆模式下TXC和RXC需要大约2ns的延迟,用来保证数据和时钟的中心对齐。这个延迟可以通过Zynq内部寄存器配置,也可以在PHY的stapping引脚上设置。我使用KSZ9031时,把PHY的RX_DLY引脚通过10kΩ下拉到地,使其内部产生RXC延迟;Zynq GEM则在开发中通过device tree配置内部延迟。这样避免了PCB上的延迟走线,是在RGMII v2.0兼容下比较稳妥的方案。

PHY的时钟输入我用25MHz无源晶振,PHY内部PLL倍频到125MHz用于千兆模式。晶振的负载电容按PHY数据手册配置,实测波形幅度要求满足芯片VIL/VIH规范。PHY的复位引脚连接到PS的GPIO,可以通过软件控制PHY复位,调试点问题方便。

5.3 USB 2.0 ULPI接口设计

Zynq的PS内置USB 2.0控制器,但不能直接驱动USB物理层,需要外部ULPI PHY。我用USB3320,它功耗低,体积小,ULPI接口占用12个MIO引脚。USB3300也可以,但USB3320在工业温度范围表现更好。

USB3320的参考时钟我用了24MHz外部晶振。有些设计喜欢用12MHz,但24MHz的DLL锁定时间更短,上电稳定更快。ULPI总线的时钟频率60MHz,必须保证USBCLK走线尽量短,并且远离DDR等高速信号。VBUS的过流保护和电源开关用了一片MIC2026,当检测到过流时自动断开,状态信号接Zynq的GPIO,可以在Linux里读取并上报。

USB插座采用MicroUSB,用于Host和Device模式切换需要通过ID引脚检测。我在USB_ID引脚上做了电阻分压网络连接到Zynq GPIO,Linux里的usb gadget驱动可以根据ID状态切换角色。不过大多数工业网关只需要Host模式,这里做成可选设计。

5.4 UART与SD卡接口电路

UART是最简单的接口,但往往是最实用的调试通道。我分配了UART0作为调试串口,接SP3232做RS232电平转换;UART1作为应用串口,通过跳线可以切换RS232或RS485收发器。RS485方向控制用Zynq的GPIO控制,Linux里通过gpios属性配置。

SD卡接口采用SD0,连接MicroSD卡座。SDIO总线工作电压3.3V,信号线包括SD_CLK、SD_CMD、SD_D0-D3共6根线。SD_CLK的工作频率最高达50MHz,需要和其他SD信号线等长,避免时序问题。卡座上有卡检测和写保护引脚接到GPIO,在应用中可以实现热插拔检测。ESD防护用的PESD0402系列阵列,每根SD信号线都加,这个位置不能省,否则工业现场静电打几天就会出现SD卡识别失败。

6. JTAG与调试接口设计:一把钥匙开两把锁

6.1 PS_JTAG与PL_JTAG的取舍

Zynq-7000的调试接口其实有两套:PS_JTAG连接ARM的DAP,PL_JTAG连接FPGA的JTAG链。但在绝大多数开发场景下,一套PS_JTAG就够了,因为Xilinx的Vivado SDK可以通过PS_JTAG同时访问PS和PL。PL的bitstream烧写和在线调试逻辑分析仪,也都走PS_JTAG通道。

核心板上的JTAG接口设计为10针2.54mm标准排针,信号是TCK、TMS、TDI、TDO、GND,另外提供VTREF电压检测。我保留了PS_JTAG和PL_JTAG两套焊盘,但默认只贴PS_JTAG那套,PL_JTAG需要调试底层逻辑时才贴,避免板卡面积浪费。JTAG信号线全部做上拉,TMS和TDI分别接10kΩ到3.3V,避免悬空时误触发调试模式。

6.2 复位电路与电源监控

Zynq的复位信号有PS_POR_B和PS_SRST_B两种。PS_POR_B是上电复位,必须在所有电源稳定后释放;PS_SRST_B是软复位,可以由外部按键或系统软件触发。我用TPS3808监控1.0V电源,当电压低于阈值时输出低电平复位脉冲,同时把PS_SRST_B也连到一个按键开关上,方便开发时手动复位。

这里有一个经验:PS_POR_B的上拉电阻不能太小,否则复位释放时瞬间灌入电流过大,可能造成电源波动。我选择10kΩ上拉到1.0V(因为TPS3808是开漏输出,上拉到VCCPINT更合理)。实际上PS_POR_B内部有弱上拉,外部上拉主要为了加快上升沿速度。复位信号走线要包地,不要和其他高速信号平行,防止复位信号上的毛刺导致CPU异常复位。

7. PCB布局布线实战:从叠层到散热一次讲清

7.1 六层板叠层与层分配策略

核心板PCB采用六层设计,层叠顺序如下:

层功能主要走线
L1顶层信号DDR数据、RGMII、MIO、QSPI
L2地层完整GND
L3内层信号DDR地址控制、低速外设
L4电源层1.0V、1.8V、3.3V、1.35V分割
L5地层完整GND
L6底层信号调试接口、电源转换

这个叠层保证了DDR信号在L1有完整地平面参考,电源层和地层紧密耦合,电源完整性不错。L4电源分割要注意隔离度,1.0V和1.35V区域不要大面积相邻,避免高频噪声串扰。电源层在分割处预留了跨接电容位置,实际测试如果发现电压波动,可以补焊跨接电容。

BGA区域内的过孔全部采用盘中孔工艺,焊盘内不出现盲埋孔,直接打通孔到内层。盘中孔填铜处理,避免焊料流失造成虚焊。CLG400封装引脚间距只有0.5mm,出线很困难,我采用0.25mm/0.45mm的过孔(钻孔/焊盘),所有信号从BGA内侧扇出到内层或底层,尽量不在BGA正下方走太长线。

7.2 关键信号布线策略

DDR布线在前面已经细说了,这里重点讲其余几组关键信号。RGMII的12根信号线要求等长,我在建模时把所有信号约束到同一组,目标长度2000mil,等长容差±50mil。RJ45方向的MDI差分对由网络变压器决定拓扑,我采用HX5008NL网络变压器,PHY侧走线按100Ω差分阻抗设计,变压器侧走线到RJ45也按100Ω,但在变压器旁放置共模扼流圈位置供EMC整改时选用。

USB ULPI总线的布线要控制最长走线长度在1500mil以内,每根线之间保持至少2倍线宽的间距,总线靠近MIO引脚扇出,不要绕到DDR区域下面。QSPI Flash的走线要短而直,CS信号加弱上拉,CLK走线远离电源开关器件。

MIO引脚本身的布线相对宽容,但因为外设多、分布广,容易和电源转换区域交叉。我的策略是MIO信号尽量走在L1和L3,电源转换的开关节点走L6,利用L5地平面隔离,避免开关噪声耦合到MIO接口信号上。

7.3 散热设计与机械结构

XC7Z010的CLG400封装功耗在满载时大约2.5W到4W,取决于PL逻辑利用率。核心板尺寸只有55mm×40mm,自然散热条件下芯片表面温度可能到80℃以上。我采用了两种散热措施:芯片底部的散热焊盘通过过孔阵列连接到PCB背面的覆铜区,形成一个简易的散热片;同时预留了四颗M3螺柱孔位,用户可以安装散热片,用导热垫接触芯片表面。

散热过孔设计要稀疏而不是过密,过孔太密会导致回流焊时锡膏吸走,造成虚焊。我采用0.3mm过孔,间距1.0mm,只覆盖芯片底部中心区域,避开焊接BGA的阻焊开窗。B2B连接器选择两个80pin的0.5mm间距板对板连接器,分布在PCB两侧,机械强度足以支撑底板上的PHY和网口。

8. 调试实录与常见问题排查:踩坑总结比设计更值钱

8.1 上电无电流、无法连接JTAG的排查

第一次打样回来最怕的就是上电没反应。我们的第一版样机插上电源后电流只有30mA,明显不正常。排查过程是这样的:先用万用表测量各电源轨对地阻抗,发现1.0V对地只有约10Ω,异常。用热成像仪扫描板子,发现一颗0.1uF去耦电容位置发烫,拆掉后阻抗恢复正常。原因是电容贴反了(虽然是陶瓷电容没有极性,但回流焊过程可能造成内部短路),换了新料后正常。

JTAG连接不上的情况也常遇到。我排查时首先量PS_JTAGTCK的波形,确认有稳定时钟;再量TDI和TMS的上拉电压是否正常;最后检查JTAG排针的VTREF是否接到正确的电源。有一次就是因为VTREF接到了3.3V,而芯片JTAG引脚参考的却是1.8V bank电压,导致调试器识别失败。Zynq的PS_JTAG引脚电压是固定的,不随MIO bank电压变化,这个要和芯片手册核对清楚。

8.2 DDR初始化失败的典型原因

DDR初始化失败是Zynq项目最高频的问题。常见现象是Vivado SDK里DDR测试程序运行后报错,或者Linux启动时卡在“Starting kernel”前的DDR自检。排查顺序依次是:

  • 检查VCCO_DDR电压是否正确,DDR3L必须是1.35V,不少开发板默认1.5V,即使颗粒也能跑,但长期可靠性有隐患
  • 检查VREF电压是否稳定在0.675V,分压电阻精度和VREF走线质量很关键
  • 检查ZQ校准电阻是否精确到240Ω,误差不能超过1%
  • 用Xilinx的DDR Calibration工具看初始化失败阶段,如果失败在Write Leveling,说明CLK和DQS的等长没做好;如果失败在读校准,说明DQ和DQS组内等长或VREF有问题

我遇到一次DDR初始化失败是因为DQS差分对的末端和DQ不在同一层,过孔数量不一致,导致传播延迟差异过大。手工调整走线后重新投板,问题消失。这类问题用万用表和肉眼很难发现,必须用示波器或Vivado的调试工具测量。

8.3 千兆网不通或丢包的硬件因素

千兆网问题在核心板上也很典型。如果是RGMII接口设计,排查顺序:

  • 先用网线连接PC和板子,查看PHY的link状态寄存器,确认PHY初始化成功
  • 如果link是好的但ping不通,查看device tree里PHY的mode配置,确认是rgmii-id还是rgmii-txid,要匹配实际硬件延迟
  • 如果ping通但丢包严重,优先怀疑RXC和TXC的延迟设置。KSZ9031的RX_DLY引脚如果悬空,默认是内部延迟开启,如果Zynq侧也配置了延迟,会造成双重延迟,接收数据错位

我建议在硬件设计阶段就固定PHY的delay模式,通过stapping引脚电阻确定,不要依赖软件动态配置,这样能减少调试痛苦。另外RGMII走线的等长一定要控制好,我在一次改板中无意间拉长了一根TX_CTL走线,造成千兆模式下随机丢包,百兆模式下又正常,非常隐蔽。

8.4 SD卡与USB识别不稳定的排查

SD卡不稳定最常见的原因是SD_CLK信号完整性问题。SD_CLK上升沿如果太缓,卡就识别不了。我遇到过一次是因为SD卡座的CLK走线绕了很长一段,导致串扰,后来在CLK引脚上加33Ω串联电阻减小过冲,并在靠近卡座的位置增加一个22pF对地电容,问题解决。

USB无法识别,先看USB PHY的电源和复位是否正常,再用示波器抓ULPI接口的60MHz时钟,看时钟是否干净。USB3320的供电要特别注意,它的VDDIO和MIO bank电压必须匹配,否则ULPI信号的电平不满足数位识别要求。还有一点,ULPI的DIR信号如果走线太长,会影响数据读回时序,我建议DIR走线尽量短,必要时做3.3V电平上拉。

9. 最后聊几句细节

实际项目里比设计本身更考验人的是器件选型和供应链。XC7Z010目前供货渠道稳定,但DDR3L自2023年之后价格波动不小,建议核心板方案里预留DDR3(1.5V)兼容位,这样DDR3L缺货时可以切换。QSPI的N25Q128也有国产替代,比如GD25Q128,引脚兼容,但要注意读写时序差异,量产前要做兼容性测试。

调试阶段的JTAG连接器尽量选带锁扣的,工业现场振动环境下普通排针容易接触不良。给客户的底板接口定义要做防呆设计,B2B连接器两个方向不能插反,因为一旦插反可能导致整个核心板短路烧毁。

这些经验都是这次做XC7Z010核心板一点点攒下来的,写出来算是给自己做个记录,也希望能帮到正在做类似板卡的同行。如果遇到具体设计问题,欢迎一起交流。

返回列表