3. 固件与配置文件

FPGA 的固件通常被称为 bitstream(比特流)或配置文件(configuration file),它本质上是描述 FPGA 内部可编程逻辑资源(LUT、FF、BRAM、DSP、IO 以及路由开关)如何连接与配置的二进制数据。与处理器固件(如 ARM 的 HEX 或 Intel 的 UEFI)不同,FPGA 的 bitstream 不包含指令集,而是直接映射到硅片上的配置存储单元(CRAM)。理解 bitstream 的格式、压缩与加密机制,以及掌握 Vivado 与 Quartus 的生成流程,是设计可靠远程升级方案的基础。本章将深入剖析 bitstream 的内部结构、安全属性以及从工程到产物的完整生成链路。

FPGA 固件(bitstream)生成与安全属性总览 Vivado / Quartus 生成流程 RTL 综合 (Synth) 布局布线 (Place & Route) bitstream 生成 (Write Bitstream) 压缩 (Compression) 加密 (AES-256 / SM4) 产物: .bit / .rbf / .pof bitstream 格式与安全 格式组成 同步头 + 命令 + 配置数据 + CRC 压缩 LZ 算法 / 稀疏编码,减少 50-70% 加密 AES-256 GCM / 密钥存储于 eFuse 认证 RSA-4096 签名 / 防回滚 远程升级链路 服务器下发加密 bitstream MCU/SoC 接收并暂存 解密 + CRC 校验 通过 SPI/SelectMAP 写入 Flash FPGA 重配置加载 回滚机制 (Golden Image)

上图展示了从工程编译到远程升级的完整链路。左侧是开发工具(Vivado/Quartus)生成 bitstream 的流程,中间是 bitstream 的格式与安全属性,右侧则是远程升级时固件从服务器到 FPGA 的流转路径。在实际项目中,开发者需要同时关注左侧的生成效率与中间的安全属性,才能保证右侧的远程升级既快又稳。

3.1 bitstream 格式深度解析

核心原理:bitstream 的层次化结构

FPGA 的 bitstream 并非简单的二进制大对象(BLOB),而是具有严格层次化结构的配置数据流。以 Xilinx 7 系列为例,bitstream 由 32-bit 同步字(0xAA995566)、配置命令(如 WRITE、READ、LFRM 等)、配置数据帧(Frame)以及 CRC 校验值组成。每个 Frame 对应 FPGA 内部的一列逻辑资源(CLB、BRAM、DSP 或 IO),Frame 的数量与器件型号直接相关。Altera(Intel)的 .rbf(Raw Binary File)格式则采用更简化的连续数据流,但同样包含同步头、配置数据和 CRC。

理解 bitstream 格式的关键在于:配置数据帧(Frame)是 FPGA 配置存储单元(CRAM)的最小寻址单位。远程升级时,如果采用部分重配置(Partial Reconfiguration),可以只更新特定区域的 Frame,而无需重写整个 bitstream。这要求开发者对 bitstream 的帧地址映射有精确掌握。

关键格式对比:Xilinx .bit 文件包含文件头(Header)和配置数据两部分。Header 中记录了器件型号、生成日期、数据长度等信息,而配置数据部分才是真正写入 FPGA 的比特流。Altera 的 .pof(Programmer Object File)用于 JTAG 直接配置,.rbf 则用于外部控制器(如 EPCS Flash)配置。在远程升级场景中,通常使用 .bin(去除 Header 的纯配置数据)或 .rbf 格式,因为它们可以直接被 MCU 通过 SPI 接口发送给 FPGA。

判断方法:如何识别与验证 bitstream 格式

在工程实践中,经常需要验证生成的 bitstream 是否正确。以下是几种常用的判断方法:

  • 文件头检查:使用十六进制编辑器查看 .bit 文件的前 32 字节,应包含同步字 0xAA995566(Xilinx)或 0xFF 0xFF 0xFF 0xFF(Altera 的 .rbf 以连续 0xFF 开头)。
  • CRC 校验:Vivado 生成的 bitstream 默认包含 CRC32 校验值。在远程升级时,MCU 应计算接收数据的 CRC32 并与 bitstream 末尾的 CRC 值比对,确保传输过程中数据未损坏。
  • 回读验证:通过 JTAG 或 SelectMAP 接口回读 FPGA 内部的配置数据,与原始 bitstream 进行逐字节比对。Xilinx 的 iMPACT 或 Vivado 的 Hardware Manager 支持回读功能。
// 伪代码:MCU 端 CRC32 校验示例
uint32_t calc_crc32(uint8_t *data, uint32_t len) {
    uint32_t crc = 0xFFFFFFFF;
    for (uint32_t i = 0; i < len; i++) {
        crc ^= data[i];
        for (int j = 0; j < 8; j++) {
            crc = (crc >> 1) ^ (0xEDB88320 & (-(crc & 1)));
        }
    }
    return ~crc;
}
// 注意:Xilinx bitstream 的 CRC 是倒序存储的,需进行字节序转换

