ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Zynq-7020开发板原理图精读:电源树、DDR3与Vivado配置对账

Zynq-7020开发板原理图精读:电源树、DDR3与Vivado配置对账

简介:面向嵌入式硬件工程师、现场可编程门阵列学习者以及需要快速熟悉开发板硬件组成的自学者,开发板原理图可用于板级方案参考、接口核对和供电设计学习。压缩包仅含一个PDF文档,约417KB,内容以系统框图和分页电路集中呈现,方便按模块查阅。图中覆盖多路电源输入与一点零伏、一点五伏、一点八伏、三点三伏等电压转换,以及核心芯片、可编程逻辑、配置和双倍速率存储供电;接口部分包含串口转接、通用串行总线、网络物理层、高清多媒体、存储芯片、闪存、存储卡、指示灯、调试与无线连接等设计。已有三千六百六十九人学习,适合用来梳理开发板硬件架构、理解原理图组织方式,并为二次设计与故障排查提供对照。

1. 17 页原理图先看第 1 页:Zynq-7020 开发板的分页结构与读图顺序

不少人拿到这份 PDF 的第一反应是直接翻到 POWER 页找 1.0V 那一路,翻完电源翻 DDR,翻到第 10 页发现网络名对不上,又回头重找,17 页来回翻三遍,脑子里还是一团散线。这份 Xilinx Zynq-7020 开发板原理图的真正入口不在电源页,而在第 1 页那张 Block 表:Page00 到 Page16 每页画什么、跨页网络靠方括号数字回指哪一页,全写在那张表里。它面向两类人——想自己做一块 Zynq 最小系统板的硬件工程师,和要在现成板子上改一路电源、换一颗 DDR3、加一个 SDIO 外设的嵌入式工程师。后面按电源、本体、接口、避坑、落 Vivado 的顺序,把这份图拆成能复算、能改、能对账的具体步骤。

2. 电源树复算:五路 MP2143DJ 加一颗 TPS51200,0.6V 基准怎么倒推反馈电阻

2.1 先把 Block 表翻译成一张电源树

第 2、3 页合起来才是一棵完整的树。第 2 页管"从墙插进来怎么变成五路",第 3 页管"这五路怎么分给 Zynq 的各个电源域"。读的时候别跳页,先把树画出来再动笔算。

输入端是 J8 这颗 DC 座,进来先过 D4(SMAJ5.0CA)做浪涌钳位,再进 SW1 自锁开关,出来就是 VDD_5V 这根主干。SW1 之后分出 VDD_USB2JTAG_5V 单独给 JTAG 那条链路,避免插拔仿真器时把主 5V 拉塌。

五路降压全部是同一颗 MP2143DJ,8 脚同步降压,开关频率内部固定,外围只需要电感、输出电容和反馈分压。图上的电感统一是 1uH,输出电容按 47uF/0805 打底,再并 10uF 和若干 0.1uF。这套配置对应 3A 级别的负载能力,带 Zynq 的 VCCINT 是够的,但要留意后面第 3 章讲的去耦数量问题。

把五路整理成一张表,读图时对着这张表找元件位号,比在 PDF 里乱翻快得多:

输出网络电压主要负载反馈网络特征
VDD_1V01.0VVCCINT、VCCBRAM、VCCPINT分压比约 0.67
VDD_1V51.5VVCCO_DDR_502、DDR3 器件 VDD分压比约 1.5
VDD_1V81.8VVCCAUX、VCCO_MIO0_500、VCCO_MIO1_501分压比约 2.0
VDD_3V33.3VVCCO_0、VCCO_13/34/35、外设分压比约 4.5
VDD_VIO1.8/2.5/3.3 可选PL bank 的 VCCO反馈网络可切换

