
搞FPGA的人一定经历过这种场景在Vivado里点了一下Program DeviceLED正常点亮功能全部正常项目交付前高高兴兴断电重启结果板子一上电程序没了一片空白。于是又赶紧打开Vivado重新烧反反复复折腾半天。其实问题就出在把“烧写”和“固化”混为一谈了。Vivado里的bitstream烧进去的是SRAM断电即失真正让程序“焊死”在板子上、上电自动加载的是固化操作。这篇文章把这两件事彻底讲明白从在线烧写到QSPI Flash固化再到MicroBlaze、Zynq平台下的ELF合并烧写以及常见的DRC报错和下载器识别问题都整理成可直接照着操作的经验帖。不管你是刚接触Vivado的新手还是被固化问题折磨过的老手应该都能从这里找到想要的答案。1. 先搞懂“烧写”和“固化”到底差在哪很多人第一次用Vivado时都会觉得烧写很简单无非是点两个按钮。但为什么有时候点完Program Device程序能跑有时候掉电就丢甚至有些配置方式烧完后板子根本无法启动这些问题的根源都在FPGA的底层架构上。1.1 FPGA的底子决定了它天生“容易失忆”绝大多数FPGA芯片基于SRAM工艺存储配置数据也就是查找表LUT和开关矩阵的控制逻辑都存放在SRAM单元里。SRAM的特点是读写快、可以无限次配置但掉电后数据清零。所以每次上电FPGA内部都是一张白纸必须由外部设备把配置数据喂给它它才知道自己该干什么。这个“外部喂数据”的过程就是FPGA的配置加载。无论是Vivado烧写还是固化后上电自动加载本质上都是在做同一件事区别只在于数据从哪里来加载方式数据来源掉电行为典型场景在线烧写Program DeviceJTAG直接写入SRAM数据丢失需要重新烧写调试、验证逻辑固化到Flash将配置文件写入外部非易失存储器上电后FPGA自动从Flash加载产品交付、离线运行从SD卡/eMMC加载文件系统中的bin镜像上电后由启动代码加载Zynq、K26等SoC平台打个比方在线烧写相当于给一间教室里的白板写好板书下课一擦什么都没了固化则是把板书拍照保存起来第二天上课直接调出照片抄上去。课堂内容一样但保存的介质完全不同。1.2 在线烧写和固化各自解决什么问题在线烧写是开发调试阶段的主力手段。改动逻辑后重新生成bitstream几秒到几十秒就能加载进芯片立即验证效果。它最大的优势是快而且不占用外部存储资源。固化则是把验证好的程序保存起来。产品要出货、设备要独立运行都必须做固化。常见做法是接一颗SPI Flash如W25Q128、S25FL128S等把配置镜像写入Flash上电后FPGA通过SPI接口主动读取Flash内容并加载。还有一类特殊情况是SoC平台比如Zynq和Kria系列。这类芯片里ARM处理器和FPGA逻辑共存启动过程更复杂上电后先由片内BootROM检查启动模式引脚MIO[4:0]再加载BootROM引导代码、读取分区表、加载FSBL和bitstream。所以在Zynq上做固化不只是写一个Flash那么简单还需要处理BOOT.bin和相关启动配置。1.3 配置模式选型SPI、BPI、JTAG还是SD卡除了JTAG和SPI FlashFPGA还有多条配置路径选择哪种取决于板卡设计和项目需求。JTAG模式最常用的调试和烧写入口优先级最高也能用于直接在线烧写SRAM。SPI Flash模式Master SPI上电后FPGA主动从SPI Flash读取配置。成本低、引脚少绝大多数板卡的固化方案都选它。BPI Flash模式Master BPI并行Nor Flash适合配置容量较大的芯片或需要高速加载的场景但连接引脚多板卡设计成本高。SD卡模式主要在Zynq UltraScale等平台使用boot镜像放在SD卡FAT分区里适合需要频繁更换镜像的开发阶段。SelectMAP/Slave SelectMAP并行总线被动加载一般出现在大型通信系统中普通项目很少碰到。在Vivado固化操作里绝大多数项目只要关心两件事JTAG在线烧写以及往SPI Flash里固化。把握住这两条主线就能覆盖日常开发和交付的全部需求。2. 烧写/固化前这些准备动作一次做对Vivado烧写操作本身不难但很多人卡在准备阶段硬件连不上、文件格式选错、版本对不上折腾半天还没走到点按钮那一步。这部分把准备工作里的关键环节全部过一遍。2.1 下载器和硬件连接的注意事项下载器是Host机和FPGA之间的桥。Xilinx官方的Platform Cable USB II、Digilent的JTAG-HS3以及大量基于FTDI芯片的兼容下载器都是常见选择。选型时注意一点下载器的供电能力通常很弱如果目标板卡没有独立供电尽量别指望下载器的3.3V输出撑起整块板子。JTAG引脚若出现电平不稳直接表现为设备扫描不到。接线规范上TCK、TMS、TDI、TDO四根信号线加上GND最好用短线直连避免飞线过长。调试经验里常见的问题是下载器接错引脚或者只接了主设备没接GND导致扫描链不稳定烧到一半报错。如果板卡上有多个JTAG设备串联务必确认JTAG链的顺序无误Hardware Manager里看到的设备列表要和板卡实际拓扑一致。2.2 配置文件的种类bit、bin、rbt、elf你手头到底该用哪个很多新手在烧写时会随手选一个文件发现报错就换格式这样很耽误事。把配置文件搞清楚一次就能选对。bitstream.bitVivado综合、实现后生成的原始配置数据包含器件信息、配置命令和有效数据。它用于在线烧写也作为生成其他格式的源文件。bin.bin去掉bit文件中的头部信息只保留纯配置数据流。Flash固化时通常要使用bin格式因为Flash只关心“从零开始存谁”。rbt.rbtASCII码表示的配置数据一般是调试或文档需要时使用普通烧写用不到。elf.elf软核处理器的可执行文件比如MicroBlaze的程序。它不能直接当作配置数据用需要先和bitstream合并成完整镜像。mcs.mcs和hex.hexIntel HEX/Motorola S-records等带地址信息的文本格式常用于工业烧录器或Flash编程器很少在Vivado Hardware Manager里直接使用。可以这样理解bit是“原图”bin是“去掉说明文字的纯像素数据”elf是“运行在上面的应用程序”。固化Flash要把原图转成纯像素数据而带软核的设计则要让处理器程序和数据通路融成一张完整的图。2.3 Vivado版本和器件支持矩阵的坑Vivado版本对器件的支持是有明确边界的。比如Vivado 2018.3对UltraScale系列支持良好但到了Vivado 2023.1旧器件Zynq-7000依然支持而更老的Virtex-5可能就只能在旧版本工具链里完成完整流程。项目开发时如果拿到一个旧工程的源码最好先确认工程版本能否在当前Vivado里正常打开避免烧写阶段出现诡异的兼容性问题。还有一类是Lab Edition的问题。Vivado Lab Edition是官方提供的精简版工具主要功能是硬件管理和烧写/调试安装包比完整版小很多。如果机器上没有完整Vivado但只想给版卡烧程序装个Lab Edition就够了。需要注意Lab Edition同样需要Lincense支持没有有效许可证Open Hardware Manager也会受限。2.4 驱动和系统环境最容易忽略的一环下载器插上电脑Vivado里却找不到设备绝大多数情况是驱动问题。Windows系统下手动安装下载器驱动、清理残留设备节点或者在设备管理器里强制更新驱动都是常用手段。在Linux环境下还需要确保用户有权限访问USB设备常见做法是添加udev规则否则即使检测到USB设备JTAG层也无法正常通信。我遇到过最典型的场景一台电脑上装过多个版本的Xilinx工具驱动相互覆盖后新版本Vivado能打开但识别不到Digilent下载器。最后把设备管理器里所有Xilinx USB设备全部卸载干净重启后重新安装目标版本驱动才恢复正常。清理驱动时不要嫌麻烦这一步省不了。3. 在线烧写Hardware Manager下的标准操作在线烧写是日常调试用得最多的操作。虽然界面很直观但一些隐蔽细节会直接影响烧写成败。下面按实际操作顺序拆解。3.1 打开Hardware Manager并连接目标在Vivado左侧Flow Navigator里展开Program and Debug点击Open Hardware Manager即可打开硬件管理界面。此时界面是空的需要点击Open Target并选择Auto Connect让工具自动枚举JTAG链上的设备。Auto Connect后Hardware window里会列出设备。常见显示是芯片型号加一个编号比如xc7z020_0、xc7a35t_1等。如果这里能看到设备说明链路没问题如果报错打开目标失败优先检查下载器驱动、线缆连接和板卡供电。连接成功后我习惯先在Device Properties里看一眼芯片IDCODE是否和实际器件一致。有的兼容下载器在扫描时会把IDCODE读错如果ID对不上烧写是注定失败的。这步提前确认能省下不少排查时间。3.2 Program Device的操作细节右键目标设备选择Program Device弹出的对话框里选择bit文件。很多人到这一步就直接点Program了但其实有两个细节值得注意如果只打算在线调试Debug/Probe等选项先不用管。除非你做片内逻辑分析仪需要配置ILA否则保持默认就行。Program时上位机通过JTAG把数据推进FPGA SRAM。这个过程会覆盖芯片内已有配置但不会写入任何非易失存储。所以Program完成后程序立刻生效掉电即失。点击Program后Vivado会显示编程进度条。通常在几百毫秒到几秒之内完成。结束后在Hardware Manager的Messages面板里看到Successfully programmed device的提示说明在线烧写成功。此时可以回头验证功能让板卡上电运行、观察指示灯、抓取信号。在线烧写就是为这个快速验证服务的所以没必要做额外动作。3.3 在线烧写的常见“假成功”和坑三种情况容易制造假成功假象Program显示成功但板上功能不工作。常见原因是bit文件生成时约束不完整或时钟未正常工作。这个阶段检查电源和时钟最有效。烧写中途报programming failed但仍显示设备连接正常。大概率是JTAG信号质量差或下载器供电不足。尝试降低JTAG时钟频率在Device Properties里调整或直接改用短粗杜邦线连接。下载器能扫到设备但Program后回读校验失败。这种情况和Flash本身无关而是SRAM配置过程中某个配置命令没有被正确解析要么文件损坏要么器件型号不符。还有一个高频操作误区在线烧写时不慎勾选了Hardware Manager里的“Program/Configure Debug Logic”把ILA调试核写进JTAG链导致后续烧写速度明显变慢。调试完成后建议关闭debug core避免影响固化流程。3.4 调试流程中为什么在线烧写才是首选固化操作虽然能掉电保存但它有一个明显缺点每次修改逻辑都要重新擦除和写入Flash耗时几十秒到几分钟不等而且频繁擦写会加速Flash磨损。在线烧写则没有这些顾虑只要bitstream生成完毕点一下就上板验证迭代效率高出很多。所以在项目开发阶段我都坚持用在线烧写做功能验证。只有等到软件形态基本冻结、功能验收通过之后才进入固化环节。这样可以最大限度减少Flash的擦写次数也避免在Flash损坏排查上浪费精力。4. 固化到Flashbin文件生成和QSPI烧写实操板卡要独立工作就必须把镜像固化到非易失存储器里。FPGA上电后主动从Flash加载配置从而跳过电脑和Vivado。这是交货前必做的一步也是最容易出问题的一步。4.1 为什么固化不能用bit文件必须先转成binbit文件头部包含Vivado版本信息、器件ID、命令序列等元数据这些信息适合JTAG编程器理解但不适合FPGA从Flash中直接读取。Flash固化要求FPGA在起始地址找到纯配置数据流因此要先把bit转换成bin格式再去写入Flash。有一种情况可以绕过bin某些Flash编程器支持直接解析bit文件并拆分有效载荷但在Vivado Hardware Manager里并没有这个功能老老实实转bin是最稳的方案。4.2 用Tcl命令生成Flash镜像在Vivado Tcl Console里执行write_cfgmem命令可以快速生成bin/mcs等多种格式。# 示例生成SPIx4模式的bin镜像 write_cfgmem -format bin -interface SPIx4 -size 128 -loadfile your_design.bit -file your_design.bin参数说明-format bin输出bin格式。-interface SPIx4指定SPI四线模式。如果板卡Flash使用单线SPI改成SPIx1。-sizeFlash容量单位Mb。128表示128Mbit16MB按实际Flash型号填写。-loadfile位流文件路径。-file输出文件路径。命令执行完成后工程目录下会生成bin文件。可以用文本编辑器打开bin文件看看开头是否有大片连续FF初步判断数据是否正常。如果你更习惯图形界面也可以使用Vivado的Edit Configuration Memory命令在GUI里选择文件、Flash型号和接口模式它本质上执行的就是write_cfgmem。两种方式结果相同看个人习惯。4.3 Add Configuration Memory Device的完整操作流程这一步是把bin文件真正写进物理Flash的关键连接设备并Open Target。在Hardware Manager界面右键设备选择Add Configuration Memory Device。在弹出的对话框里选择板卡上实际焊接的Flash型号。常见的是Winbond W25Q128、Micron MT25QL128、Spansion S25FL128S等。如果列表里找不到试试选择兼容型号或者同一系列其他密度型号但烧写前必须确认引脚兼容和指令集一致。点击OK后Vivado会提示你是否立即编程。建议选择Yes进入Programming对话框。在Programming对话框里Configuration file选择刚才生成的bin文件。State和Address都保持默认通常从零地址开始写入。点击Program等待进度条完成。Flash编程需要的时间远长于在线烧写这在几十秒到几分钟之间视Flash容量和JTAG速度而定。Programming完成后Vivado会提示是否验证Flash内容。建议选择Yes做一次回读校验确保写入数据与bin一致。固化完成后板卡断电拔掉JTAG下载器重新上电。观察FPGA是否正常加载并运行。如果Flash配置成功你会看到和在线烧写时一致的功能表现。这是整个固化流程最终的判断标准。4.4 Flash编程时的几个关键设置很多人在Flash编程对话框里看到满屏选项就发怵其实大部分保持默认即可。几个真正需要关注的点Configuration Interface必须和实际硬件匹配。板卡是SPIx4就从SPIx4进设计里是SPIx1就用SPIx1不一致会导致固化后无法启动。Address Range通常从0x0开始不用手动指定除非你打算做多镜像或启动备份。Erase选项Vivado默认会按需擦除Flash扇区。如果需要彻底清空选Full Erase。调试阶段建议用Erase Before Programming确保不会残留旧镜像。Blank Check写入前检查Flash是否已被擦除干净可先不做普通流程里意义不大。这些设置在大多数项目里不需要改动只有实现多镜像启动或者验证Flash质量时才需要深究。5. 带软核的固化MicroBlaze的ELF合并和Zynq启动链如果设计里加了MicroBlaze软核或者用的是Zynq SoC固化的复杂度会上升一个档次。它不再只是把bit塞进Flash还要把处理器的可执行程序和FPGA配置数据合并成同一个启动镜像。5.1 为什么添加了软核之后bit文件不再是完整镜像MicroBlaze等软核处理器运行时指令和数据存放在FPGA内部存储器或外部DDR中。这意味着单靠bit配置文件只能把FPGA的硬件逻辑配好软核程序还没有着落。上电后MicroBlaze需要从某个来源取指令执行如果指令不存在系统自然无法工作。常见的做法是把编译好的ELF文件合并到bit文件里。合并后MicroBlaze代码会被放置到指定的Block RAM地址和FPGA配置一起写入Flash或在线烧进SRAM。这样上电后硬件逻辑和软件程序同时就位系统才能跑起来。5.2 在Vivado/SDK里合并ELF和bit的两种方式第一种方式是图形界面操作。在Xilinx SDK中创建好应用工程并编译生成ELF后菜单栏选择Xilinx - Program FPGA在弹出的编程对话框里配置bitstream文件以及BMM信息并在Software/Processor里填入elf文件路径点击Program即可。SDK会自动调用data2mem或updatemem工具完成合并。第二种方式是命令行操作适合脚本构建和自动化发布场景。在Vivado或SDK的Tcl控制台里执行# 方式一基于BMM和MMI合并 data2mem -bm system.bmm -bd elf_file.elf -bt bit_file.bit -o b design_out.bit # 方式二使用updatememVivado推荐 updatemem -meminfo system.mmi -data elf_file.elf -proc system_i/microblaze_0 -bit bit_file.bit -out design_out.bit注意这里的system.mmi文件是Vivado生成的内存映射信息文件它描述了哪些Block RAM网表区域与某个AXI外设相关。没有MMI文件updatemem就不知道该把ELF数据插到哪块内存里。在Vivado中默认会为带MicroBlaze的设计生成MMI文件路径一般在工程目录下的*.runs目录里。合并完成后把design_out.bit作为固化源文件用第4章提到的方式生成bin并写入Flash即可。这样上电后程序才会自动运行。5.3 Zynq平台BOOT.bin与FSBL是怎么回事Zynq则完全是另一套玩法。它的启动阶段划分非常明确上电后由片内BootROM读取启动模式引脚MIO[4:0]确定从哪里读取镜像。BootROM引导到第一阶段启动引导程序FSBLFirst Stage Boot Loader。FSBL初始化DDR、配置PS端时钟并通过PCAP接口把FPGA bitstream配置进PL端。最后FSBL加载U-Boot或直接加载裸机应用。所以在Zynq上做固化需要做的事情是将FSBL、FPGA bitstream、应用程序分别准备好然后用SDK的Create Boot Image工具打包成BOOT.bin再写进QSPI Flash或SD卡。打包BOOT.bin的关键在于分区顺序分区1是FSBL分区2是bitstream分区3是应用程序。如果顺序错乱板卡上电后就会卡死或一直重启。在SDK里创建Boot Image时按下图顺序依次添加即可每个分区都要确认使用的文件路径无误。固化BOOT.bin到Flash的操作和在普通FPGA上固化bin类似仍然是在Hardware Manager里Add Configuration Memory Device然后选择BOOT.bin文件。要理解的是Zynq掉电后Flash里最终存的就是这份BOOT.bin而它的加载流程由BootROM自动接管。5.4 国产工具的对照Procise固化思路一脉相承现在很多国产FPGA厂商如紫光同创等也推出了自己的开发工具例如Procise。用过Vivado的人再去操作Procise会发现界面和流程有不少似曾相识的地方同样是综合、布局布线、生成位流然后进入编程和固化流程区别主要是术语和细节设置。在Procise里也分为在线编程和固化编程两步固化Flash时仍然要先生成合适的烧写文件再选择Flash型号、配置地址和接口模式。这意味着掌握Vivado的固化和烧写思路迁移到国产工具链时只需要对照菜单就能上手。核心不变搞清在线与固化的区别搞清配置文件该以什么格式落到Flash里剩下的都是工具操作的相似套路。6. 这些高频报错我替你们都踩过了烧写和固化过程中会碰到各色报错。有些错误信息在Vivado里看似宽泛实际根因非常具体。我挑几个高频问题把排查思路分享出来。6.1 DRC RTSTAT-2配置引脚相关问题DRC RTSTAT-2这个报错大多会在工程综合后或生成bit时弹出提示某个配置相关引脚状态有风险。常见根因是配置电压VCCONN未供电或者配置引脚的电平约束不当尤其是在使用eFUSE加密、或外部配置模式时更容易触发。排查建议检查原理图中VCCONN供电是否满足器件要求确认JTAG模式下的保留引脚如DONE、PROG_B等是否有正确上下拉。通常情况下DONE引脚需要一个上拉到VCC的高阻或弱上拉确保配置完成后FPGA释放该信号。如果原理图设计没问题再看约束文件里是否对配置引脚添加了不当的FIXED约束。这类问题一旦出现大概率是硬件设计的锅拿软件反复改约束往往解决不了要和硬件工程师一起核对供电网络和上下拉电阻。6.2 Implement Design变红先看消息再做这四步Vivado界面里Synthesis Implementation显示红叉是新手最容易慌张的情况。这通常不是烧写环节的问题而是综合或实现阶段产生了错误。红叉只代表状态真正的错误信息在Messages窗口或Reports里。遇到红叉我的习惯做法是打开Flow Navigator里的Messages窗口切到Errors标签先定位第一个错误。看错误出现的环节如果是Synthesis报错优先查HDL语法和IP配置如果是Implementation报错优先查时序约束、引脚分配和资源占用。修复后重新运行综合或实现。注意修改过约束文件后要实现一次Reset Runs确保旧的中间结果不污染新流程。如果再跑还是红叉把错误信息里的关键文件名和行号抓出来在网上一搜通常能找到类似的案例。最忌讳的是一口气改十个地方再重新跑这样错误源头很难定位。一次只改一处保持中间产物可复现才能真正解决问题。6.3 串口烧写失败的背后逻辑“串口烧写失败”听起来像单片机场景但在Zynq或某些FPGA平台的串口加载模式下也常见。典型的排查路径是确认启动模式引脚拨码是否拨对位置确认波特率配置和上位机端一致确认镜像文件和芯片型号匹配确认PC串口驱动没有挂起。我处理过最典型的一次串口烧写失败是启动模式引脚被误拨到了SD卡模式串口那边当然等不到任何数据。还有一次是镜像是老版本编译的加载后ARM没有正确进入FSBL卡在跳转阶段表现也是“烧写失败”。串口烧写不像JTAG那样能看到详细状态更多靠观察板卡打印log判断卡点。6.4 JTAG扫描不到设备从驱动到信号的全链路排查这个问题的排查优先级顺序非常明确驱动打开设备管理器确认USB设备是否被正确识别为Xilinx USB Cable。没有 → 重装驱动。供电确认板卡已上电JTAG口参考电压是否正常。VMOD引脚如果有需要和板卡IO电压一致。接线TCK/TMS/TDI/TDO是否一一对应GND是否连通。高位序错误会导致设备列表显示乱码或扫描失败。JTAG链拓扑多个设备串联时一个设备虚焊或损坏会导致整条链断开可以把坏设备短路跳过后再扫。IDE状态如果Vivado卡在hang住的进程中先关掉所有Hardware Manager实例重启后再连。这套顺序基本能定位九成以上的JTAG连接问题。如果扫描到了设备但ID不对再检查芯片型号是否选择正确。7. 固化完成之后的验证动作建议一个都别省固化最后一步不是“看到Programming Successful”就算完。我的习惯是做完一套完整的上电验证才敢把板子交出去。验证清单如下完整断电拔掉JTAG和USB线再上电观察程序是否自动运行。连续做3次掉电重启排除偶发性加载失败或Flash读取不稳定。如果程序里有运行状态指示LED翻转、打印信息确认每次上电行为一致。如果板卡有多个供电档位分别记录各电压是否正常。条件允许时用示波器看DONE引脚的上升沿判断配置是否成功释放逻辑。这轮验证通过后才能定义“固化成功”。大多数交付后的“板子跑不起来”问题都发生在复位时序异常或供电斜坡时间过长的场合这些在线烧写时很难发现只能靠完整的上电验证去兜底。我个人还有个小习惯每块板子在第一次固化前先用blank check确认Flash是全新的。尤其是从生产线上拿回的板子Flash里可能烧过测试镜像如果不确定是否彻底擦除先做一次全片擦除再写bin。这能排除很多“明明写了程序但就是跑不对”的灵异问题。整个烧写和固化的流程说起来就两件事在线烧写验证逻辑固化Flash保存逻辑。但只要往深一层看配置文件格式、启动链、Flash型号、版本匹配和信号质量每一环都能成为一个坑。希望这篇文章能帮你把这块拼图一次补齐以后在Vivado里做烧写和固化时能少走弯路。