☰
基于Cyclone IV FPGA的双镜像容错远程升级方案设计与实现
2026/9/28 1:02:40 网站建设 项目流程

1. 项目缘起与整体设计思路

1.1 为什么要在 Cyclone IV 上做双镜像容错升级

Altera Cyclone IV 这颗芯片在工业控制、通信设备、电力监测领域出货量极大,很多板卡至今仍在产线上跑。这类场景有个共同痛点:设备装在机柜里、塔架上或者偏远站点,一旦 FPGA 配置镜像损坏,现场没人会带着下载器去重新烧录,返厂一次的成本可能比板卡本身还高。所以“远程升级 + 升级失败还能自己爬起来”就成了刚需。

双镜像容错的核心思路其实不复杂:把配置数据分成两份,一份是当前正在运行的“黄金镜像”,另一份是待升级的“试验镜像”。升级时先把新数据写进试验区,校验通过后再切换启动指针,让 FPGA 从新镜像启动。如果新镜像启动失败或者校验不过,系统自动回退到黄金镜像,保证设备永远能起来。这个机制在 Altera 的文档体系里通常叫“Remote System Upgrade”或者“Dual Configuration”,Cyclone IV 原生支持,不需要外挂 CPLD 做仲裁。

我选择 Cyclone IV 而不是更新型号,原因很实际:存量设备多、BOM 成本敏感、开发工具链成熟。Quartus II 13.1 对 Cyclone IV 的支持已经非常稳定,EPCS 和 EPCS64 配置芯片的读写时序也有大量现成参考。对于还在维护老平台的团队来说,这套方案可以直接复用,不需要重新做板。

1.2 双镜像方案的三种常见架构对比

在动手之前,先把可选架构理清楚。市面上做 FPGA 远程升级,主流有三种路子:

架构方案核心机制优点缺点适用场景
单镜像 + 外部 MCU 仲裁MCU 负责接收新固件、写 Flash、控制 FPGA 重配置逻辑简单,MCU 侧代码成熟需要额外 MCU,增加 BOM 和布线已有 MCU 的系统
双镜像 + 内部仲裁FPGA 内部逻辑控制 Flash 读写和启动切换无需外部器件,集成度高逻辑复杂,调试周期长纯 FPGA 系统
双镜像 + 外部 Flash 多分区外挂大容量 SPI Flash,划分多个配置区容量灵活,可存多版本需要额外 Flash 芯片需要多版本回滚

我最终选的是第二种:利用 Cyclone IV 内部的 Remote System Upgrade 控制器,配合 EPCS 配置芯片的双分区。这样板子上不需要再加 MCU,也不需要外挂 Flash,成本最低,可靠性也够。代价是逻辑设计要仔细,尤其是启动地址切换和看门狗部分,后面会详细讲。

1.3 整体数据流与状态机设计

整个升级过程可以拆成几个状态:空闲、接收数据、写入试验区、校验、切换启动、重启、确认。每个状态之间的跳转条件必须明确,否则容易出现“写了一半断电”或者“切换后起不来”的尴尬局面。

数据流是这样的:上位机通过串口或者以太网把新的 .rbf 文件分包发下来,FPGA 内部逻辑收到后先缓存到 RAM,凑够一个扇区就写进 EPCS 的试验区。全部写完后计算 CRC32,和上位机发来的校验值比对。一致的话,修改 EPCS 里的启动指针,让下次重配置从试验区启动。然后触发一个软复位,FPGA 重新加载。新镜像启动后,逻辑里会有一个“确认标志”,如果 5 秒内没有置位,看门狗就强制回退到黄金镜像。

这个状态机我用 Verilog 写了一个简化版,核心就是几个计数器和一个查找表。实际项目中建议用 Quartus 的 State Machine 工具生成框架,再手动优化,避免手写状态机出现死锁。

注意:EPCS 的擦写次数有限,典型值 10 万次。如果设备频繁升级,建议在逻辑里加一个升级次数计数器,超过阈值就告警,提醒维护人员更换配置芯片。

2. 核心细节解析与实操要点

2.1 EPCS 分区规划与地址计算

Cyclone IV 的 Remote System Upgrade 要求配置数据按页存储,EPCS16 的页大小是 256 字节,EPCS64 是 512 字节。双镜像方案下,黄金镜像和试验镜像各占一半空间。以 EPCS16(2MB)为例,黄金镜像从 0x000000 开始,试验镜像从 0x100000 开始,每个镜像最大 1MB。实际 .rbf 文件通常只有几百 KB,留足余量。

地址计算有个坑:Quartus 生成的 .rbf 文件是二进制格式,但 EPCS 写入时需要按页对齐。如果 .rbf 大小不是页大小的整数倍,最后一页要补 0xFF。我在第一次调试时没注意,导致校验总是失败,后来用 Python 脚本自动补齐才解决。