VDD_VIO 那一路是整份图里最值得多看两眼的地方:它的反馈分压不是固定的,而是用几颗 0Ω 电阻(图上标了 0 和 NC)在几组阻值之间做二选一,配合丝印说明可以在 1.8V、2.5V、3.3V 之间切换。做兼容板、要同时支持 1.8V 和 3.3V 电平外设的时候,这种"跳线改电压"的做法比重新改板划算得多,代价是 BOM 上多几颗不贴的电阻,以及生产时容易贴错——这一点在第 5 章会展开。

2.2 用 0.6V 基准反推反馈电阻,别照抄别人的阻值

MP2143DJ 的内部基准是 0.6V,输出由 FB 脚上的上下分压决定,公式是老一套:

VOUT = 0.6 × (1 + R_top / R_bot)

反过来,已知目标电压和手上现有的上电阻,求下电阻:

R_bot = 0.6 × R_top / (VOUT - 0.6)

拿 1.8V 那一路做验算。图上 U10 这一路的反馈位上电阻是 10K、下电阻是 4.7K:

VOUT = 0.6 × (1 + 10 / 4.7) = 0.6 × 3.128 = 1.877V

算出来 1.877V,比标称 1.8V 高了 4.3%。这个偏差不是画错了,是 E24 系列阻值选不到正好 5K 的结果——按公式反算,10K 上电阻配 1.8V 需要下电阻 5.0K,E24 里最接近的是 5.1K,图上用 4.7K 是把输出电压往上偏了一点,换取 VCCAUX 的裕量。做产品的时候这么干没问题,做实验板就要知道:你量到 1.87V 属于设计内,不用怀疑芯片坏了。

同样的验算方法套到 1.0V 那一路:上电阻 4.7K、下电阻 6.8K,算出 1.014V,误差 1.4%,这一路选值选得比 1.8V 那路准。这说明设计者在 1.0V(VCCINT,Zynq 核心电压,容差通常 ±3%)上更保守,在 1.8V(VCCAUX,容差宽)上更随意——读图读到这一层,才算把别人的设计意图读出来了。

自己改板的时候有个血泪经验:反馈电阻别用 5% 精度的厚膜,1.0V 那一路上下分压比接近 1:1.45,两颗 5% 电阻叠加出来的误差能到 ±5% 以上,直接顶到 VCCINT 的容差边缘。常见做法是上下都用 1% 甚至 0.5% 的薄膜电阻,成本增加很有限,省下的是后面排查"为什么 PS 端 DDR 初始化偶尔失败"的几天时间。

2.3 TPS51200 与 DDR3 端接:0.75V 是算出来的不是调出来的

第 7 页那颗 TPS51200DRCR 是 DDR3 的专用端接芯片,作用是同时产生 VTT(端接电压)和 VREF(参考电压),两者都等于 DDR3 供电的一半。图上 VDD_1V5 供给 VLDOIN,REFIN 脚接一组分压,REFOUT 输出 VREF,VO 输出 VTT,VOSNS 做远端采样。

DDR3 的 VDD 是 1.5V,所以:

VTT = VREF = VDD_DDR / 2 = 0.75V

REFIN 那组分压要分到 0.75V,用的是两颗等值电阻(图上 R200 和 R202 都是 80.6 欧,0.1% 级别)。这里用 80.6 欧这种非整数阻值不是为了好看,是为了在 1% 精度下把分压误差压到最小,同时给 REFIN 脚提供足够低的源阻抗。自己改板时如果图省事换成两颗 10K,源阻抗上去了,VREF 会被 DDR3 的输入漏电流带偏,表现出来就是高频读写误码,而且这种误码是玄学型的——跑 memtest 前几百兆不报错,跑热了才报。

VOSNS 是远端采样脚,走线要从 VTT 的负载端(也就是 DDR3 的端接排阻那一侧)引回来,不是从芯片 VO 脚就近取。这条线的走法直接决定 VTT 在负载点的精度,图上把它单独拉出来画,就是在提醒这件事。

2.4 PG 链与时序:为什么四路 PG 都要引出来

第 2 页上能看到 PG_1V0、PG_1V5、PG_1V8、PG_3V3 四根信号,从各自 DCDC 的 PG 脚引出来,但没有直接连在一起,而是各自拉到一个汇合点。这个画法对应的是上电时序控制。