案例拆解:从 .bit 到 .bin 的转换与验证

某工业网关项目采用 Xilinx Artix-7 FPGA,需要通过以太网远程升级固件。原始工程生成的 .bit 文件大小为 4.2MB,但直接通过以太网传输效率较低。工程师使用 Vivado 的 write_cfgmem 命令将 .bit 转换为 .bin 格式,去除了文件头,大小降至 3.8MB。随后,在 MCU 端编写了 CRC32 校验程序,对接收到的 .bin 文件进行校验。测试中发现,当网络丢包导致数据错误时,CRC 校验能够准确捕获错误,触发重传机制。经过 100 次连续升级测试,成功率达到 100%。

经验提醒:在远程升级方案中,建议始终使用 .bin 或 .rbf 格式,而不是 .bit 格式。因为 .bit 文件头包含的元数据(如时间戳、器件型号)在升级过程中毫无意义,反而增加传输负担。同时,务必在 bitstream 末尾附加自定义的版本号和 CRC 值,便于 MCU 进行版本管理和完整性验证。

常见误区与总结

风险提示:不要将 .bit 文件直接烧写到 SPI Flash 中。SPI Flash 的启动模式要求 bitstream 以特定的同步头开始,而 .bit 文件头会干扰 FPGA 的自动加载。正确做法是使用 write_cfgmem 生成 .bin 文件,并确保其格式与 SPI Flash 的启动地址对齐(通常从 0x0 地址开始)。

总结:bitstream 格式是 FPGA 固件升级的基础。开发者必须理解 .bit、.bin、.rbf、.pof 等格式的区别与适用场景,并掌握 CRC 校验和回读验证等基本手段,才能确保远程升级的数据完整性。

3.2 bitstream 压缩与加密技术

核心原理:压缩与加密的必要性

FPGA 的 bitstream 通常较大(从几百 KB 到几十 MB),在远程升级场景中,传输时间与带宽成本是重要考量。bitstream 压缩技术通过去除配置数据中的冗余信息,可显著减小文件体积。Xilinx 的压缩算法基于 LZ77 变体,利用配置数据中大量重复的 0 和 1 模式进行编码。Altera 则采用更简单的稀疏编码(Sparse Encoding),对全零字节进行特殊标记。

加密则是保护 FPGA 知识产权(IP)和防止固件被逆向工程的关键手段。现代 FPGA(如 Xilinx UltraScale+、Intel Agilex)内置 AES-256 解密引擎,bitstream 在烧写前使用 AES 密钥加密,FPGA 在配置时自动解密加载。密钥可存储在 FPGA 内部的 eFuse 或 BBRAM(电池备份 RAM)中,确保密钥无法被外部读取。

特性 Xilinx (Vivado) Altera/Intel (Quartus)
压缩算法 LZ77 变体(默认开启) 稀疏编码(需手动开启)
加密算法 AES-256 GCM(支持认证) AES-256 CBC(部分器件支持)
密钥存储 eFuse / BBRAM eFuse / 内部 SRAM
压缩率 通常 50%-70% 通常 30%-50%
加密后压缩 不支持(先压缩后加密) 不支持(先压缩后加密)

操作流程:在 Vivado 中启用压缩与加密

在 Vivado 中,压缩默认开启,但加密需要额外配置。以下是标准操作流程:

  1. 生成加密密钥:使用 write_aes_key_file 命令生成 256-bit 密钥文件(.nky 格式)。
  2. 配置加密属性:在约束文件(XDC)中添加 set_property BITSTREAM.ENCRYPTION.AESKEYFILE <key_file.nky>。
  3. 设置加密模式:添加 set_property BITSTREAM.ENCRYPTION.MODE AES256 [current_design]。
  4. 生成加密 bitstream:运行 write_bitstream,生成的 .bit 文件已加密。
  5. 烧写密钥:首次使用时,需通过 JTAG 将密钥烧写到 eFuse 或 BBRAM(使用 program_hw_devices 命令)。
# Vivado Tcl 脚本示例
# 生成密钥文件
write_aes_key_file -file mykey.nky -key 0x00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF
# 设置加密属性
set_property BITSTREAM.ENCRYPTION.AESKEYFILE mykey.nky [current_design]
set_property BITSTREAM.ENCRYPTION.MODE AES256 [current_design]
# 生成加密 bitstream
write_bitstream -file encrypted.bit

案例拆解:加密 bitstream 的远程升级实战

某通信设备厂商需要防止其 FPGA 算法被竞争对手逆向。他们采用 Xilinx Kintex-7 FPGA,并启用了 AES-256 加密。在开发阶段,工程师将密钥存储在 BBRAM 中,方便调试。量产阶段,改为烧写 eFuse(一次性可编程),确保密钥不可更改。远程升级时,服务器下发加密的 .bin 文件,MCU 通过 SPI 接口将密文写入 SPI Flash。FPGA 上电后,自动从 Flash 读取密文,使用内部 AES 引擎解密并加载。测试表明,加密后的 bitstream 大小增加了约 2%(加密开销),但安全性大幅提升。即使攻击者从 Flash 中读出密文,也无法在没有密钥的情况下还原明文 bitstream。