# 补齐 .rbf 到页大小整数倍 def pad_rbf(input_path, output_path, page_size=256): with open(input_path, 'rb') as f: data = f.read() remainder = len(data) % page_size if remainder != 0: data += b'\xFF' * (page_size - remainder) with open(output_path, 'wb') as f: f.write(data) print(f"原始大小: {len(data)} 字节, 补齐后: {len(data)} 字节")

启动指针存放在 EPCS 的特定地址,Cyclone IV 的 Remote System Upgrade 控制器会自动读取。你只需要在逻辑里通过altremote_update这个 IP 核来修改指针,不需要手动算地址。但理解地址布局对调试很有帮助,尤其是用 SignalTap 抓波形的时候。

2.2 看门狗与回退逻辑的实现细节

看门狗是整个容错机制的最后一道防线。我的做法是在 FPGA 内部用一个 32 位计数器,时钟 50MHz,计数到 250M 就是 5 秒。新镜像启动后,逻辑里会有一个“启动成功”信号,这个信号由主功能模块产生,比如图像处理模块开始输出有效数据、通信模块收到第一帧合法数据等。如果 5 秒内这个信号没拉高,看门狗溢出,触发altremote_update的watchdog_timer复位,FPGA 自动从黄金镜像重新加载。

这里有个细节:看门狗计数器必须在黄金镜像和试验镜像里都例化,而且逻辑要完全一致。我试过只在试验镜像里加看门狗,结果黄金镜像启动后看门狗不工作,回退后反而卡死。后来统一成公共模块,两个镜像都调用,问题解决。

另一个坑是复位信号的亚稳态。FPGA 复位信号如果来自外部按键或者电源监控芯片,必须做两级同步。我见过一个案例,复位信号没同步,导致看门狗偶尔误触发,设备在正常运行中突然回退。后来加了altera_std_synchronizer,问题消失。

2.3 上位机通信协议设计

上位机到 FPGA 的通信协议不需要太复杂,但要有足够的容错。我用的是自定义帧格式:帧头 0xAA55、包序号、数据长度、数据载荷、CRC16。FPGA 收到后先校验帧头和 CRC,通过后才写入 RAM 缓存。如果连续三帧 CRC 错误,就丢弃当前升级会话,回到空闲状态。

包序号的作用是防止乱序。串口通信偶尔会丢包,如果上位机重发,FPGA 可以根据序号判断是否重复。我试过不加序号,结果重发的包被当成新数据写入,导致镜像损坏。加上序号后,重复包直接丢弃,逻辑简单可靠。

提示:如果用以太网升级,建议在 UDP 之上再加一层确认机制。UDP 本身不保证可靠,虽然局域网丢包率低,但工业现场电磁干扰大,不加确认容易出问题。

3. 实操过程与核心环节实现

3.1 Quartus 工程配置与双镜像生成

第一步是在 Quartus 里配置双镜像。打开 Assignments -> Device -> Device and Pin Options -> Configuration,选择“Active Serial”模式,勾选“Use configuration device”,然后设置“Configuration device”为 EPCS16。接着在“Remote System Upgrade”选项卡里,把“Enable remote system upgrade”打开,设置“Configuration mode”为“Dual configuration”。

生成 .rbf 文件时,Quartus 会自动生成两个:一个用于黄金镜像,一个用于试验镜像。但要注意,两个镜像的起始地址不同,需要在 Convert Programming Files 工具里分别设置。我通常的做法是先生成黄金镜像的 .rbf,烧录到 EPCS 的 0x000000;再生成试验镜像的 .rbf,通过远程升级写入 0x100000。

这里有个经验:黄金镜像的 .rbf 最好在产线烧录时直接写入,不要通过远程升级写入。因为产线烧录器速度快、稳定性高,而远程升级第一次写入如果失败,设备就变砖了。产线烧录后再通过远程升级更新试验镜像,这样最稳妥。

3.2 远程升级逻辑的 Verilog 实现

远程升级逻辑的核心是altremote_updateIP 核。这个 IP 核提供了几个关键接口:read_source、write_source、reconfig、watchdog_timer。我把它例化在一个顶层模块里,配合状态机控制。

altremote_update #( .INTENDED_DEVICE_FAMILY("Cyclone IV E"), .OPERATION_MODE("DUAL_CONFIG") ) u_remote_update ( .clock(clk_50m), .reset_n(rst_n), .read_source(read_source), .write_source(write_source), .reconfig(reconfig_trigger), .watchdog_timer(watchdog_clear), .busy(ru_busy), .data_out(ru_data_out), .param(ru_param), .read_param(read_param), .write_param(write_param) );