Zynq-7000 对电源上电顺序有明确要求:VCCINT 先起,然后 VCCAUX 和 VCCPLL,再是 VCCO_DDR,最后是 VCCO_MIO 和 VCCO_PL。顺序反了不会立刻烧,但会出现 PS 端启动不稳定、偶尔卡在 FSBL 阶段的现象——这类问题在实验室里靠反复断电重启"能好",一旦量产就是灾难。

图上的做法是把前一级的 PG 接到后一级的 EN 上,做成级联。我一般会在改板时把这个链再收紧一点:VCCINT 的 PG 有效之后再延时 2~5ms 才放行 VCCAUX,用一颗 RC 加比较器就能实现,比纯靠 PG 直连稳。代价是多两颗小器件,收益是把时序裕量从"刚好够"变成"有富余"。

还有一个容易漏的点:图上 VDD_5V 主干到各路 DCDC 的 VIN 之间没有做大容量储能,只有 0.1uF 和 10uF 的组合。如果下游挂了 USB OTG 或者 WiFi 模块这种瞬时电流大的负载,热插拔瞬间会把 5V 拉塌,导致其他路跟着复位。实际做板时在每路 DCDC 的 VIN 脚旁边补一颗 22uF 以上的陶瓷电容,这个钱不能省。

3. Zynq 本体与 7010/7020 同板兼容:VCCO 分域和那颗标着 Z7020 ONLY 的 1K 电阻

3.1 CLG400 封装下的电源域,一个都不能混

第 3 页那颗主芯片标的是 XC7Z010/20-1CLG400C,斜杠的意思是这份原理图同时兼容 7010 和 7020 两个型号,封装都是 400 球。400 球意味着球间距很密,扇出和去耦电容的摆放空间都很紧张,这也是为什么图上把这颗芯片的电源引脚按域拆成好几页画——画在一页上根本放不下。

把图上的电源域整理出来,这是改板和对账的基础:

电源域电压供给什么图上对应网络
VCCINT1.0VPL 逻辑阵列核心VDD_1V0
VCCBRAM1.0VBlock RAMVDD_1V0
VCCPINT1.0VPS 内核VDD_1V0
VCCAUX1.8VPL 辅助VDD_1V8
VCCPAUX1.8VPS 辅助VDD_1V8
VCCPLL1.8VPLL 供电VDD_1V8
VCCO_03.3V配置 bankVDD_3V3
VCCO_13 / 34 / 353.3V 或 VIOPL 用户 IOVDD_3V3 / VDD_VIO
VCCO_DDR_5021.5VPS DDR 接口VDD_1V5
VCCO_MIO0_5001.8VMIO bank0VDD_1V8
VCCO_MIO1_5011.8VMIO bank1VDD_1V8

这张表里最容易被忽略的是 VCCO_0。它是配置 bank,供电电压必须是 3.3V 或 1.8V(由 CFGBVS_0 脚选择),而且必须和 QSPI Flash 的 IO 电平一致。图上 CFGBVS_0 接的是 3.3V,说明整个配置链路按 3.3V 电平设计,QSPI 那边如果贴了 1.8V 的颗粒,读写就会挂。这种错误在打样阶段不报,贴完片第一次上电才暴露。

另外注意 VCCO_MIO0_500 和 VCCO_MIO1_501 都是 1.8V。这决定了所有接在 MIO 上的外设——以太网 PHY、SD 卡、QSPI、UART——都必须是 1.8V IO 电平,或者外部加电平转换。如果拿一颗 3.3V IO 的 PHY 直接怼上去,短期能通,长期在高温下会出问题。

3.2 R143 那颗 1K 电阻:7010 和 7020 的兼容位

第 5 页 bank 34/35 那一块,有颗电阻标着 "1K (Z7020 ONLY)",旁边还有两颗 0 欧电阻标着 0 和 NC,位置紧挨着 K17 和 E17 两个球。这是整份图里信息密度最高的一个角落。

