说实话,ZYNQ选型这事,我一开始也栽过跟头。之前做某图像采集项目,起初选了7020,逻辑用到了八成多,BRAM直接爆了,DSP也快见底,算法团队还想往里塞算子,最后只能硬着头皮往7045迁移。结果发现换芯片根本不是改一下型号那么简单:PCB要动,电源要动,DDR引脚要重排,Vivado工程里的IP要重新生成,连FSBL和设备树都得推倒重来。这个过程中踩了不少坑,也把选型和迁移的整套逻辑理清楚了。这篇就把7020和7045的资源对比、选型计算和项目迁移避坑经验一次讲透,适合正在纠结这两颗料的硬件工程师、FPGA开发者,以及做ZYNQ裸机、DMA、烧写固化相关工作的人参考。
1. 为什么7020和7045的对比不是换个器件那么简单
很多人第一眼看到的是“7020便宜、7045资源多”,但在工程上,这两颗芯片几乎是两套设计方案。7020属于Zynq-7000家族里的入门到中端档位,PS端和7045一样都是双核Cortex-A9,但PL端资源差了四倍多,封装和引脚也完全不是一个级别。选型的时候如果只盯着逻辑单元数量,后面迁移基本会处处碰壁。
1.1 一张表看懂两颗芯片的硬资源差异
先看官方数据,这里以常见的XC7Z020和XC7Z045为例,数据主要参考Xilinx的DS190和DS187手册,速度等级通常选-1或-2,PS端主频可以跑到766MHz到1GHz,具体看等级。
| 资源项 | XC7Z020(7020) | XC7Z045(7045) | 差异说明 |
|---|---|---|---|
| 可编程逻辑单元Logic Cells | 85K | 350K | 约4.1倍 |
| CLB LUT | 53,200 | 218,600 | 约4.1倍 |
| CLB Flip-Flop | 106,400 | 437,200 | 约4.1倍 |
| Block RAM | 140块,共4.9Mb | 545块,共19.2Mb | 约3.9倍 |
| DSP Slice | 220个 | 900个 | 约4.1倍 |
| 硬核PCIe | 无 | 有 | 7020只能PL做软核 |
| GTX高速收发器 | 无 | 有,具体lane数看封装 | 影响高速接口方案 |
| PS处理器 | 双核ARM Cortex-A9 | 双核ARM Cortex-A9 | 基本相同 |
| PS最高频率 | 766MHz~1GHz | 766MHz~1GHz | 选-3等级可上1GHz |
| 常见封装 | CLG400 / CLG484 | FFG676 / FFG900 | 引脚、尺寸完全不同 |
这张表十几秒就能看懂,但真要用来做决策,还得再往深想一层。Logic Cells是宣传值,工程上实际看LUT、FF、BRAM、DSP四项是否够用。我见过有人只看逻辑单元数量觉得够了,结果BRAM先爆了,算法没法落地,最后只能改架构,非常被动。
另一个经常被忽略的点是GTX和PCIe。7020没有GTX,也没有PCIe硬核,而7045有。如果项目里将来可能接PCIe采集卡、CameraLink转接板、高速AD/DA,那7020基本就不适合。反过来说,如果项目就是普通工业控制、电机驱动、千兆网透传,7045的GTX和PCIe反而是多余成本的来源,功耗也压不住。
1.2 资源参数背后的真实需求映射
选型不能只数资源,要往回映射到具体算法模块。举个例子,做720p灰度图像处理,一帧原始数据是1280乘以720约等于0.92MB。7020的BRAM总量是4.9Mb,换算过来只有0.61MB左右,连一帧都缓存不下,必须靠PS端的DDR;7045的BRAM有19.2Mb,约2.4MB,可以缓存两帧以上,这时候设计流水线就有很多灵活空间。很多图像算法之所以在7020上跑不动,不是逻辑不够,而是BRAM这头堵死了。
再比如卷积运算。一个5x5的卷积核,一个输出像素需要25次乘加。如果做FPGA全并行,一个像素周期内就要完成数十次乘加,DSP消耗是几十到几百不等。7020只有220个DSP,做三路并行大卷积核很容易吃紧;7045有900个DSP,余量明显宽裕。算资源时建议这样估算:先把每个模块需要的LUT、FF、BRAM、DSP列一张表,累加后除以器件资源,看看占用率是多少。经验上,综合占用率最好控制在70%到80%以内,超过80%布局布线就开始吃紧,时序收敛难度指数上升,工具跑多久都难收敛。
这里多说一句,资源余量不是玄学,是给接口逻辑、跨时钟域、调试逻辑留的。很多项目在联调阶段会临时加在线抓信号、触发逻辑、计数器,这些都要占资源。如果一开始就压到95%,后期每加一个ILA模块都要拆东墙补西墙,痛苦得很。
2. 从7020迁移到7045前,先算清硬件这笔账
如果资源评估之后确认必须从7020迁到7045,先别急着开Vivado,硬件层面的账要先算清楚。这个阶段最容易出问题,而且一出问题就是改板、换物料、返工的大问题。
2.1 封装、引脚与PCB改动成本
7020常用CLG400或CLG484封装,7045常用FFG676或FFG900封装。两者球距、封装尺寸、扇出规则完全不一样,基本意味着PCB要重新设计。不要指望用飞线或者转接板把7020的板子改成7045,电源网络、去耦电容、DDR拓扑都撑不住。
引脚上最大的坑是bank分配和电压域不一样。Zynq的IO分HR和HP bank,不同封装下bank的位置、可用的HR/HP数量都不同。原来在7020上用的某个bank可能到7045封装里变成了另一个bank,VCCO电压、HSIO电平都要重新核对。我见过有人迁移后直接把旧XDC里的引脚编号平移过去,结果DDR控制器复位失败、千兆网初始化失败,查了两周最后发现是引脚分配错位。
PCB改版时,重点检查三块:DDR走线拓扑、VCCINT电源平面、GTX差分走线。DDR部分如果7045封装的引脚位置变化很大,原来的数据线、地址线分组会乱掉,MIG配置也要同步改。电源平面方面,7045的PL逻辑规模大,动态功耗比7020高得多,如果沿用7020的电源铜箔宽度和过孔数量,跑大逻辑时VCCINT很容易跌落。
2.2 电源、时钟与DDR设计差异
电源设计是迁移中最容易低估的一环。7020在中等资源利用率下,内核电流大致在1安培到2安培级别;7045如果跑到70%以上利用率,动态电流可以到4安培甚至更多。DC-DC选型时不要只看平均电流,要看瞬态响应。FPGA在高频翻转时电流是脉冲式的,电源模块动态响应不够快,电压跌落几十毫伏就可能导致时序崩溃或者偶发死机。
我遇到过一台7045设备,跑图像算法时不定时重启,最后用示波器抓VCCINT波形,发现负载突增时电压跌了将近0.1V,最低点已经接近芯片工作下限。后面把DC-DC的开关频率调高、加了大容量陶瓷电容、重新优化了反馈采样位置才解决。这个坑在7020上不明显,因为电流小,IR压降不容易体现,但到了7045就暴露了。
DDR设计上,7020和7045的PS端DDR控制器本质上是一样的,支持DDR3、DDR3L、LPDDR2,但不支持DDR4。迁移到7045后,因为封装引脚变了,原有的DDR走线、引脚分组、字节通道都要重新分配。操作上不能直接把旧MIG工程拿来用,必须在新器件下重新生成MIG,逐项核对DDR型号、位宽、Bank地址、时序参数。特别要注意DQS、DM引脚的约束组,这类错误通常不会有明显报错,但跑内存压力测试时随机出错。
时钟方面,PS端的时钟输入仍然是PS_CLK,频率范围一般在30MHz到50MHz,这个不影响。但7045如果要启用GTX,就需要额外设计GTX参考时钟,常见的是125MHz或100MHz差分时钟,802.3协议通常还要多个频率相位对齐。7020完全没有GTX,很多旧板子根本没有对应的时钟buffer和匹配电路,迁移时往往要重新加。
2.3 PCIe和高速接口带来的连锁反应
7045的GTX和PCIe硬核是它比7020强出许多的地方,但这也是迁移时新增工作量最大的部分。PCIe硬核不是简单配个IP就能用,涉及到参考时钟、复位逻辑、LTSSM状态机、DMA地址映射,还要配合PL端逻辑做报文中断处理。这些工作在7020上完全不存在,等于软件和逻辑团队都要补课。
如果项目原本没有高速接口,纯粹为了资源数从7020升到7045,那GTX相关电路可以先不画,但要注意7045的封装里,GTX引脚所在的bank即便不用,也必须接正确的参考地或端接,不能悬空。很多原理图设计人员习惯性把不用的高速引脚空着,结果板子画完上电,PL温度异常,查半天是GTX电源域没处理干净。
反过来,如果项目未来三年都看不到PCIe或万兆光口需求,我反而建议慎重选7045,成本高、功耗大、设计复杂度高。中间档位还有个XC7Z030,资源在两者之间,有GTX但没有PCIe硬核,也能做三路以下的高速串行通道,预算敏感时可以考虑。
3. Vitis/Vivado工程迁移实操流程
硬件设计确认没问题后,才轮到软件工程迁移。这里我按从Vivado工程到Vitis的完整链路写一下步骤,重点是换器件后哪些东西必须重建、哪些东西容易忽略。
3.1 Vivado器件替换与IP更新
先把原工程备份一份,这个老生常谈,但我真见过有人迁移到一半原工程被自动更新坏掉,追悔莫及。然后在Vivado里做器件替换,操作路径是Tools -> Project Settings -> General -> Project Device,把器件从xc7z020换成对应的7045,比如xc7z045ffg676-2。也可以直接用Tcl命令行:
set_property -name {part} -value {xc7z045ffg676-2} [current_project]改完器件后,IP状态会变成需要升级或重新生成。重点检查这几个IP:MIG DDR控制器、AXI Interconnect、Clocking Wizard、AXI DMA。MIG必须重新配置,因为引脚分组和封装变了;AXI Interconnect可能会根据新器件的位宽规则自动调整,但建议手动确认数据宽度;Clocking Wizard要重新生成时钟,检查是否和白皮书约束冲突;AXI DMA如果原来跑在较低频率,换到7045后可以试着往上拉频率,但要重新跑时序验证。
XDC约束文件是迁移中最大的坑。不同封装的物理引脚几乎不兼容,单纯把约束文件里的引脚名称做正则替换是危险的。我习惯的做法是:先把原工程综合后的资源报告和I/O报告导出存档,然后新建一个空约束文件,按照新原理图逐条填写引脚约束,而不是从旧XDC复制。这个过程耗时,但能排查出原理图里bank电压错误、引脚冲突等问题。
完成更换后,跑一遍综合和实现。7045的资源多,通常时序更容易收敛,但如果原设计在7020上已经压着时序线过的,换到7045后不一定直接通过,尤其是时钟树结构变化之后,部分路径的约束需要重配,比如创建生成时钟的从节点位置变了,需要同步修改。
3.2 FSBL、设备树与BSP重建
换完器件后,Vivado侧导出新的硬件文件,然后进入Vitis(旧版本叫SDK)。这里强烈建议新建一个platform工程,不要用旧platform硬改。很多人图省事直接在新Vitis里挂旧BSP,结果外设配置、中断号、DDR地址这些参数还是按7020生成的,启动后各种诡异现象。
新platform生成后,FSBL会自动换成新器件对应的版本。要注意FSBL里的DDR初始化参数,如果新板子的DDR容量变了,或者DDR型号变了,必须更新DDR参数,否则FSBL启动阶段就卡住。DDR参数的来源是Vivado里的MIG配置,或者PS DDR配置界面,两者要一致。
裸机应用的BSP也要重新生成,尤其是外设配置。比如原来用SDIO、SPI、UART、USB,BSP里对应的驱动版本、时钟频率、中断ID都要重新确认。Zynq的PS外设中断ID在器件迁移后一般不变,但PL侧自定义IP的中断号取决于Vivado工程里对Interrupt Controller的连接,如果地址映射变了,裸机代码里的XScuGic配置要同步修改。
设备树方面,Linux场景下要重点核对memory节点,例如DDR实际容量为1GB时:
memory@0 { device_type = "memory"; reg = <0x0 0x40000000>; /* 1GB DDR3 */ };如果设备树里DDR大小和新硬件不一致,Linux能启动但跑大任务就随机崩溃。还要检查PL侧设备树节点中的中断属性,确保和Vivado工程导出的中断号一致。Zynq设备树的很多节点是固定外设,这部分迁移后变化不大,但FPGA节点、DMA节点、自定义IP节点建议逐个过一遍。
3.3 启动镜像生成与QSPI固化烧写
工程重建完后,生成BOOT.BIN是Zynq启动的关键一步。在Vitis里创建Boot Image时,顺序是FSBL、Bitstream、应用App(如果是裸机),或者FSBL、PMU、ATF、U-Boot、kernel image(Linux方案)。普通裸机方案最简单,三件套按顺序加进去就行。
烧写到QSPI Flash有两种常用方式。一种是在Vitis菜单里选Xilinx -> Program Flash,界面里选择BOOT.BIN路径,偏移地址填0,Flash Type选择对应的qspi型号,点击烧写。另一种是命令行方式,习惯自动化流程的人喜欢用program_flash:
program_flash -f BOOT.BIN -offset 0 -flash_type qspi-x4-single -fsbl fsbl.elf -cable type xilinx_tcf url "TCP:127.0.0.1:3121"这里有个经典问题:为什么烧Flash时要带fsbl?因为program_flash工具需要FSBL来初始化DDR,然后把BOOT.BIN整体搬到DDR里,再从DDR写入Flash。这就自然引出了众说纷纭的“JTAG固化Flash必须用DDR吗”这个问题,下面专门展开讲。
4. 迁移后的常见问题排查与避坑记录
这一章算是我踩坑集锦,也是很多搜索热词背后的真实痛点。项目迁移过程中,烧写固化、DMA、裸机USB、上位机串口通信这些环节最容易出问题,我按场景逐个梳理。
4.1 固化烧写类:JTAG烧Flash到底要不要DDR
先给明确结论:不是绝对必须,但标准工具链使用方法下一定会用到DDR。Zynq的上电启动过程是BootROM先把FSBL加载到片内OCM里执行,FSBL的第一个大动作通常是初始化DDR。之后DDR就可以作为数据中转区。program_flash这类工具要烧写的镜像一般有几百KB到几十MB,OCM只有256KB,放不下,所以必须先把镜像放在DDR里再写进Flash。
网上经常能搜到“7020使用JTAG固化Flash时必须使用DDR吗”,实际场景答案是:如果只是想把一个很小的FSBL烧进Flash,理论上可以改FSBL,跳过DDR初始化,直接从OCM搬到Flash控制器,但这样做没有任何收益,反而绕。更常见的坑是,有人烧写BOOT.BIN后拔电重启,发现QSPI启动失败,第一反应是DDR没初始化,其实大概率是Flash型号配置错误或者偏移地址不对。
排查思路大概是:先确认上电后MIO启动模式引脚拨到了QSPI档位;再从Vivado Hardware Manager里读Flash ID,确认软件识别的型号和板子上的一致;最后确认BOOT.BIN偏移,QSPI通常从0地址启动,如果偏移到了某个地址,BootROM就找不到镜像头。烧完后不要直接关电,先读回Flash内容,对比前几百字节是否和BOOT.BIN一致,这条经验能节省大量重复烧写时间。
4.2 AXI DMA与缓存一致性问题
Zynq平台做DMA传输,最常见的问题是PS和PL之间数据不一致,尤其是跑Linux或带Cache的裸机工程时。现象经常是DMA能搬数据,但数据偶尔旧、偶尔新,或者中断丢了。核心原因是CPU有Cache,DMA直接访问DDR,两边看到的数据不同步。
解决办法就是正确的Cache操作。发送数据前,将buffer cache flush;接收数据后,将buffer cache invalidate。在Xilinx的驱动里常见写法是:
Xil_DCacheFlush(); // 或者 Xil_DCacheInvalidate();如果工程用了AXI DMA,还要注意描述符地址和数据buffer地址的对齐。描述符建议放在DDR的低地址区域,数据buffer按32字节对齐,避免跨4KB边界。还有一个隐藏点:DMA的Buffer大小如果设置得比实际传输大很多,Cache操作的区间也要对应,不能只刷前一半,否则后半段数据可能被Cache残留污染。
迁移到7045后,PL侧AXI时钟可以跑更高,DMA吞吐量理论上更大,但跨时钟域稳定性反而更敏感。建议做长时间压力测试,不只测传输速度,还要盯着系统跑24小时以上看有没有偶发中断丢失。另外,如果原来在7020上是用AXI GP端口做DMA,迁移后7045上有更多高性能接口选项,如HP端口,可以降低CPU参与度。
4.3 裸机USB与libusb通信的坑
Zynq的PS端自带USB控制器,通常切换到Device模式做USB从设备,和上位机通信。这块在7020和7045上差别不大,但很多团队从旧工程迁移后会在USB上踩坑。常见现象:USB插入电脑后枚举成Unknown Device,或者枚举成功但端点传输一直失败。
排查顺序一般是:先量USB PHY的参考时钟是否正常,Zynq PS USB需要外部USB PHY,常用的有USB3320等,PHY的CLKOUT要连到PS的USB时钟脚;再看MIO配置,USB接口的MIO引脚是否被其他外设复用;最后查软件里USB描述符和端点配置。Xilinx裸机USB Device驱动里,比较常见的坑是配置了错误的端点地址,主机端请求的端点号和Zynq端实际注册的不一致,导致控制传输之后数据端点一直处于STALL状态。
上位机用libusb访问裸机Zynq USB设备,首先要解决驱动识别问题。Windows下libusb需要WinUSB驱动,通常用Zadig把设备驱动替换成WinUSB,否则libusb找不到设备;Linux下要写udev规则,否则普通用户没有权限open设备。通信时的坑主要来自端点空闲状态处理,Zynq裸机USB设备端如果没有及时调用接收接口,主机发数据时会超时。建议把端点读取放在循环线程里,配合中断事件做联动。
4.4 上位机QT串口库编译与波特率不准
这个场景很多做Zynq上位机的人都会遇到。QT里用串口有两类方案,老工程可能用qextserialport,新版直接用QSerialPort。qextserialport在较新QT版本里编译偶尔会报错,主要是因为connect语法或者信号槽宏不兼容,建议新工程直接选QSerialPort,省去维护第三方库的麻烦。
Zynq端串口波特率不准导致上位机乱码,是另一个高频问题。PS端UART时钟来自IO PLL,如果PLL配置和实际晶振频率不匹配,波特率分频就会产生误差,误差超过2%就可能出现乱码。排查时先用示波器测TXD引脚的电平宽度,比如9600波特率时,一个bit宽度大约是104微秒,如果明显偏差,就去核对UART时钟配置。换器件后最容易碰到的问题,是时钟向导里的输入频率没按新板子的晶振改,或者PS_CLK频率和BootROM预期不一致导致整个系统时钟偏了。
还有个小细节:QT上位机和Zynq设备之间如果经过USB转串口,某些廉价转换芯片在高速波特率下会乱码,这并不是Zynq端问题。测试时尽量用示波器或硬件串口直连先排除链路问题,再定位是软件还是硬件。
最后再分享一个我自己的心得。迁移到7045后,不要把旧工程里的资源使用率优化习惯丢掉。7045虽然资源多,但布线规模大,综合实现时间也比7020慢不少。如果能在算法层面把DSP用量降下来,比如用CSA近似乘法替代部分乘法器,或者把BRAM的位宽利用率提升,7045跑起来会更从容。项目选型也是一样,7020和7045之间不是简单二选一,而是要看整机功耗、成本、PCB改版周期和团队维护能力。如果只是资源紧张,先试试逻辑优化和IP调参,可能根本不用换芯片;如果确实要换,硬件账、软件账、测试账三笔一起算,才能把迁移风险降到最低。