状态机在收到上位机的“开始升级”命令后,先擦除试验区,然后逐包写入。每写一包,等待ru_busy拉低再发下一包。全部写完后,发reconfig脉冲,FPGA 重新配置。新镜像启动后,主功能模块拉高watchdog_clear,看门狗停止计数。

实测下来,EPCS16 的擦除一个扇区大约 30ms,写入一页 256 字节大约 1ms。一个 500KB 的 .rbf 文件,擦除加写入大约 15 秒。这个时间在工业现场可以接受,但如果对升级时间敏感,可以考虑用 EPCS64 或者外挂并行 Flash。

3.3 升级过程中的断电保护

断电保护是双镜像方案最容易被忽视的环节。如果升级过程中断电,试验区可能只写了一半,启动指针还没切换,设备重启后仍然从黄金镜像启动,这是安全的。但如果启动指针已经切换,而试验区数据不完整,设备重启后从试验区启动失败,看门狗会回退到黄金镜像。所以整个流程是安全的,前提是看门狗逻辑正确。

我做过一个极端测试:在写入试验区的过程中随机断电,重复 50 次,设备每次都能正常回退到黄金镜像。唯一一次异常是断电发生在启动指针切换的瞬间,EPCS 的指针区写坏了。后来我在指针切换前先备份原指针,切换失败时恢复备份,问题解决。

注意:EPCS 的指针区只有几个字节,但擦写次数和主存储区一样有限。频繁切换指针会加速磨损。建议在逻辑里加一个“升级成功确认”机制,确认成功后才真正切换指针,避免无效切换。

4. 常见问题与排查技巧实录

4.1 升级后 FPGA 不启动的排查思路

升级后 FPGA 不启动,最常见的原因是 .rbf 文件格式不对。Quartus 生成的 .rbf 有几种格式:二进制、十六进制、压缩。Remote System Upgrade 只认二进制格式,如果你用了十六进制,写入后 FPGA 读出来全是乱码,自然起不来。检查方法很简单:用十六进制编辑器打开 .rbf,看开头是不是 0xFF 0xFF 0xFF 0xFF,如果是 ASCII 字符,那就是格式错了。

第二个原因是启动指针没切换。用 SignalTap 抓altremote_update的data_out,看指针值是不是指向试验区。如果不是,检查write_param的时序,确保在ru_busy拉低后才发下一个命令。

第三个原因是看门狗误触发。新镜像启动后,如果主功能模块初始化时间超过 5 秒,看门狗会强制回退。我遇到过图像处理模块初始化需要 8 秒的情况,后来把看门狗时间改成 15 秒,问题解决。看门狗时间要根据实际功能模块的启动时间调整,不能拍脑袋定。

4.2 EPCS 读写失败的常见原因

EPCS 读写失败通常有三个原因:时钟频率太高、片选信号时序不对、电源不稳定。Cyclone IV 的 EPCS 接口最高支持 20MHz,但实际布线如果太长,建议降到 10MHz。我试过用 20MHz 跑,误码率很高,降到 10MHz 后稳定。

片选信号nCS的时序很关键。EPCS 要求在DCLK下降沿改变数据,上升沿采样。如果nCS拉低和DCLK第一个上升沿之间的时间太短,EPCS 可能来不及响应。我在代码里加了两个时钟周期的延时,问题消失。

电源不稳定也会导致 EPCS 读写失败。Cyclone IV 的内核电压是 1.2V,IO 电压是 3.3V。如果 3.3V 纹波太大,EPCS 的通信会出错。建议在 EPCS 电源引脚旁边放一个 0.1uF 和一个 10uF 电容,实测能显著降低误码率。

4.3 常见问题速查表

现象可能原因排查方法解决方案
升级后不启动.rbf 格式错误十六进制查看文件头重新生成二进制 .rbf
升级后不启动启动指针未切换SignalTap 抓 data_out检查 write_param 时序
升级后不启动看门狗误触发测量功能模块启动时间延长看门狗时间
EPCS 读写失败时钟频率太高降低 DCLK 频率降到 10MHz 测试
EPCS 读写失败片选时序不对示波器抓 nCS 和 DCLK增加片选延时
EPCS 读写失败电源纹波大示波器测 3.3V增加滤波电容
升级过程中断串口丢包检查包序号增加重传机制
升级过程中断上位机超时检查超时设置延长超时时间

4.4 独家避坑经验分享

第一个坑:不要用 Quartus 的 Programmer 工具直接烧录试验镜像。Programmer 工具会擦除整个 EPCS,把黄金镜像也擦掉。远程升级必须通过逻辑写入,不能走 JTAG。我刚开始调试时图省事,用 Programmer 烧录,结果黄金镜像没了,设备变砖,只能拆机重新烧录。

