这一篇在干嘛?
加载模式总览与启动方式
先分清两代器件的加载模式配置方法,这不一样:
- EF2、EF3(内置 Flash):加载模式由 **Flash 里的位流参数(TD 软件选项)**决定,绝大部分场景用 MSPI 模式(从内部 Flash 加载)——因为它 Flash 都合封好了,没必要折腾别的。
- EG4、PH1(外挂 Flash):加载模式由专用 MSEL 管脚的电平(外部上下拉电阻决定高低)配置。常用模式:MSPI、从动串行(SS)、从动并行(SP)。手册给出 EG4X 的 MSEL 编码:
| 配置引脚名 | 类型 | SS:从动串行 | SP:从动并行 | MSPI:主动 SPI | MP:主动并行 (X8) | JTAG |
|---|---|---|---|---|---|---|
| M[1:0] | 复用 | 11 | 10 | 01 | 00 | XX |
比赛用的 EG4S20 属于 EG4 系:MSEL 接成 “01” 就是 MSPI。还有一条保底规则:不管选哪种模式,JTAG 口永远可以加载 FPGA——所以板上务必预留 JTAG 插座(还支持菊花链,一 households 条链挂多颗器件)。
什么事件会触发一次加载?四个入口:
- 上电触发 POR(Power-On Reset,上电复位)——最常见,插电就加载;
- PROGRAMN 管脚输入低脉冲——外部强制重载(见第二篇的复位按键电路);
- JTAG 输入 Refresh 指令——调试器软件按钮本质也是这个;
- FPGA 逻辑调用 Multi-Boot 原语,给 rebootn 送低电平——让 FPGA 自己决定”我要重启换逻辑”(后面 Multi Boot 细讲)。
怎么判断加载成功?两个手段:看 DONE 管脚是否拉高(最直接,可点 LED);或者从系统层面验证——通过 FPGA 内部逻辑是否在工作来判断,比如上位机读写一个 FPGA 寄存器。
MSPI:最常用的主动加载
MSPI(Master SPI,主动串行外设接口)模式的”主动”是相对 FPGA 说的:
- 位流存在 SPI 接口的 Flash 里;
- FPGA 工作在主模式(Master):FPGA 自己产生时钟,主动从 Flash 里把位流读出来;
- EG4、PH1 需要外挂一颗 SPI Flash 芯片,并把 MSEL 配置为 MSPI 模式;
- EF2、EF3 把 Flash Die 直接合封进芯片,而且合封 Flash 的容量都装得下两份位流(这是 Dual Boot 的硬件基础),加载模式的配置参数存在 Flash 起始部分。

