Files
boweiandClaude Opus 5 e07cfaa6d1 sync: WIN-BOWEI 2026-08-10 fpga_flash 增 Zynq BOOT.bin/QSPI 脚本,rtl-ip-replace 与 sim-rtl-flow 更新
- fpga_flash: 新增 build_zynq_boot.py / program_zynq_qspi.py(bootgen + program_flash,
  含备份、SHA-256/容量/marker 守卫);vivado_env.py 增 resolve_sdk_dir(SDK_ROOT/SDK_PATH);
  SKILL.md 补 Zynq 烧写流程,示例去掉写死的 D:\Xilinx\SDK\2018.1,改由 skills_env.md 解析。
- rtl-ip-replace: gen_ip.tcl / namespace_ip.py 更新。
- sim-rtl-flow: SKILL.md 与 run_sim_rtl_flow.py 更新。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 12:50:44 +08:00

16 KiB
Raw Permalink Blame History

name, description
name description
fpga_flash 按开发板/器件架构选择正确的 Flash 固化方式。支持 EMV7.1 等 Artix-7 板卡的 MCS/cfgmem 流程,以及 HJX9009(XC7Z100/Zynq-7000)将 FSBL、PL bitstream、PS ELF 打包为 BOOT.bin 后写入双并行 QSPI 的流程。 当用户提到"烧写 flash"、"flash 编程"、"固化 bit 文件"、"下载到 flash"、"program flash"、"write flash"、"burn flash"、"Vivado flash"、"SPI flash 烧写"时,必须触发此 skill。

FPGA Flash 固化流程(按开发板路由)

本 skill 由 Claude 全自动执行完整的 Flash 固化流程。除了向用户确认必要信息外,所有操作(文件检查、备份、哈希/容量/内容守卫、工具调用、硬件编程)均由 Claude 直接完成,不要求用户手动执行任何命令。执行前必须先识别开发板与 FPGA/SoC 类型;不得把 Artix-7 的 .mcs/cfgmem 流程用于 Zynq,也不得把 Zynq 的 BOOT.bin/program_flash 流程用于普通 Artix-7。


执行规范

自动执行原则:

  • 每个需要调用 Vivado 的步骤,Claude 通过 Bash 工具调用 skill scripts/ 目录下的 Python 脚本
  • 禁止在用户工程目录或系统临时目录(%TEMP%、/tmp)下创建任何脚本文件
  • 所有可执行脚本已预置在 skill 目录的 scripts/ 子目录中,Claude 只需传入正确的参数调用

定位 skill 脚本目录:

Claude 在执行前需先确认脚本的完整路径。使用 Glob 工具查找:

C:/Users/<当前用户>/.claude/skills/fpga_flash/scripts/gen_mcs.py

或直接使用默认路径:%USERPROFILE%/.claude/skills/fpga_flash/scripts/

scripts/ 目录内容:

scripts/
  check_flash_csv.py     # 第一步:检查/更新 Vivado Flash 器件表
  gen_mcs.py             # 第三步:生成 .mcs 文件
  program_flash.py       # 第四、五步:连接目标板并烧写 Flash
  step3_write_mcs.tcl    # gen_mcs.py 使用的 Tcl 模板(勿手动修改)
  step4_5_program.tcl    # program_flash.py 使用的 Tcl 模板(勿手动修改)
  build_zynq_boot.py     # Zynq:FSBL + bit + PS ELF 生成受保护的 BOOT.bin
  program_zynq_qspi.py   # Zynq:哈希/容量/marker 守卫后烧写并强制 verify
  vivado_env.py          # 解析 Vivado/SDK 工具路径

调用方式(Bash 工具):

python "$USERPROFILE/.claude/skills/fpga_flash/scripts/<script>.py" [参数...]