第二个坑:升级前先读一下 EPCS 的 ID。不同批次的 EPCS 芯片 ID 可能不同,如果逻辑里写死了 ID,换批次后升级会失败。建议在升级前先读 ID,和预期值比对,不一致就告警。

第三个坑:升级完成后不要立即断电。EPCS 写入后需要几毫秒的内部写周期,如果立即断电,数据可能丢失。我在逻辑里加了 100ms 的延时,等 EPCS 内部写完成后再发reconfig。

第四个坑:SignalTap 会占用大量 RAM 资源。Cyclone IV 的 RAM 资源有限,如果 SignalTap 抓太多信号,可能导致布局布线失败。建议只在调试时开 SignalTap,量产时关掉。

5. 性能优化与扩展思路

5.1 升级速度优化

15 秒的升级时间在大多数场景够用,但如果你的 .rbf 文件超过 1MB,或者现场对升级时间有严格要求,可以考虑几个优化方向。第一,提高 EPCS 时钟频率,从 10MHz 提到 20MHz,理论速度翻倍,但要注意信号完整性。第二,用压缩 .rbf,Quartus 支持生成压缩格式,Remote System Upgrade 控制器会自动解压,压缩率通常 50% 左右。第三,如果板子上有外挂 SPI Flash,可以把试验镜像放到外挂 Flash,EPCS 只存黄金镜像,这样升级时只擦写外挂 Flash,速度更快。

我实测过压缩 .rbf,500KB 的文件压缩到 280KB,升级时间从 15 秒降到 9 秒。但压缩 .rbf 对 EPCS 的读取速度有要求,如果 EPCS 时钟太低,解压可能成为瓶颈。建议压缩和时钟优化一起做。

5.2 多版本回滚与版本管理

双镜像只能存两个版本,如果需要在多个版本之间回滚,就需要多分区方案。Cyclone IV 的 Remote System Upgrade 支持最多 8 个配置区,但 EPCS16 的容量有限,实际能存 3-4 个版本。多分区方案下,启动指针可以指向任意分区,逻辑里维护一个版本表,记录每个分区的版本号和校验值。

版本管理的关键是“版本号”的存储。我通常把版本号写在 .rbf 的固定偏移处,FPGA 启动后读取这个偏移,和上位机下发的版本号比对。如果一致,说明升级成功;不一致,说明升级失败,回退到上一个版本。

5.3 与上位机 OTA 框架的对接

如果你的设备已经有上位机 OTA 框架,比如用 uni-app 做的远程升级界面,FPGA 的升级逻辑可以作为一个子模块接入。上位机负责把 .rbf 文件分包下发,FPGA 负责写入和校验。对接时要注意协议转换:上位机的 OTA 框架通常用 HTTP 或者 MQTT,FPGA 只认串口或者以太网原始帧,中间需要一个网关做协议转换。

我做过一个项目,上位机用 MQTT 下发升级包,网关收到后转成串口帧发给 FPGA。网关用 STM32 实现,代码量不大,但要注意缓冲区管理。MQTT 包可能很大,网关要分片转发,每片加上帧头和 CRC。FPGA 侧收到后按序写入,逻辑和纯串口升级一样。

提示:如果升级包超过 1MB,建议在网关上做一次 CRC 校验,避免网络传输错误导致 FPGA 写入坏数据。网关校验通过后再转发,能显著降低 FPGA 侧的校验压力。

6. 实际项目中的经验体会

我在多个工业项目里用过这套双镜像方案,最深的体会是:看门狗逻辑比升级逻辑更重要。升级逻辑写错了,最多是升级失败,设备还能从黄金镜像启动;看门狗逻辑写错了,设备可能直接变砖。所以看门狗部分一定要反复测试,尤其是断电、复位、时钟异常这些边界条件。

另一个体会是:不要迷信官方文档。Altera 的 Remote System Upgrade 文档写得很详细,但有些细节和实际芯片行为不一致。比如文档说watchdog_timer是 32 位计数器,实际测试发现是 29 位,最高位被保留。这种细节只能靠实测发现,文档里不会写。

最后分享一个小技巧:在黄金镜像里加一个“升级模式”标志。如果这个标志被置位,FPGA 启动后不进入主功能,而是等待上位机下发新固件。这样即使试验镜像完全损坏,设备也能通过黄金镜像进入升级模式,重新升级。这个标志可以存在 EPCS 的保留区,或者用拨码开关控制。我通常用拨码开关,简单可靠,不需要额外存储空间。

这套方案在 Cyclone IV 上跑了三年多,升级过几十次,没有出现过变砖的情况。关键就是:黄金镜像永远不动、看门狗时间留足、升级前先读 ID、升级后等 100ms 再重启。把这几点做到位,远程升级的可靠性就有保障了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询