这张手册示意图展示 EF2/EF3 的合封:左边是 1.5~9.2K LEs 的 FPGA Die,右边是 Flash Die,两者在同一封装里用 SPI 总线相连。对外看不到 Flash 芯片,省面积也更难被仿制。
![EG4X 的 MSPI 模式连接:MSEL[1:0]=01,FPGA 作为 SPI 主机从外部 Flash 读位流](../../images/fpga/fae-03_02.jpg)
这张是 EG4X 的 MSPI 连接:MSEL[1:0] 用上下拉电阻配成 “01”,FPGA 上电后作为 SPI 主机,从外挂 Flash 读位流。画原理图时 Flash 的 CS/SCLK/MOSI/MISO 必须接在手册指定的专用配置管脚上,不能随便挑 IO。
MSPI 加载速度与时间计算
加载不是瞬间完成的,系统有”上电到可用”的时间指标时就得算加载时间。可调参数有三个维度:
- 位宽:MSPIx1 / MSPIx2 / MSPIx4(单、双、四线 SPI);
- 时钟频率 MCLK:EF2、EF3 可选 2.5~24MHz;EG4 可选 2.5~16MHz;
- 计算公式:加载时间 = 位流长度 ÷ 时钟频率 ÷ 加载位宽。
TD 软件里的配置项(boot_mode 选 mspix1/x2/x4;mclk_freq_div 选时钟频率):
| Option | Description | Selection |
|---|---|---|
| hswapen | 加载过程 IO 上拉开关 | enable √ |
| boot_mode | 加载模式选择 | mspix4 √(可选 mp/mspix1/mspix2/mspix4/sp/ss) |
| mclk_freq_div | MCLK 分频 | 2.5~24MHz 多档 |
带着算一遍(手册实测表,位流 159×8 Kbit = 1272 Kbit,MCLK 2.5MHz):
| 位流长度 (Kbit) | 时钟 (MHz) | 位宽 | 实测时间 (ms) | 计算时间 (ms) |
|---|---|---|---|---|
| 159×8 | 2.5 | 4 | 126.8 | 127.2 |
| 159×8 | 2.5 | 2 | 250.8 | 254.4 |
| 159×8 | 2.5 | 1 | 498.8 | 508.8 |
以 x4 为例:1272 Kbit ÷ 2.5 MHz ÷ 4 = 127.2ms,和实测 126.8ms 几乎重合——公式可信。同样的位流,x4 比 x1 快整整 4 倍(127ms vs 499ms),所以位宽能开 x4 就开 x4。
两个隐藏坑(手册备注展开):
- MCLK 由 FPGA 内部 OSC(振荡器)分频得到,而 OSC 本身有 30% 频率偏差——所以加载时间也会有 ±30% 的漂移。算系统上电时间指标时要留余量,别把 127ms 当死数用。
- 早期 TD 软件频率可选范围偏大,为了批量可靠性,最高几档频率已被禁用——别死磕最高频率,稳比快重要。
Dual Boot 与 Multi Boot
Flash 里只有一份位流,升级写坏就变砖——双保险机制应运而生。
**Dual Boot(双备份启动)**特性:
- 在 MSPI 模式下工作,且 MSPI 模式自动包含 Dual Boot(不用额外开关);
- SPI Flash 存两份位流:Primary(主)区域和 Golden(黄金/安全)区域;
- Primary 起始地址固定 0x000000;Golden 的起始地址由指针向量决定,指针本身的存放地址固定(如 EF2 为 0x040000),指针指向的地址理论上可调,但建议用 TD 生成的默认值不要乱改(EF2 默认指向 0x041000);
| Dual Boot Flash 地图 | 内容 |
|---|---|
| 0x000000 | Primary 位流 |
| 0x040000 | Golden 地址(指针) |
| 0x041000 | Golden 位流 |
- 工作流程:先加载 Primary → 失败则跳去加载 Golden → Golden 也失败再回头加载 Primary……如此循环。始终找不到合法位流时,INITN 管脚上能观察到连续脉冲——这是”我在空转找位流”的求救信号。
用法定位:Dual Boot 是为在线升级的可靠性服务的——Golden 区域预先烧入一份保底位流,在线升级过程只动 Primary,绝不擦写 Golden。这样升级中途断电、写坏数据,芯片至少还能从 Golden 启动,保住”还能再次升级”的底线。另注意:加载成功后,逻辑代码自己无法直接判断是从哪个区域启动的。
**Multi Boot(多重启动)**是更灵活的进阶版:
- 同样在 MSPI 模式下工作,但要调用 MBOOT 原语,由用户逻辑代码控制重新加载的时机和目标位流的地址;
- 三个参数调整加载起始地址:ADDR_SOURCE_SEL、STATIC_ADDR、dynamic_addr;
- rebootn:重启控制信号,低有效,低电平至少维持 2500ns;
- 重要差异:Multi Boot 加载失败后 FPGA 会挂死,不会自动回落到 Primary 区域——灵活的代价是没有 Golden 兜底,用在能保证位流可靠性的场景。
从动串行(SS)
从”FPGA 当主机”翻转到”FPGA 当从机”:位流由外部主机(MCU/CPU)提供,FPGA 只负责接收。SS(Slave Serial,从动串行)单芯片模式:
- 主机通过 SCLK、DIN 两个信号把位流送进 FPGA,SCLK 上升沿采样;
- 注意文件位序差异:bin 文件每个字节高位(MSB)先送,rbf 文件每个字节低位(LSB)先送——发错了整片位流全错;
- 配置出错:FPGA 把 INITN 拉低表示加载失败;DONE 拉高表示配置完成;
- 级联模式:多颗 FPGA 可串成一条链,多个位流文件分别读取发送,也可合并为一个文件连续发送;文件切换时 PROGRAMN、SCLK 状态保持不变。

