Update FPGA and Vivado skills

This commit is contained in:
Myfro9
2026-07-14 18:18:17 +08:00
parent d20ec12fee
commit bceafcd58c
14 changed files with 1707 additions and 14 deletions
+77
View File
@@ -0,0 +1,77 @@
# Flash 布局与 QuickBoot 兜底
板上 flash:Winbond **w25q128bv**,128 Mbit = 16 MB,SPIx1,**24-bit 地址**,64 KB sector / 4 KB subsector。
## 三个地址,一个都不能记错
来自 `my_exciter.srcs/sources_1/quickboot/SpiFlashProgrammer.vhd`(**RU_golden 和 my_exciter 引用的是同一份文件**,
见 `RU_golden.xpr` 里的 `$PPRDIR/../my_exciter/.../SpiFlashProgrammer.vhd`,所以两个工程的常数天然一致):
```vhdl
cAddrUpdateStart = X"00400000" -- update 镜像起点
cAddrUpdateEnd = X"00C00000" -- update 镜像终点+1 → 槽宽 8 MB
cAddrSwitchWordN25Q = X"00000FFC" -- 切换字
cAddrWidth = 24 -- 和 w25q128bv 匹配
```
flash 实际布局(从 `golden_design_initial.mcs` 解码得到,不是推测):
```
0x000000..0x000FFB FF FF ... 空
0x000FFC 00 99 55 66 切换字(AA 被写成 00 = 无效)
0x001000 20000000 NOOP
30020001 00400000 写 WBSTAR = 0x400000
30008001 0000000F 写 CMD = IPROG → 跳到 update 镜像
0x001050 AA995566 golden bitstream 自己的同步字
..0x3FFFFF golden bitstream(RU_golden_top.bit,3.4 MB)
0x400000..0xBFFFFF update 镜像(8 MB,日常远程升级写这里)
0xC00000..0xFFFFFF 未用
```
**兜底机制**:上电时 FPGA 从地址 0 扫描同步字。
- 切换字 = `AA995566` → 在 0xFFC 同步 → 执行 0x1000 处的 IPROG → 加载 update 镜像。
- 切换字 ≠ `AA995566`(擦除后是 `FFFFFFFF`)→ 0xFFC 不同步 → 继续扫 → 在 0x1050 撞上 golden 的同步字 → **加载 golden**。
远程升级一开始就把切换字所在的 subsector 擦掉(`sProgrammerEraseSwitchWord`,SSE 命令,
擦 `0x000000..0x000FFF`),写完校验通过后再把切换字写回去。所以**升级中途断电只会退回 golden,不会变砖**。
> subsector 是 4 KB,擦 0xFFC 只波及 `0x000000..0x000FFF`。IPROG 头在 `0x001000`,属于下一个
> subsector,**不会被擦到**。golden 是安全的 —— 如果怀疑"升级把 golden 弄坏了",可以排除这条。
## 为什么 `-imagesize 64`
perl 脚本的模型是"golden 和 update 一样大、update 紧跟 golden":
`imageSizeBytes = imagesize(Mbit) × 131072`,`updateStartAddr = imageSizeBytes`。
- **golden**(`MakeSpiFlashProgrammerOnlyInitMcs.pl -imagesize 32`)→ 4 MB → IPROG 里的
WBSTAR = `0x400000`,和 `cAddrUpdateStart` 对上。日志见 `RU_golden/bitstream/gen_initial.log`。
- **update**(`MakeSpiFlashProgrammerMcsFiles_backup.pl -imagesize 64`)→ 8 MB → 负载
`pad(bitstream, 0x7FFFFC) + crc32` 正好 8 MB,和槽宽 `0xC00000-0x400000` 对上。
两个 imagesize 不一样是**故意的**(VHDL 注释里的 "Plan B: golden enlarged to 4MB"),别去"统一"它们。
`_update.mcs` 里的 Intel-HEX 地址写的是 `0x800000`,看起来和 `cAddrUpdateStart=0x400000` 矛盾 ——
**它不矛盾,因为地址被忽略**。imx6 的 `recv_upgrade_data_parse()` 只从 `:10xxxx00<32 hex>` 记录里抠出
16 个数据字节,扩展线性地址记录 `:02000004` 直接当"中间控制字段"丢掉。FPGA 从 `cAddrUpdateStart`
顺序写。所以对远程升级而言,`_update.mcs` 只有**负载长度**和**CRC**是有意义的。
校验 `_update.mcs` 的起始地址是 `0x800000`,本质上是在校验"这个文件是用 `-imagesize 64` 生成的"。
## 两条烧写路径,别搞混
| | JTAG 直烧 | 网络远程升级 |
|---|---|---|
| 文件 | `RU_golden/bitstream/golden_design_initial.mcs` | `bitstream/<tag>_update.mcs` |
| 工具 | `/fpga_flash` skill(flash 型号 `w25q128bv`) | `scripts/fpga_ru.py` |
| 写到 | `0x000000..0x3FFFFF` | `0x400000..0xBFFFFF` |
| 何时用 | 首次装机、板子变砖、换打底镜像 | 日常迭代 |
`_update.mcs` **不能**拿去 JTAG 烧写:它只是 8 MB 裸数据 + CRC,没有 bitstream 头。
反过来 `_initial.mcs` 也不能拿去远程升级。
严守上电时序:断电 → 断 USB-Blast → 上电 → 连 USB-Blast → 烧写 → 断电 → 断 USB-Blast → 上电 → 连 USB-Blast。
## 调试期的第三条路
`program_device` 直接把 `.bit` 下到 FPGA,掉电即失,不碰 flash,配 `.ltx` 还能抓 ILA。
迭代验证用它最快,功能确认后再走远程升级固化。固化用的 bit 要**去掉 ILA 重新实现**。