7010 和 7020 在 CLG400 封装下引脚是兼容的,但内部资源不同,某些配置引脚在两个型号上的默认状态或者推荐接法有差异。图上这颗 1K 只在装 7020 时贴、装 7010 时留空,配合两颗 0 欧做二选一,本质上是给同一块 PCB 留了两个 BOM 变体。

落到实操上,这意味着三件事:

第一,如果你手上这块板子是 7010 版本,量到那颗电阻位是空的(NC),不要以为是漏贴,那是设计如此。反过来,如果你要把 7010 的板子换成 7020,只换芯片不补这颗电阻,可能会遇到配置不稳定或者某个 bank 功能异常。

第二,自己改板想复刻这种兼容设计,就别只抄原理图的连接关系,要把 BOM 变体一起抄下来。我见过有团队只抄了图、没抄变体表,量产后发现 7010 和 7020 混着贴,同一批板子表现不一致,查了两周才发现是这颗电阻。

第三,判断一块板子到底贴的是哪个型号,最直接的办法不是看丝印,是读 IDCODE。JTAG 连上之后读回来的器件 ID 会明确告诉你是 7010 还是 7020,比看丝印可靠得多。

3.3 去耦电容的数量:图上画了多少颗,就该贴多少颗

第 3 页这一片是整份图里最"密恐"的区域,几十颗 0.1uF 排成一列,外加若干 10uF 和 47uF。数一下 VCCINT 的球:G13、H12、J13、K12、L13、M12、N13、P12、R13,一共 9 个球。VCCAUX 有 J11、L11、N9、P10、R9 五个球。

这些球每一个都要配至少一颗 0.1uF,位置要尽量贴近球。图上给 VCCINT 配的 0.1uF 数量明显多于 9 颗,多出来的部分是给同一片区域的 VCCBRAM 和 VCCPINT 共用的。10uF 和 47uF 则是按区域布的大容量储能,一般一个电源域配一到两颗。

复现的时候最常见的翻车是:为了省 PCB 面积,把 0.1uF 砍掉一半,或者把 10uF 从 0805 换成 0603 省空间。前者导致高频去耦不足,PL 跑高速逻辑时出现随机错误;后者因为 0603 的 10uF 实际容值随直流偏压衰减严重,等效容值可能只剩标称的三成,效果还不如不贴。

判断去耦够不够,有个土办法:拿示波器配近场探头,在板子上方扫一遍,看电源平面的噪声峰值。噪声峰值超过电源电压的 5% 就要回头查去耦。这个办法不精确,但比拍脑袋强。

4. DDR3 页与接口页对账:DQ/DQS 分组、VREF 端接和 MIO 归属

4.1 从网络命名反推 DDR3 的位宽和分组

第 7、8 页是 DDR3 接口。看网络名就能读出位宽:PS_DDR_DQ0 到 PS_DDR_DQ31,一共 32 位;PS_DDR_DQS_P0/N0 到 P3/N3,四对差分选通;PS_DDR_DM0 到 DM3,四根数据掩码。

32 位配 4 对 DQS,说明是 4 组、每组 8 位。分组关系是固定的:

数据组数据线选通掩码
组 0DQ0 ~ DQ7DQS_P0 / DQS_N0DM0
组 1DQ8 ~ DQ15DQS_P1 / DQS_N1DM1
组 2DQ16 ~ DQ23DQS_P2 / DQS_N2DM2
组 3DQ24 ~ DQ31DQS_P3 / DQS_N3DM3

地址线是 PS_DDR_A0 到 A14,共 15 根;bank 地址 BA0 到 BA2,共 3 根。A14 加 BA2 这个组合,说明设计上留了单颗大容量 DDR3 的空间(8Gb 级别),实际贴的可能只是其中一档。

