比特流格式解析:FPGA的“灵魂代码”

做FPGA逆向这么多年,我始终觉得比特流格式是绕不开的硬骨头。你想想看,我们平时写的Verilog代码,经过综合、布局布线,最后变成什么?就是比特流。它才是FPGA真正执行的“灵魂代码”。

今天我们就来聊聊比特流的结构。我会结合Xilinx 7系列和Intel Cyclone V这两个主流平台,把它们的比特流格式掰开揉碎了讲清楚。

比特流的基本结构

说白了,比特流就是一串二进制数据。但这一串数据不是乱排的,它有严格的层次结构。我习惯把它分成三个核心部分:

  • 同步头:告诉FPGA“数据来了,准备接收”
  • 配置数据:真正的配置内容,包括逻辑单元、布线资源、BRAM初始化等
  • CRC校验:确保数据在传输过程中没出错

嗯,这里要注意:不同厂家的比特流,这三部分的组织方式完全不同。我在项目中遇到过最头疼的事,就是拿着Xilinx的解析工具去读Altera的比特流——结果当然是乱码。

Xilinx 7系列比特流格式详解

Xilinx 7系列的比特流,我个人觉得设计得相当优雅。它采用了一种叫“字对齐”的结构,每个配置字是32位。

同步头

同步头由几个特殊的32位字组成。最经典的是:

0xAA995566  // 同步字
0x20000000  // 同步头结束标志

为什么是0xAA995566?这个值在二进制里是10101010 10011001 01010101 01100110,有丰富的跳变沿,方便FPGA内部的时钟恢复电路锁定。我记得第一次手动解析比特流时,看到这个固定模式,心里踏实了不少。

配置数据

配置数据部分是最复杂的。它包含多个数据包,每个数据包有包头和负载。包头指定了操作类型和目标寄存器地址。

包头类型 描述 常见用途
Type 1 简单读写操作 配置寄存器、FAR、CRC等
Type 2 大数据块传输 配置LUT、BRAM内容

我曾经在逆向一个Xilinx 7系列的设计时,发现配置数据里有一段奇怪的重复模式。后来才意识到,那是BRAM的初始化数据——设计者把一段查找表硬编码进去了。

CRC校验

Xilinx使用32位CRC,多项式是0x04C11DB7。配置完成后,FPGA会计算接收到的所有数据的CRC,与比特流末尾的CRC值比对。如果对不上,FPGA会拉低DONE信号,表示配置失败。

避坑指南:我曾经在修改比特流时,只改了配置数据忘了更新CRC,结果FPGA死活不工作。后来花了半天才排查出来——嗯,从那以后我再也不敢忽略CRC了。

Intel Cyclone V比特流格式详解

Cyclone V的比特流和Xilinx完全不同。它采用了一种叫“快速被动并行”(FPP)的配置模式,数据宽度可以是8位、16位或32位。

同步头

Cyclone V的同步头更简单,通常是一个固定的32位模式:

0xFFFFFFFF  // 前导码
0xAAAAAAAA  // 同步码

为什么用全1和交替的1010?说白了,就是为了让FPGA的配置逻辑能快速锁定数据边界。我在调试Cyclone V的配置时序时,发现如果前导码长度不够,FPGA会一直处于等待状态。

配置数据

Cyclone V的配置数据是连续的,没有像Xilinx那样的包头结构。它直接按照地址顺序写入配置RAM。每个配置位对应一个逻辑单元或布线资源。

这里有个关键点:Cyclone V的比特流是压缩的。默认情况下,Intel的工具会使用LZSS算法压缩配置数据。如果你直接拿压缩后的比特流去解析,看到的全是乱码。

个人经验:我建议在分析Cyclone V比特流前,先用工具解压缩。Intel官方提供了decompress工具,或者你也可以自己实现LZSS解码器。我写过一版Python的,大概200行代码就能搞定。

CRC校验

Cyclone V使用16位CRC,多项式是0x8005。它不像Xilinx那样放在末尾,而是穿插在配置数据中。每配置完一个扇区(sector),就会插入一个CRC值。

为什么会这样?因为Cyclone V支持部分重配置,每个扇区可以独立校验。这样设计的好处是,如果某个扇区配置出错,不需要全部重来。

两种格式的核心差异

特性 Xilinx 7系列 Intel Cyclone V
同步头 0xAA995566 0xFFFFFFFF + 0xAAAAAAAA
数据组织 包结构(Type1/Type2) 连续地址映射
压缩 可选(支持多比特流压缩) 默认LZSS压缩
CRC 32位,末尾校验 16位,扇区间隔校验
部分重配置 支持(通过ICAP) 支持(扇区级)

核心知识体系

下面这张图是我自己整理的,把比特流解析的核心逻辑串起来了。你看一眼就能明白整体脉络。

比特流解析核心知识体系 比特流格式 同步头 配置数据 CRC校验 Xilinx: 0xAA995566 Intel: 0xFFFF+0xAAAA Xilinx: 包结构 Intel: 连续地址映射 Xilinx: 32位末尾校验 Intel: 16位扇区间隔 解析关键:识别厂家 → 确定格式 → 提取数据 → 验证CRC

核心要点:解析比特流,第一步就是识别厂家。Xilinx和Intel的格式差异巨大,用错解析方法等于白干。我个人习惯先看同步头,0xAA995566就是Xilinx,0xFFFFFFFF开头就是Intel。

好了,这一章的内容就到这里。比特流格式是FPGA逆向的基础,搞懂了它,后面的配置逻辑分析、资源提取才能顺利进行。


公众号:蓝海资料掘金营,微信deep3321