风险提示:加密密钥的管理是安全链路的薄弱环节。如果密钥文件(.nky)泄露,加密将形同虚设。建议将密钥文件存储在受控的构建服务器上,并限制访问权限。同时,eFuse 烧写是不可逆操作,一旦烧写错误,芯片将无法重新配置密钥,只能报废。

常见误区与总结

  • 误区一:压缩与加密可以同时开启。实际上,加密后的数据具有高熵,压缩算法无法有效工作。因此,Vivado 和 Quartus 均要求先压缩后加密,且加密后不再压缩。
  • 误区二:加密 bitstream 可以防止所有攻击。加密只能防止静态逆向,但无法防止侧信道攻击(如功耗分析)。对于高安全场景,建议结合 FPGA 的物理不可克隆函数(PUF)或外部安全芯片。
  • 误区三:所有 FPGA 器件都支持加密。低端器件(如 Spartan-6 的部分型号)不支持 AES 加密,设计时需确认器件选型。

总结:压缩与加密是远程升级方案中平衡效率与安全的关键技术。开发者应根据实际威胁模型选择是否加密,并合理配置压缩参数,以最小化传输时间与带宽消耗。

3.3 配置文件生成流程(Vivado / Quartus)

核心原理:从 RTL 到 bitstream 的完整链路

无论是 Vivado 还是 Quartus,生成配置文件的过程都遵循相似的步骤:综合(Synthesis)→ 布局布线(Place & Route)→ 时序收敛(Timing Closure)→ 生成 bitstream。综合将 RTL 代码转换为门级网表,布局布线将网表映射到 FPGA 的物理资源上,时序收敛确保设计满足时钟约束,最后生成 bitstream 文件。

在远程升级场景中,开发者需要额外关注两个环节:配置模式(如 SPI x4、SelectMAP)和启动地址(如 SPI Flash 的起始地址)。这些参数在生成 bitstream 时必须正确设置,否则 FPGA 无法从外部 Flash 正确加载固件。

操作流程:Vivado 与 Quartus 的配置生成步骤

步骤 Vivado (Xilinx) Quartus (Altera/Intel)
1. 综合 Run Synthesis → 生成 .dcp Analysis & Synthesis → 生成 .vo
2. 布局布线 Run Implementation → 生成 .dcp Fitter → 生成 .fit
3. 时序分析 Report Timing Summary → 检查 WNS/TNS TimeQuest → 检查 setup/hold 裕量
4. 生成 bitstream Write Bitstream → 生成 .bit/.bin Assembler → 生成 .pof/.rbf
5. 配置模式设置 Edit Device Properties → 设置 SPI/SelectMAP Device and Pin Options → 设置 Configuration Scheme

案例拆解:多镜像远程升级的配置生成

某数据中心加速卡项目采用 Xilinx UltraScale+ FPGA,需要支持远程升级且具备回滚功能。工程师在 Vivado 中创建了两个配置镜像:Golden Image(出厂固件,存储在 SPI Flash 的 0x0 地址)和 Update Image(新固件,存储在 0x400000 地址)。生成 bitstream 时,通过 write_cfgmem 命令分别生成两个 .bin 文件,并设置不同的起始地址。FPGA 上电时,先加载 Golden Image,然后由 Golden Image 中的逻辑检查 Update Image 的版本号和 CRC。如果 Update Image 有效,则触发重配置加载 Update Image;如果无效,则继续运行 Golden Image。这种方案确保了升级失败时设备仍可正常工作。

# 生成 Golden Image (地址 0x0)
write_cfgmem -format bin -interface SPIx4 -loadbit "up 0x0 golden.bit" -file golden.bin
# 生成 Update Image (地址 0x400000)
write_cfgmem -format bin -interface SPIx4 -loadbit "up 0x400000 update.bit" -file update.bin
经验提醒:在生成多镜像配置时,务必确保两个镜像的起始地址与 FPGA 的启动模式匹配。例如,SPI x4 模式下,FPGA 从 Flash 的 0x0 地址开始读取,但可以通过 bitstream 中的 MULTIBOOT 命令跳转到其他地址。Vivado 的 write_cfgmem 支持 -loadbit 参数指定多个镜像及其地址。

常见误区与总结

风险提示:Quartus 生成 .rbf 文件时,默认不包含 CRC 校验。如果远程升级使用 .rbf 格式,必须在 MCU 端自行添加 CRC 校验,否则无法检测传输错误。建议在 Quartus 的 Assembler 设置中启用 "Generate CRC" 选项,或使用 .pof 格式(包含 CRC)。

总结:配置文件生成流程是 FPGA 固件升级的源头。开发者需要熟练掌握 Vivado 和 Quartus 的配置生成步骤,特别是配置模式、启动地址和多镜像设置,才能为远程升级方案提供正确的固件输入。同时,应结合压缩与加密技术,在保证安全的前提下优化传输效率。