控制线包括 CLK_P/CLK_N 差分时钟、CKE、ODT、nCS、nRAS、nCAS、nWE、nRESET。这些线全部来自 PS 端的专用 DDR 控制器,不经过 PL,所以它们永远不需要在 Vivado 里手动约束引脚——MIG 会自动处理。这一点能帮很多人省掉瞎折腾的时间:PS DDR 的引脚约束不在 XDC 里,在 PS 配置里。

读这一页时要注意一个细节:所有网络名都带 _502 后缀,502 是 PS 的 DDR bank 编号。带这个后缀说明是专用 bank,不能挪作 PL 用。同理,MIO 的网络上带 _500 和 _501,PL 的网络上带 _34、_35、_13。看后缀就能立刻判断一根线归谁管,这个习惯在读大图时能省很多时间。

4.2 VREF 与端接:电阻分压和专用芯片的差别

第 7 页除了 TPS51200,还有一组 VREF_DDR3 和 VTT_DDR3 的网络,分别从芯片的 REFOUT 和 VO 出来。VREF 送到 DDR3 器件的 VREF 脚和 Zynq 的 PS_DDR_VREF0/1 脚,VTT 送到地址线的端接排阻。

有些低成本设计会把 VREF 直接做成两颗电阻分压,省掉 TPS51200。这么干能省几毛钱,代价是 VREF 的源阻抗高、噪声抑制差,DDR3 在高温或者电压波动时容易出现读写错误。这颗芯片本身不贵,除非是极限压缩成本的产品,否则不该省。

端接排阻的接法也要看清楚:地址线和控制线到 VTT 之间要有端接电阻,典型值在 40 欧到 50 欧之间,看具体拓扑。图上是把端接电阻做成了排阻,一路排阻管好几根线。这种做法的好处是省面积,坏处是排阻内部各路的匹配性不如分立电阻,做高频设计时要看排阻的一致性参数。

VTT 的去耦电容在这份图里画得比较散,建议改板时把 VTT 的电容集中放在端接排阻旁边,而不是靠近 TPS51200 输出。原因是 VTT 的电流回路是"芯片 VO → PCB → 端接排阻 → 地",电容放在负载端才能真正旁路掉端接瞬间的电流尖峰。

4.3 把 DDR3 的约束结论落到长度检查表

原理图阶段能确定分组,PCB 阶段要确定长度。DDR3 的长度匹配规则网上说法很多,我一般按这套来设初值,再根据实际叠层微调:

匹配项参考容差说明
同组内 DQ 之间±0.5mm8 根数据线互相之间
同组 DQS 与 DQ±0.5mmDQS 差分对内等长更严
DQS 差分对内 P/N±0.1mm差分对内部
组与组之间±2mm四组之间的 skew
地址/控制相对时钟±2mm全部地址线互相对齐

画完 PCB 导出长度表,用一段脚本做批量检查比人眼翻表格靠谱:

import csv from collections import defaultdict # nets.csv 三列:net,group,length_mm # group 取值示例:dq0/dq1/dq2/dq3/addr/clk TOL_INTRA = 0.5 # 组内 DQ 之间的容差,单位 mm TOL_INTER = 2.0 # 四个数据组之间的容差 TOL_ADDR = 2.0 # 地址控制线相对时钟的容差 rows = [] with open("nets.csv", newline="") as f: for r in csv.DictReader(f): rows.append((r["net"], r["group"], float(r["length_mm"]))) # 按组归类,先算每组内部的平均值和最大偏差 groups = defaultdict(list) for net, grp, ln in rows: if grp.startswith("dq"): groups[grp].append((net, ln)) group_mean = {} for grp, items in groups.items(): avg = sum(ln for _, ln in items) / len(items) group_mean[grp] = avg skew = max(abs(ln - avg) for _, ln in items) flag = "OK" if skew <= TOL_INTRA else "FAIL" print(f"[{flag}] {grp} 组内最大偏差 {skew:.2f} mm,均值 {avg:.2f} mm") # 再算四个组之间的偏差 if group_mean: gm = list(group_mean.values()) inter = max(gm) - min(gm) flag = "OK" if inter <= TOL_INTER else "FAIL" print(f"[{flag}] 组间偏差 {inter:.2f} mm") # 地址/控制线单独对齐 addr = [ln for net, grp, ln in rows if grp == "addr"] clk = [ln for net, grp, ln in rows if grp == "clk"] if addr and clk: ref = sum(clk) / len(clk) worst = max(abs(ln - ref) for ln in addr) flag = "OK" if worst <= TOL_ADDR else "FAIL" print(f"[{flag}] 地址线相对时钟最大偏差 {worst:.2f} mm")