这张时序图是 SS 模式的”交通规则”全图,重点看四个时间参数:T_program_b(PROGRAMN 低脉冲宽度,太短无效)、T_init_b(PROGRAMN 释放后到 INITN 拉高的初始化时间,INITN 没拉高前绝不能发数据)、T_dsu/T_dh(DIN 相对 SCLK 的建立/保持时间)、T_cl/T_ch(SCLK 低/高电平宽度)。DONE 在数据末尾拉高,之后进入 User mode。

这张是 SS 级联接线图:MCU 发 CCLK、DIN,第一片 EG4X 收完自己的位流后从 DOUT 把后续数据转发给下一片的 DIN(菊花链);PROGRAMN/INIT_B/DONE 三条状态线全链共享,VCCIO 上有上拉。不同器件的 T_program_b、T_init_b 数值不同,混链时要以最慢的器件为准,并注意建立保持时间。
从动并行(SP)
SP(Slave Parallel,从动并行)模式——把串行改成 8 位并行,加载速度更快:
- FPGA 作为从器件,通过 SCLK + DATA[7:0] 8 位总线收位流,SCLK 上升沿采样;
- 片选 CSN:0 允许写入数据,1 禁止写入;
- 文件处理:bin 文件按字节直发接 DIN[7:0];rbf 文件每个字节的 bit 顺序要颠倒再发(又是位序坑);
- 出错拉低 INITN、完成拉高 DONE,与 SS 相同;
- 级联两种玩法:①多个位流合并为一个文件连续发送,用 CSI/CSO 串接实现级联(前一片的 CSO 接下一片的 CSI);②多文件分别发送,主机出多个片选 CS 分别接各片的 CSI。多颗 FPGA 加载过程中 PROGRAMN、SCLK 保持不变。