各脚本通过命令行参数接受变量(Vivado/SDK 安装目录、bit/ELF/MCS/BOOT 路径、容量和 marker 等)。Artix-7 脚本内部调用 Vivado -mode batch -source <tcl模板> -tclargs <参数>;Zynq 脚本调用 SDK 的 bootgen/program_flash。工程路径和板级文件均由参数传入,不在 skill 中硬编码。


第零步:识别板卡并选择唯一流程

先用工程名、器件型号、原理图/板卡说明和现有部署资料交叉确认,不允许只根据输出文件扩展名猜测。

板卡/器件 固化容器 写入工具与接口 选择的流程
HJX9009、xc7z100、Zynq-7000(PS+PL) BOOT.bin,顺序为启动 FSBL + PL .bit + PS .elf SDK bootgen + program_flash -flash_type qspi_dual_parallel 本文“Zynq/HJX9009”流程
EMV7.1、xc7a*、Artix-7(纯 PL) .mcs Vivado write_cfgmem + Hardware Manager cfgmem 本文“Artix-7/EMV7.1”流程

硬阻断规则:

  • 发现 xc7z*、PS7、FSBL、PS ELF 或工程明确写明 Zynq 时,禁止运行 gen_mcs.py、program_flash.py 或 create_hw_cfgmem。
  • 发现 xc7a* 且无 PS/FSBL 时,禁止生成 BOOT.bin。
  • 板型、Flash 拓扑或容量不明确时,先查原理图/现有已验证部署记录;不得试烧。
  • HJX9009 已验证为两片 s25fl128s 双并行 QSPI,总容量 32 MiB,必须使用 qspi_dual_parallel,不能退化为 qspi_single。

Zynq/HJX9009:同时固化 PS 与 PL

Z1. 输入与两个 FSBL 角色

生成冷启动镜像需要三个输入,BIF 中顺序不可改变:

the_ROM_image:
{
    [bootloader]<boot_fsbl.elf>
    <implemented_pl.bit>
    <ps_application.elf>
}

必须区分两个角色不同的 FSBL:

  • 启动 FSBL:封装在 BOOT.bin 第一分区,板卡冷启动时由 BootROM 加载,随后配置 PL 并启动 PS 应用。
  • JTAG 烧写辅助 FSBL:由 program_flash -fsbl 临时下载到 OCM,用于初始化当前板卡的 QSPI MIO/控制器并完成写入。它不等于、也不能默认替换 BOOT.bin 内的启动 FSBL。

对 HJX9009,必须使用已验证能初始化该板 QSPI MIO 的参考 JTAG 辅助 FSBL。若项目提供其期望 SHA-256/MD5,必须作为守卫验证。错误的辅助 FSBL 可能读出 JEDEC 00,00,00,造成表面执行但没有可靠写入。

HJX9009 当前工程部署记录中的参考辅助 FSBL 指纹为 MD5 14232757864453B418E67D63457EE24F。这只是板级身份参考,不应写死进通用脚本;实际执行仍应从当前项目部署清单取得文件并同时记录 SHA-256。

Z2. 安全预检与备份顺序

执行顺序固定如下:

  1. 确认本次 PS ELF、时序通过的 PL bitstream、启动 FSBL 和 JTAG 辅助 FSBL 的绝对路径。
  2. 记录四个输入的 SHA-256、字节数和修改时间;若有 .ltx,另记录其 SHA-256,确保它与 bitstream 同次构建。
  3. 在覆盖部署目录中的任何已有 BOOT.bin、BIF、FSBL、bit 或 ELF 前,复制到带时间戳的备份目录并写 manifest。不得删除已知可回退镜像。
  4. 对源文件和 staging 副本逐个比较 SHA-256,任一不一致立即停止。
  5. 为新固件指定至少一个能区分版本的 ASCII marker,并在 PS ELF 和生成的 BOOT.bin 中检查。marker 不匹配立即停止。
  6. 生成后要求 BOOT.bin 严格小于物理 QSPI 容量;HJX9009 上限为 33,554,432 字节。
  7. 记录最终 BOOT.bin 的 SHA-256 和精确长度;烧写命令必须重新校验这两个值,防止旧镜像或 TOCTOU 误烧。