这段脚本做的事很直接:读一张三列 CSV(网络名、分组、长度),先按组算内部偏差,再算组间偏差,最后单独校地址线。TOL_INTRA、TOL_INTER、TOL_ADDR三个常量就是上表里的容差,改板时按实际叠层和速率调整——DDR3-1600 和 DDR3-1866 的容差不是一个量级,速率越高越要收紧。

group字段的命名要和前面那张分组表对齐,dq0 到 dq3 对应四组,addr 是所有地址加控制线,clk 是差分时钟。CSV 由 PCB 工具导出,Altium、Cadence、KiCad 都能导,格式不一样就改读入那几行,核心逻辑不用动。

跑出 FAIL 不可怕,可怕的是不跑。我见过一块板子四组数据线的组间偏差做到 6mm,DDR 在常温下能跑,一到 60 度就开始随机挂——这种问题在原理图阶段完全看不出来,只能靠 PCB 长度表兜底。

4.4 接口页的 MIO 归属:一根线接错就是整板返工

第 6 页是 PS 的 MIO 区域,第 9 到 16 页是各个外设。这两部分必须对账,因为 Zynq 的 MIO 是复用的,一个外设占了哪几根 MIO,必须在 Vivado 的 PS 配置里一模一样地选出来。

把外设和 MIO 的对应关系从图上读出来,整理成表:

外设接口类型占用 MIO供电 bank
QSPI Flash四线 SPIMIO1 ~ MIO6MIO0_500
SD 卡SDIOMIO40 ~ MIO45MIO0_500
以太网 PHYRGMIIMIO16 ~ MIO27MIO0_500
USB OTGULPIMIO28 ~ MIO39MIO0_500
UART两线MIO48 / MIO49MIO1_501
WiFi/BTSDIOMIO40 起的另一组MIO1_501
EEPROMI2CMIO 上的一组MIO1_501

这张表里的 MIO 编号是按图中网络出现的位置推出来的,实际填 Vivado 时要以图纸上标的网络名为准。这里最容易踩的坑是 MIO 编号冲突:SD 卡和 WiFi 都用 SDIO 控制器,如果一个用 SD0、一个用 SD1 就没问题,如果两个都往 SD0 上挤,Vivado 会直接报错,而报错信息不会告诉你是原理图的问题。

USB 部分要分清楚两路:一路是 USB TO UART,走的是 USB 转串口芯片,再接到 PS 的 UART 上,MIO 只占两根;另一路是 USB OTG,走 ULPI 接口,要占 12 根(DATA0~7、NXT、DIR、STP、CLKOUT),还要一根复位。两者在图上画在不同的页,网络名前缀也不一样,读图时按前缀区分就不会混。

USB TO JTAG 那一路是独立于 PS 的,直接接 PL 的 TCK/TMS/TDI/TDO。这意味着 JTAG 调试不依赖 PS 端是否启动成功,即使 FSBL 挂了也能连上——这是排查启动问题的关键通路,改板时不要把它和 PS 的调试口合并。

以太网 PHY 那部分,除了 RGMII 的十几根线,还有 MDIO/MDC 两根管理线和一根 PHY_nRST 复位线。复位线的时序要和 PHY 的上电时序配合,图上把它接到 PS 的一个 GPIO 上,软件里控制复位时间。如果直接接 POR,PHY 可能在 PS 启动完成前就复位好了,后面再配置就来不及。

