
1. 为什么“下载成功”不等于“固化完成”很多刚接触 FPGA 的朋友第一次把比特流下载进板子看到 LED 闪起来、串口有输出就以为大功告成。结果一断电再上电板子像什么都没发生过一样——程序没了。这不是板子坏了也不是工程有问题而是你只完成了下载到 FPGA 内部 SRAM这一步没有做固化到外部 Flash。FPGA 的主流架构是基于 SRAM 的查找表结构SRAM 有个天然特性掉电即失。配置数据存在 FPGA 内部的配置存储器里断电就清空。所以每次上电FPGA 都需要从外部非易失存储器通常是 SPI Flash 或 BPI Flash重新读取配置数据。固化这件事的本质就是把 PC 上生成的比特流文件转换成 Flash 能识别的格式再写进板载 Flash 芯片里让 FPGA 上电时能自己“读回来”。这里要区分三个容易混淆的概念比特流文件.bitVivado 综合实现后生成的原始配置文件面向 FPGA 内部配置存储器不能直接烧进 Flash。MCS 文件把 .bit 按 Flash 的地址空间和位宽重新编排后的文件是烧录器真正写进 Flash 的内容。下载Program通过 JTAG 把 .bit 直接灌进 FPGA掉电丢失用于调试。固化Program Configuration Memory Device通过 JTAG 把 .mcs 写进板载 Flash掉电不丢用于量产和交付。新手最容易卡在“MCS 文件怎么生成”和“生成完怎么烧”这两步。下面我按实际操作的顺序把整条链路拆开讲清楚包括每一步背后的原因、参数怎么选、以及我踩过的那些坑。提示固化操作会覆盖 Flash 里原有的内容。如果板子上有出厂固件或别人的程序先确认是否可以擦除必要时先备份。2. 固化前的硬件与工程确认清单在动手生成 MCS 之前有几件事必须先确认否则后面大概率会报错或者烧进去不启动。这部分是很多教程跳过、但实际最耗时间的环节。2.1 确认 Flash 型号与连接方式打开原理图找到 FPGA 配置相关的 Flash 芯片记录以下信息需要确认的信息为什么重要常见取值Flash 型号决定容量、扇区大小、烧录算法W25Q128、W25Q64、S25FL128 等接口类型决定 MCS 的位宽和数据排列SPI x1 / x2 / x4容量决定 MCS 文件大小是否放得下16Mb、64Mb、128Mb数据位宽影响 MCS 生成时的位宽设置1、2、4是否与 FPGA 配置专用引脚相连决定上电能否自动加载通常接在专用配置 Bank如果原理图不在手边可以在 Vivado 硬件管理器里连上板子后通过Open Hardware Manager → Add Configuration Memory Device搜索型号。但更稳妥的做法还是查原理图因为自动识别有时会因为 JTAG 链路问题识别不到。2.2 确认工程已经成功生成比特流MCS 是从 .bit 转换来的所以前提是工程已经完成综合、实现、生成比特流且没有严重错误。如果你在Implementation阶段看到implement design变红或者生成比特流时报 DRC 错误比如DRC RTSTAT-2那要先解决这些问题固化的事往后放。一个快速判断方法在 Vivado 的Design Runs里看write_bitstream是否显示Complete并且能在工程目录下找到.bit文件。路径通常在工程目录/工程名.runs/impl_1/顶层模块名.bit2.3 确认板子上电顺序和模式引脚FPGA 上电后从哪种模式加载配置由模式引脚M[2:0]决定。常见的有Master SPI 模式FPGA 主动从 SPI Flash 读配置这是最常见的固化场景。JTAG 模式只用于调试下载不用于固化启动。Slave 模式由外部主控给 FPGA 送配置数据。如果模式引脚设置不对即使 Flash 里烧了正确的 MCS上电也不会自动加载。所以固化前务必确认模式引脚跳线或电阻配置符合 Master SPI 的要求。具体电平组合查对应 FPGA 型号的配置手册不同系列不一样。注意有些开发板用拨码开关切换模式烧录时可能需要在 JTAG 模式和 Master SPI 模式之间切换。烧完记得拨回启动模式再重新上电验证。3. 用 Vivado 生成 MCS 文件的完整流程这一步是整篇的核心。Vivado 生成 MCS 有两条路图形界面操作和 Tcl 命令。图形界面适合新手Tcl 适合批处理和复现。我把两种都讲一遍并解释每个参数的含义。3.1 图形界面操作从 Add Configuration Memory Device 开始打开 Vivado确保硬件连接正常JTAG 下载器插好板子上电。然后按以下步骤走在左侧 Flow Navigator 底部找到Open Hardware Manager点击Open Target → Auto Connect。如果连不上检查下载器驱动和 JTAG 链路。连接成功后在 Hardware 窗口里右键 FPGA 器件选择Add Configuration Memory Device。在弹出的搜索框里输入 Flash 型号比如w25q128选中匹配的器件点击 OK。Vivado 会弹出对话框询问是否现在就要烧录配置存储器。这里先选Cancel因为我们还没生成 MCS 文件。此时 Hardware 窗口里会多出一个 Flash 器件节点。右键它选择Program Configuration Memory Device。在配置对话框里Configuration file一栏点击浏览选择你的.bit文件。Vivado 会自动提示是否要生成 MCS或者你也可以在Configuration file旁边勾选生成 MCS 的选项。但更规范的做法是先生成 MCS再单独烧录。生成 MCS 的入口在Tools → Generate Memory Configuration File这个对话框里的参数是重点逐个说Format选MCS。也有BIN格式但 MCS 是带地址信息的 ASCII 格式通用性更好。Memory Part选你的 Flash 型号。这个必须和实际芯片一致否则地址映射会错。Interface根据 Flash 接口选SPIx1、SPIx2、SPIx4。大多数小容量 Flash 用 SPIx1大容量高速加载用 SPIx4。Data Width和 Interface 对应SPIx1 就是 1SPIx4 就是 4。Start Address一般填0x00000000除非你有特殊的分区需求。Load Bitstream files勾选后添加你的.bit文件。File name指定输出的.mcs路径。填完之后点 OKVivado 会在后台调用write_cfgmem命令生成 MCS。生成成功后在指定目录能看到.mcs和.prm两个文件.prm是烧录时用的参数文件别删。3.2 Tcl 命令方式可复现的批处理写法如果你要反复生成或者想把流程写进脚本用 Tcl 更省事。在 Vivado 的 Tcl Console 里执行write_cfgmem -format MCS \ -interface SPIx1 \ -size 16 \ -loadbit up 0x00000000 ./top.bit \ -file ./output/top.mcs参数解释-format MCS输出 MCS 格式。-interface SPIx1SPI 单线模式对应 Data Width 1。-size 16Flash 容量单位是 Mb。这里 16 表示 16Mb即 2MB。这个值必须大于等于比特流实际大小否则会报空间不足。-loadbit up 0x00000000 ./top.bitup表示从起始地址向上加载0x00000000是起始地址后面是比特流路径。-file输出文件路径。执行后如果看到类似Writing MCS file...的日志说明生成成功。可以用文本编辑器打开.mcs看一眼开头是:020000040000FA这样的 Intel HEX 格式记录说明格式正确。3.3 MCS 文件大小与 Flash 容量的匹配计算很多人烧录时报not enough space或者烧完不启动根源是 MCS 大小和 Flash 容量没对上。这里给一个简单的估算方法比特流文件大小 ≈ 配置比特数 / 8。比如一个中等规模的 FPGA 工程比特流可能是 3MB 到 8MB 不等。MCS 因为是 ASCII 编码体积会比原始二进制大约 2 倍多。所以16Mb Flash2MB通常只够放很小的工程。64Mb Flash8MB能放大多数中小规模工程。128Mb Flash16MB适合大工程或多镜像。在 Vivado 里可以直接看.bit文件大小然后乘以 2.2 左右估算 MCS 大小再和 Flash 容量对比。如果不够要么换更大 Flash要么压缩设计比如开启比特流压缩。提示Vivado 生成比特流时可以勾选Enable bitstream compression能显著减小比特流体积对容量紧张的板子很有用。但压缩后的比特流加载时会稍慢一点属于用时间换空间。4. 把 MCS 烧进 Flash 的实操与验证MCS 生成好之后下一步是烧录。这一步的坑主要集中在“烧录器识别不到 Flash”和“烧完不启动”两类。4.1 在 Hardware Manager 里烧录 MCS操作路径打开 Hardware Manager连接目标板。右键 FPGA 器件Add Configuration Memory Device选好 Flash 型号。右键新增的 Flash 节点选择Program Configuration Memory Device。在对话框里Configuration file选择刚才生成的.mcs。PRM file会自动关联如果没有就手动选.prm。勾选Verify可以在烧录后校验。勾选Erase会先擦除再烧首次烧录建议勾上。点击 OK等待进度条走完。烧录时间取决于 Flash 容量和 JTAG 速度128Mb 的 Flash 可能要几分钟。烧录过程中如果报error: flash download failed - target dll has been cancelled通常是 JTAG 连接不稳定或者 Flash 型号选错。先检查下载器接触、板子供电再确认型号。4.2 烧完之后的验证步骤烧录完成不代表成功必须验证。验证分两步第一步不断电用 JTAG 重新加载一次比特流确认 FPGA 本身工作正常。这一步排除工程问题。第二步断电等几秒重新上电。观察板子是否自动启动。如果启动了说明固化成功。如果没启动按下面的顺序排查模式引脚是否在 Master SPI 位置。Flash 型号是否选对特别是容量和扇区结构。MCS 起始地址是否和 FPGA 配置加载地址一致通常都是 0。比特流是否真的对应这个板子的 FPGA 型号和封装。Flash 的写保护引脚是否被拉低导致写入失败。我遇到过一种情况烧录显示成功但上电不启动最后发现是 Flash 的HOLD或WP引脚在板子上被错误拉低导致 FPGA 读取时数据被保持。这种硬件层面的问题软件层面怎么查都查不出来只能对着原理图量引脚电平。4.3 常见报错与对应处理报错信息可能原因处理方式cannot load flash device descriptionFlash 型号不在 Vivado 数据库手动添加或换用兼容型号warning: failed to communicate with the flash chipJTAG 链路或 Flash 供电异常检查连接、供电、复位not enough spaceMCS 大于 Flash 容量换大容量 Flash 或压缩比特流烧录成功但上电不启动模式引脚、地址、引脚电平逐项排查硬件配置implement design变红工程本身未通过实现先解决时序和 DRC 问题5. 几个让固化更省心的经验技巧做了很多次固化之后我总结了几条能明显减少返工的习惯。第一把 MCS 生成和烧录分开做。不要图省事在烧录对话框里临时生成因为那样参数不好复用。先生成好.mcs和.prm归档到工程目录烧录时直接选文件出问题也容易定位。第二给 Flash 留一份“救砖”镜像。如果板子支持可以在 Flash 里烧两个镜像一个主用一个备份通过地址偏移区分。主镜像损坏时还能切到备份启动。这对量产和现场升级很有价值。第三记录每次固化的参数。Flash 型号、接口模式、起始地址、比特流版本这些信息写在一个flash_config.txt里放在工程根目录。过几个月再回来烧不用重新翻原理图。第四注意 Vivado 版本和 Flash 数据库的匹配。有些新 Flash 型号在老版本 Vivado 里没有需要手动添加或升级软件。如果公司环境不能随便升级就选数据库里已有的兼容型号。第五固化后做一次完整的上电循环测试。至少断电三次、上电三次确认每次都能正常启动。有些偶发问题只在特定上电时序下出现单次测试发现不了。最后说一个我自己的习惯每次固化成功后把当次的.bit、.mcs、.prm和参数记录打包存一份命名带上日期和版本号。FPGA 项目迭代快过一阵子回头看没有这些归档根本记不清哪版烧的是哪个文件。这个习惯帮我省过好几次重新生成和重新验证的时间。