Z3. 生成 BOOT.bin

调用参数化脚本;示例只表示参数结构,实际路径和 marker 必须来自当前项目。 Xilinx SDK 安装根目录由脚本自行解析(SDK_ROOT / SDK_PATH:先查环境变量,再查 ~\skills_env.md),只有需要临时覆盖时才显式传 --sdk-dir:

python "$env:USERPROFILE\.claude\skills\fpga_flash\scripts\build_zynq_boot.py" `
  --boot-fsbl "<cold-boot-fsbl.elf>" `
  --bit-file "<implemented-top.bit>" `
  --app-elf "<ps-application.elf>" `
  --boot-bin "<deployment-dir>\BOOT.bin" `
  --bif-file "<deployment-dir>\boot.bif" `
  --capacity-bytes 33554432 `
  --require-marker "<build-identity-marker>"

脚本会备份已有 BOOT/BIF、生成候选镜像、执行容量与 marker 守卫、原子替换最终镜像,并输出 JSON manifest。成功标志为:

ZYNQ_BOOTGEN_PASS size=<n> sha256=<64 hex>

如果工程采用 staging 目录,复制 FSBL/bit/ELF 后仍要逐项重算并对比 SHA-256。BOOT.bin 约 18 MiB 只是 HJX9009 的常见值,不是成功判据。

Z4. 启动 Vivado hw_server 并确认 JTAG

HJX9009 当前机器上必须由 Vivado 的 hw_server 给 Platform Cable USB II 加载固件;SDK 自带 hw_server 可能无法完成该动作。先启动并等待枚举出 xc7z100:

& '<Vivado-root>\bin\hw_server.bat' -s tcp::3121

保持服务运行,确认 tcp:127.0.0.1:3121 可连接且 JTAG 链中只有预期目标。若 3121 被未知进程占用、目标器件不是 xc7z100、板卡掉电或线缆未枚举,停止,不得烧写。

Z5. 写入 HJX9009 双并行 QSPI 并强制 verify

从 Z3 的输出/manifest 复制精确 SHA-256 和长度后执行:

python "$env:USERPROFILE\.claude\skills\fpga_flash\scripts\program_zynq_qspi.py" `
  --image "<deployment-dir>\BOOT.bin" `
  --jtag-fsbl "<verified-jtag-helper-fsbl.elf>" `
  --expect-sha256 "<exact-BOOT.bin-sha256>" `
  --expect-size <exact-byte-length> `
  --capacity-bytes 33554432 `
  --flash-type qspi_dual_parallel `
  --hw-server-url tcp:127.0.0.1:3121 `
  --expect-jtag-fsbl-sha256 "<exact-helper-FSBL-sha256>" `
  --require-marker "<build-identity-marker>" `
  --log-file "<deployment-dir>\program_flash.log"

安全约束:

  • offset 必须为 0;HJX9009 的 Flash 类型必须保持 qspi_dual_parallel。
  • 参数顺序必须是 -verify 在 -fsbl 前,-cable ... 最后;参数化脚本已固定此顺序。
  • 擦除、编程、回读校验可能超过 10 分钟;期间禁止断电、拔 JTAG、关闭 hw_server 或终止进程。
  • 不信任包装层退出码。已验证存在“无法连接 hw_server 但返回码仍为 0”的情况。

真正成功必须在同一次日志中同时出现:

Erase Operation successful
Program Operation successful
Verify Operation successful
Flash Operation Successful
ZYNQ_QSPI_FLASH_VERIFY_PASS

若出现 Verify Operation unsuccessful、Flash Operation Failed,或缺少任一成功行,一律判失败。End of startup status: HIGH 只证明易失配置完成,不能证明 Flash 已写入。

Z6. 完全断电冷启动与 COM5 验收

烧写成功后还必须验证自主启动:

  1. 保存烧写日志、BOOT manifest、bit/LTX/ELF 哈希和回退镜像位置。
  2. 关闭板卡主电源及可能通过 JTAG 反向供电的接口,静置至少 30 秒;JTAG 枚举异常时按板级规程全断 90 秒。
  3. 保持 JTAG 断开,重新打开主电源,让板卡只从 QSPI 启动。
  4. 打开 COM5(115200、8N1、无流控),保存带时间戳的启动日志。
  5. 要求看到本次 PS 固件的唯一 marker/banner,并执行项目定义的只读状态命令。HJX9009 当前固件通常用 HELP、?,随后按项目规程输入 R;验收期望状态和命令必须以本次固件文档为准。
  6. 若 marker 不匹配、COM5 无输出、PL/PS 版本不一致或只能在重新接入 JTAG 后工作,判定冷启动失败并使用已备份的已知良好镜像回退。

只有“写入日志完整成功 + verify 成功 + 完全断电后 COM5 确认本次固件自主启动”三者同时成立,才可以向用户报告 HJX9009 PS+PL 已固化。


Artix-7/EMV7.1:MCS/cfgmem 流程(保留)

第一步:检查并修复 Vivado Flash 器件表

Claude 自动执行:

调用 check_flash_csv.py,检查 xicom_cfgmem_part_table.csv 中是否已包含 w25q128bv-spi-x1_x2_x4:

python "$USERPROFILE/.claude/skills/fpga_flash/scripts/check_flash_csv.py"

返回值含义:

  • 退出码 0:器件已存在,直接进入第二步
  • 退出码 2:已成功添加器件行,需提示用户重启 Vivado 后才能识别
  • 退出码 1:CSV 未找到,检查 ~/skills_env.md 的 VIVADO_ROOT 是否指向有效的 Vivado 安装

Vivado 安装路径不写死在本 skill 里:三个脚本都通过 scripts/vivado_env.py 按 --vivado-dir > 环境变量 > ~/skills_env.md 的 VIVADO_ROOT(退化到 VIVADO_PATH) 的顺序解析。换机器只改 ~/skills_env.md,不改 skill。仅在需要临时用另一套 Vivado 时才显式传 --vivado-dir。


第二步:选择 Flash 型号

询问用户板卡上焊接的 Flash 芯片型号,仅支持以下两种:

选项 厂商 --flash-part 值
1 Micron mt25ql128-spi-x1_x2_x4
2 Winbond w25q128bv-spi-x1_x2_x4

记录用户选择,后续步骤中作为 --flash-part 参数传入。如果用户不确定,提示查看板卡丝印或原理图中 Flash 芯片的位号。


第三步:确认文件路径并自动生成 .mcs

需向用户确认:

  1. .bit 文件的完整路径(通常在工程 runs/impl_1/ 目录下)
  2. 输出 .mcs 文件的保存路径和文件名(建议与 .bit 文件同目录)

用户确认后,Claude 自动调用:

python "$USERPROFILE/.claude/skills/fpga_flash/scripts/gen_mcs.py" \
    --bit-file   "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
    --mcs-file   "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs"

将示例路径替换为用户实际的 .bit 文件路径、.mcs 输出路径(Vivado 路径自动解析,见第一步)。

验证成功的标志: 输出中包含 write_cfgmem completed successfully 且显示 0 Errors。


第四步 + 第五步:连接目标板、配置存储器并烧写

确认板卡已上电并连接 JTAG 后,Claude 自动调用:

python "$USERPROFILE/.claude/skills/fpga_flash/scripts/program_flash.py" \
    --flash-part  "w25q128bv-spi-x1_x2_x4" \
    --bit-file    "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
    --mcs-file    "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs" \
    --ltx-file    "E:/Xilinx_design/smod/SMOD_DTMB_CG/RU_golden/RU_golden.runs/impl_1/RU_golden_top.ltx"

参数说明:

  • --flash-part:第二步用户选择的型号
  • --bit-file:第三步确认的 .bit 路径
  • --mcs-file:第三步生成的 .mcs 路径
  • --ltx-file:若设计无 ILA,省略此参数(脚本自动跳过 PROBES.FILE 配置)

此脚本在同一个 Vivado batch 会话中完成:硬件连接 → cfgmem 器件创建 → 载入 flash-loader 比特流(关键步骤) → 擦除/编程/验证 → 回载用户 bit。

验证成功的标志(真正写入 flash): 输出必须包含 Performing Erase Operation... Erase Operation successful、 Program/Verify Operation successful、Flash programming completed successfully, 并能读到非零的 Mfg ID(如 Winbond=ef、Micron=20)。

⚠️ 仅有 End of startup status: HIGH 不代表写了 flash——那只是把 bit 载入 FPGA 易失配置。若看到 Mfg ID : 0 / Unable to read device properties,说明 flash-loader 没接管 SPI 总线(本 tcl 已用 create_hw_bitstream+program_hw_devices 载入 spi_<part>_pullnone.bit 修复此问题)。

ILA core 的 Dropping logic core WARNING 是正常现象(载入 loader/golden 镜像时不含 ILA core),不影响烧写结果。


第六步:上电验证

烧写完成后,提示用户:

  1. 断开 JTAG,给板卡重新上电(或按复位键)
  2. 观察 FPGA 是否从 Flash 正常加载(DONE 灯亮起)
  3. 如果 DONE 灯不亮,检查:
    • BOOT_MODE 跳线是否选择 SPI Flash 启动模式
    • MCS 生成时起始地址是否为 0x0
    • 板卡电源是否满足 Flash 的 VCC 要求(3.3V / 1.8V)

常见错误排查

现象 可能原因 解决方法
check_flash_csv.py 退出码 1 VIVADO_ROOT 未配置或指错 修正 ~/skills_env.md 的 VIVADO_ROOT;临时可传 --vivado-dir 覆盖
Vivado 中找不到 w25q128bv CSV 已修改但 Vivado 未重启 提示用户重启 Vivado 后重新执行
bad lexical cast: source type value could not be interpreted as target,报在 get_cfgmem_parts 或 refresh_hw_device 上 CSV 里的 w25q128bv 行畸形(2026-07-30 之前的版本写的是 9 字段、从 NAME 开头,缺了首列数字 CFGMEM_ID),Vivado 拿名字当整数解析 重跑 check_flash_csv.py,它会识别并替换掉畸形行(退出码 2),然后重启 Vivado。注意报在 refresh_hw_device 上极具误导性 —— 那一步内部也读这张表,看起来像硬件/probe 问题,其实与 .ltx、debug core 无关
No hardware target 错误 JTAG 未连接或板卡未上电 检查连接后重新执行第四步
DONE 灯不亮 启动模式跳线错误 检查 MODE 引脚电平,确认为 SPI 启动模式
烧写后板卡跑旧程序 Flash 未完全擦除 确认 PROGRAM.ERASE 1 已设置后重新执行
PermissionError 写 CSV 权限不足 提示用户以管理员身份运行 Claude Code
Zynq program_flash 返回 0 但无成功行 hw_server 未连接或工具包装层假成功 按日志判失败;要求 erase/program/verify/Flash 四组成功标志齐全
HJX9009 JEDEC 为 00,00,00 JTAG 辅助 FSBL 未正确初始化 QSPI MIO 使用项目已验证的参考辅助 FSBL并核对哈希,保持 qspi_dual_parallel
BOOT.bin 可写但冷启动无 COM5 启动 FSBL/PS ELF/PL 不匹配或未自主启动 完全断电、断开 JTAG,从 QSPI 冷启动并核对固件 marker;失败则回退备份