HDMI 那一路在 PL 侧,用的是 bank 34/35 的 IO。网络名里有 HDMI_CLK_P/N、HDMI_DATA0~2_P/N、HDMI_CEC、HDMI_HPD、HDMI_OUT_EN。这些信号里 TMDS 差分对要走 100 欧差分阻抗,CEC 和 HPD 是单端低速线。图上 HDMI_OUT_EN 单独引出来,说明板上有 HDMI 发送芯片或者电平转换,PL 只负责数据,输出使能由软件控制。

5. 复现避坑:五个烧片前必须排查的电源与配置陷阱

5.1 现象:QSPI 启动偶尔成功、多数卡死

原因:MIO 复用冲突。QSPI 占 MIO1~MIO6,其中 MIO3/MIO4 在某些配置下会被其他外设复用。如果 Vivado 的 PS 配置里 MIO 选择和原理图不一致,FSBL 读 Flash 时读到一半就停。

解决:把原理图上所有 MIO 网络名列出来,和 Vivado 里 PS7 配置生成的 MIO 分配表逐行对。对不上的地方以原理图为准改配置,不要反过来改图。这个对账动作建议做成一个 Excel,改板时直接复用。

5.2 现象:1.8V 那一路量出来 1.88V,PS 端 DDR 初始化失败

原因:反馈电阻按 E24 选值,偏差 4% 以上,叠加电阻本身 5% 精度,实际输出超出了 DDR 控制器对 VCCAUX 的容差要求。

解决:按 2.2 节的公式重算,用 1% 精度电阻,或者干脆改用可调基准的分压方案。量电压时用四位半表,不要用万用表的普通档,2% 的偏差在普通档上看不出来。

5.3 现象:JTAG 连不上,报找不到器件

原因:常见有三种。一是 CFGBVS_0 没接或者接错电平,配置 bank 的电压判断失效;二是 VCCBATT_0 悬空,虽然这颗脚只影响加密和部分配置,但悬空会导致 JTAG 链路不稳定;三是 DONE 信号被外部电路拉低。

解决:先量 CFGBVS_0 和 VCCBATT_0 的电压,再量 DONE 在上电后的状态。DONE 正常应该是低电平,配置完成后拉高。如果一直是低,查 PROGRAM_B 是不是被复位电路拉住没放开。

5.4 现象:DDR3 常温能跑,高温误码

原因:VREF 用电阻分压代替专用芯片,或者 VTT 的电容放错位置,导致端接电压在负载点偏离 0.75V。

解决:量 VTT 在端接排阻那一端的实际电压,不是量芯片输出脚。偏离超过 ±2% 就把 VREF/VTT 换成 TPS51200 这类专用芯片,同时把 VTT 电容挪到排阻旁边。这个改动在已打样的板子上做飞线也来得及,飞完立刻能验证。

5.5 现象:VIO 那一路电压不对,PL 外设全部不工作

原因:VDD_VIO 的可切换反馈网络里,0 欧电阻贴错位置。图上用 0 和 NC 区分不同电压档,生产时如果按默认 BOM 贴,贴出来的是 1.8V 档,但外设要求 3.3V。

解决:把 VIO 的档位选择做成明确的丝印标注,而不是靠 BOM 表区分。每块板子出厂前量一次 VIO 电压并记录,比事后排查便宜。自己改板时,如果只需要一个固定电压,干脆把切换电阻删掉,直接用固定分压,少一个变量。

6. 从原理图到 Vivado:把 PS 配置和 XDC 对上的具体做法

图读完了,最后一步是把纸面结论变成工程里能校验的东西。这一步做扎实,能省掉大量"板子明明是好的但就是跑不起来"的时间。

先建一个最小 block design,把 PS7 加进去,然后把原理图上读出来的外设配置逐项填进去。填完之后用 Tcl 把配置读回来核对:

# 在 Vivado 的 Tcl Console 里跑,核对 PS7 的关键配置 set ps [get_bd_cells -quiet processing_system7_0] if {$ps eq ""} { error "block design 里没有 PS7,先建一个" } # 要核对的属性列表,按原理图上实际用到的外设增删 set checks { CONFIG.PCW_QSPI_PERIPHERAL_ENABLE CONFIG.PCW_SD0_PERIPHERAL_ENABLE CONFIG.PCW_ENET0_PERIPHERAL_ENABLE CONFIG.PCW_USB0_PERIPHERAL_ENABLE CONFIG.PCW_UART1_PERIPHERAL_ENABLE CONFIG.PCW_USE_M_AXI_GP0 } foreach p $checks { if {[catch {get_property $p $ps} v]} { puts "属性不存在:$p" } else { puts "$p = $v" } } # 把 MIO 分配导出来,和原理图逐行对 report_property -all $ps | grep -i "PCW_MIO"

这段 Tcl 做两件事:先按列表核对每个外设的使能位是不是 true,再把所有 MIO 相关的属性导出来。checks列表里的属性名要和实际工程里使能的外设对应,用不到的直接删,别留着误判。report_property那行的输出会比较长,重定向到文件再看更方便:report_property -all $ps > ps_props.txt。

导出来的 MIO 属性和第 4 章那张表逐行对,对完就可以确定 PS 侧的配置是对的。这一步做完,PS 端的引脚问题基本排除,剩下的问题都在 PL 侧。

PL 侧要自己写 XDC。引脚号从原理图的第 5 页和第 16 页读,把网络名和球号对应起来:

# PL 侧 IO 约束,管脚号从原理图对应页读出后填入 # bank 34 的 LED set_property PACKAGE_PIN <BALL_LED1> [get_ports fpga_led1] set_property IOSTANDARD LVCMOS33 [get_ports fpga_led1] set_property PACKAGE_PIN <BALL_LED2> [get_ports fpga_led2] set_property IOSTANDARD LVCMOS33 [get_ports fpga_led2] # bank 34 的按键,注意上拉和去抖 set_property PACKAGE_PIN <BALL_SW1> [get_ports fpga_sw1] set_property IOSTANDARD LVCMOS33 [get_ports fpga_sw1] # 时钟:PL 侧 50MHz 单端输入 set_property PACKAGE_PIN <BALL_CLK50> [get_ports clk_50m] set_property IOSTANDARD LVCMOS33 [get_ports clk_50m] # 时序约束:50MHz 周期 20ns,留 20% 裕量写 16ns create_clock -period 16.000 -name sys_clk [get_ports clk_50m]

PACKAGE_PIN后面的<BALL_...>要替换成原理图上对应的球号,比如 LED 那颗在 bank 34 的哪个球,第 16 页写得清楚。IOSTANDARD必须和该 bank 的 VCCO 一致——bank 34 接的是 3.3V 就写 LVCMOS33,接 VIO 且 VIO 调到 1.8V 就写 LVCMOS18。写错不会报错,只会在实现阶段报 IO 标准冲突,而且报错信息指向的是 bank,不是具体哪根线。

时钟约束的周期用 16ns 而不是 20ns,是故意收紧的。综合和实现会按更紧的约束去优化,实际跑 50MHz 时裕量更足。这个习惯在做高速接口时尤其重要,等到时序报违规再回头改约束就晚了。

最后一步验证:把生成的 bit 流下载进去,用 ILA 抓一下 PL 侧的时钟和复位,确认时钟频率和复位极性都对。这一步看着多余,但能排除掉一大类"代码没问题但板子不响应"的情况——很多时候问题出在复位的极性反了,或者时钟根本没起来。

从那以后我每次拿到一份新板子的原理图,都会强制走一遍这个流程:先把 Block 表抄成树,再把电源反馈电阻逐个复算,接着把 MIO 分配抄成表,最后在 Vivado 里用 Tcl 把配置读回来对一遍。这一套走完大概两个小时,省下的是后面几天找不到原因的调试时间。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进