这张时序图比 SS 多了 CSN 和 DATA[7:0]:CSN 拉低后数据才有效,同样要遵守 T_program_b → 等 INITN 高 → 按 T_dsu/T_dh 送数 → DONE 拉高的流程。
![从动并行级联连接:CPU/外部主机通过 DATA[7:0]/CSN/CLK 驱动两片 EG4X,M[1:0]=10,CSI/CSO 菊花链接](../../images/fpga/fae-03_06.jpg)
这张是 SP 级联接线图:主机 DATA[7:0] 总线挂两片 FPGA,第一片 CSO_B 接第二片 CSI_B;两片 M[1:0] 都接 “10”(SP 模式),PROGRAMN/INIT/DONE 共享。SS 和 SP 的备注完全一致:注意 T_program_b 脉宽、等 INITN 拉高再发数、关注 T_dsu/T_dh 建立保持时间。
常见坑:INITN 还没拉高就开始发位流
从串/从并模式最经典的加载失败原因:主机看到 PROGRAMN 变高就立刻发数据,但 FPGA 初始化还没完成(INITN 尚未拉高),数据全被丢弃。正确流程:PROGRAMN 拉高 → 等 INITN 拉高 → 开始送数 → DONE 拉高后还要补若干时钟(bin 文件尾部有 Dummy 字节)。
加载失败排查
这部分是 FAE 实战经验的浓缩,按模式分开看。
MSPI 模式排查:
- 用 JTAG 回读 Flash 内容,与原始 bin 文件逐字节比较——位流不能有任何 bit 错误(一个 bit 错可能就加载失败或跑飞);
- 检查电源、PROGRAMN、INITN、DONE 等配置管脚的硬件连接与电平;
- 降低 MCLK 频率再试——老 TD 版本最高几档频率本来就有风险。
从串、从并模式排查:
- PROGRAMN 变高后必须等 INITN 变高才能写数据;
- DONE 变高后还要继续送 SCLK,直到唤醒状态机走完——bin 文件结尾有 Dummy 字节,加载失败可以试着再补一些时钟;
- 核对 CCLK 与 DI 的建立保持时间,以及 bin/rbf 的 bit 位序;
- 加载过程中电源跌落 → 电源供电能力不足;
- PROGRAMN、MSEL 等模式配置管脚出现中间电平或毛刺 → 加载失败(MSEL 是三态编码信号,中间电平可能读错模式);
- 加载时钟信号质量:JTAG 的 TCK、从串从并的 SCLK 要求边沿单调无回沟,20%~80% 幅度时间小于 10ns,建议时钟源端串 33Ω 电阻改善阻抗匹配。
神器:监测 INITN 管脚做故障定位——INITN 的行为就像体温计,不同”病症”曲线不同:
| INITN 表现 | 诊断方向 |
|---|---|
| 不跟随 PROGRAMN 变高 | 查各路供电电源;电源正常则芯片可能已损坏 |
| 变高后不再变低,但 FPGA 没工作 | 可能是 DONE 后还需继续补送 SCLK |
| 再次拉低的时刻固定 | 查:数据是否在 INITN 拉高前就发了?bit 位序对吗?MSEL 模式配对了吗? |
| 再次拉低的时刻不固定 | 查:电源跌落/纹波?PROGRAMN 毛刺?TCK、SCLK 信号质量?数据时序;从并模式的 RW、CS |
在线升级
产品出厂后要远程/本地更新逻辑,这就是在线升级。按器件类型分两条路线:
EG4(MSPI 外接 Flash)——升级通道可以绕开 FPGA:
- 主设备 CPU 拿到新位流后,直接访问 SPI 接口更新 Flash,完全不经过 FPGA(FPGA 该干嘛干嘛,甚至可以挂掉不影响升级);
- 或者通过 JTAG 接口操作 SPI Flash,执行 SVF/AJE 文件(见下一节);
- 或者通过 FPGA 逻辑代码操作 SPI Flash,用桥接逻辑对外提供 UART、SPI、I2C、LocalBus、Ethernet 等接口。
EF2、EF3(MSPI 内置 Flash)——Flash 在片内,外部 CPU 摸不到,只能借道:
- 通过 JTAG 接口操作 SPI Flash,执行 SVF/AJE 文件;
- 或通过 FPGA 逻辑代码操作片内 Flash,桥接出 UART、SPI、I2C、LocalBus 等接口(具体原语见硬件接口(四))。
SPI 从动模式(SP/SS):主设备 CPU 拿到新位流后直接重新加载 FPGA 即可。
必须记住的升级安全设计:Flash 编程是先擦除再写入,且擦除按块进行——升级流程若被意外打断(断电、复位)或写入错误数据,Primary 区域的位流可能不完整。所以经由 FPGA 逻辑升级时必须结合 Dual Boot:Golden 区域永不擦写,Primary 坏了至少还能从 Golden 启动,保住一条能再次升级的”生命线”。
SVF 与 AJE 文件
做在线升级工具前,先认识两种”JTAG 指令脚本”文件。
SVF(Serial Vector Format,串行向量格式):IEEE 1149.1 边界扫描编程及测试的事实业界标准语言,所有可编程器件厂商都支持。本质是用文本描述的 JTAG 指令集合,不同内容的 SVF 实现不同功能(编程、校验、擦除……)。用法:通过 TD 的 Device Chain 工具,输入 bit 文件输出 SVF 文件;SVF 支持 JTAG 菊花链。打开一个 SVF 你会看到类似这样的文本:
// Disable Dual boot loop
SIR 8 TDI (80) ;
SDR 64 TDI (00800000000000a5);
RUNTEST 200 TCK ;
// Loading device with 'bypass' instruction
SIR 8 TDI (ff) ;
每行就是一条 JTAG 操作:SIR 写指令寄存器、SDR 写数据寄存器、RUNTEST 跑指定数量的时钟。
AJE(Anlogic JTAG Embedded):可以看作二进制版的 SVF——由 SVF 文件转换生成,JTAG 指令内容完全相同。为什么要转成二进制?给嵌入式 CPU 用:
- 文件尺寸大幅变小,减小对 CPU 存储空间的占用;
- 二进制格式便于 CPU 解析,执行效率高;
- 官方提供转换工具 svf2aje.exe;
- 还提供 CPU 侧参考代码,实现”用普通 IO 模拟 JTAG 时序 + 执行 AJE 文件”的功能——这就是”没有 USB-Blaster 也能升级”的方案。
另有一个 TDE 格式,与 AJE 类似但 CPU 处理代码有差异,兼容 Lattice 的 VME 文件格式,新项目不推荐。
调试经验(嵌入式 JTAG 升级开发必看):
- 先跑最简单的 Check_Device SVF 文件——它能正常执行,说明你的模拟 JTAG 基础时序是对的,再上复杂的编程文件;
- Flash 操作需要等待时间,延时过短会导致失败——务必校准 CPU 代码里的延时函数(擦除一个扇区可能要几百毫秒,不能想当然)。
本篇通关标准:
- 能说出 EF2/EF3 与 EG4 加载模式配置方式的区别(Flash 内参数 vs MSEL 管脚)、MSPI 的主从关系,并用公式手算一个位流的加载时间(含 ±30% OSC 偏差意识)。
- 能画出 Dual Boot 的 Flash 地图(Primary 0x000000 / 指针 0x040000 / Golden 0x041000)、叙述”Primary 失败转 Golden 循环尝试”的流程,并解释为什么在线升级必须保留 Golden。
- 能从 INITN 的四种异常表现定位加载失败原因,说出”INITN 拉高才能发数、DONE 拉高后补时钟”两条铁律,以及 SVF→AJE 的用途与 Check_Device 调试法。
EF2/EF3 与 EG4 在加载模式配置上最大的区别是什么?比赛用的 EG4S20 属于哪种?
EF2/EF3 内置 Flash,加载模式由 TD 软件写进 Flash 的参数决定,绝大多数用 MSPI;EG4/PH1 外挂 Flash,模式由 MSEL 管脚的上下拉电平决定(SS=11、SP=10、MSPI=01、MP=00)。EG4S20 属于 EG4 系,用 MSEL 配置;但无论哪种器件,JTAG 口都始终可加载,板上应预留 JTAG 插座。
Dual Boot 和 Multi Boot 失败后的行为有什么关键差异?为什么在线升级推荐 Dual Boot?
Dual Boot 加载 Primary 失败会自动跳 Golden,Golden 失败再回 Primary,循环尝试且可从 INITN 连续脉冲观察;Multi Boot 加载失败 FPGA 直接挂死,不会自动回落。在线升级存在”升级中断电、数据写错”导致 Primary 位流不完整的可能,Dual Boot 的 Golden 区域(升级中永不擦写)保证了系统永远有一个可启动的位流和再次升级的通道。
从动串行模式下,bin 和 rbf 文件的发送位序有什么不同?从动并行呢?
从串:bin 文件每字节 MSB(高位)先送,rbf 文件每字节 LSB(低位)先送;从并:bin 文件按字节直接接到 DATA[7:0],rbf 文件每字节的 bit 顺序需要颠倒后再发。位序发错是”回读 Flash 内容对比却完全对不上”的常见原因之一。
DONE 已经拉高了,主机还需要做什么?
还要继续送 SCLK 时钟,直到 FPGA 唤醒状态机走完——bin 文件末尾包含 Dummy 字节。如果加载”看起来完成”但器件没工作,可以尝试再多补一些时钟数量再排查其它原因。
用 MCU 的普通 IO 模拟 JTAG 做 AJE 升级,调试第一步跑什么文件?最容易失败的环节是什么?
第一步跑 Check_Device 这个最简洁的 SVF,验证模拟 JTAG 的基础时序(TCK/TMS/TDI)正确;最容易失败的环节是 Flash 操作的等待时间——擦写需要较长时间,CPU 代码延时不足会导致升级失败,必须按 Flash 手册校准延时函数。