STEP: 1596 / Date: 2026-08-30 / Status: ✅ E2E 動作確認完了 (Tang Nano 9K + STEP 1591 bitstream で 1 attempt PASS)
★ STEP 1586 で発見された programming transient (programmer_cli 100% 完了報告 + Status non-error なのに FPGA に data 到達せず) を fs↔programmed UserCode diff で 一発検知 + auto retry する wrapper。 STEP 1590 で 「User code mismatch」 warning が critical signal であることが 実証され、 本 STEP で それを code 化。 Phase C 全 project の README を wrapper 経由に 統一。
scripts/gowin-program-verify.sh -f impl/pnr/<project>.fs
| Flag | Default | 説明 |
|---|---|---|
-f FSFILE | (required) | .fs bitstream path |
-c INDEX | 1 | cable-index |
-d DEVICE | GW1NR-9C | --device value (Tang Nano 9K default) |
-r RETRIES | 3 | max retry on mismatch |
--flash | off | embFlash Program (irreversible); default = SRAM (reversible) |
--programmer PATH | Gowin V1.9.12.02_SP2 | programmer_cli.exe path override |
//UserCode: header を 事前抽出 (例: 0x0000E28C)programmer_cli --device ... --cable-index ... --run 2 --fsFile FSFILE 実行User Code is: 0xNNNNNNNN + Status Code is: 0xNNNNNNNN + Cost 抽出"User code mismatch" warning 有無 検出scripts/gowin-program-verify.sh -f hardware/phase-c/14-nano9k-inductive-coil-loopback/impl/pnr/inductive_coil_loopback.fs
═══════════════════════════════════════════════════════════════
Gowin program-verify
fs file: .../inductive_coil_loopback.fs
fs UserCode: 0x0000E28C
device: GW1NR-9C
cable-index: 1
run mode: 2 (SRAM Program (reversible))
max retries: 3
═══════════════════════════════════════════════════════════════
attempt 1 result:
programmed User Code: 0x0000E28C
Status Code: 0x0003F020
Cost 3.02 second(s)
✅ MATCH — configuration OK (fs=0x0000E28C == prog=0x0000E28C)
═══════════════════════════════════════════════════════════════
✅ SUCCESS after 1 attempt(s)
═══════════════════════════════════════════════════════════════
$ scripts/gowin-program-verify.sh ERROR: -f FSFILE is required $ echo $? 2 $ scripts/gowin-program-verify.sh -f /nonexistent.fs ERROR: file not found: /nonexistent.fs $ scripts/gowin-program-verify.sh -f /tmp/fake.fs # 不正 fs ERROR: could not extract UserCode from fs header: /tmp/fake.fs (expected line like: //UserCode: 0xNNNNNNNN)
| Code | 意味 |
|---|---|
| 0 | program 成功 + UserCode 一致 verify OK |
| 1 | configuration 失敗 (retry 後も mismatch or 通信 error) |
| 2 | usage error (args 不正 / fs 不在 / UserCode header 抽出失敗) |
STEP 1586 で発生した incident: Rev 1 (counter reset-comparison pattern) の bitstream を Program → progress bar 100% + "Finished. Cost 4.89 second(s)" = 見た目 成功 → LED 点滅せず。 唯一の critical signal は 「User Code is: 0x00000000」 (fs 側は valid checksum のはずが 0 = configuration 失敗) と 「User code mismatch」 warning。 私 (Claude) は これを cosmetic 判断 (「set_option -user_code 未指定 だから」) してしまい、 「STEP 1574 generator の bug」 と 誤診断。
STEP 1590 で hardware 不要 diagnostic (byte-for-byte 同一 source rebuild → LUT/FF/CLS 完全一致 + fs UserCode 0x0000B4BF valid) で 「code は 正しい」 と 特定、 STEP 1590 silicon retest で 「program → UserCode 一致 + LED 点滅」 で 完全裏付け = 単なる一時的 programming failure だった と 確定。
Wrapper 使用で 「気付かない失敗」 を fs↔programmed UserCode diff で 一発検知 できる。 mismatch なら 自動 retry で 大半の transient は 2 回目以内で 通る。
hardware/phase-c/README.md — 「Programming protocol」 section 追加 (トップに 目立つ 位置)hardware/phase-c/04-tang-nano-9k-led-blinky/README.md — wrapper section 追加 + 生 programmer_cli を legacy 扱いにhardware/phase-c/12-tang-nano-9k-radio-clock-silicon/README.md — wrapper に切替hardware/phase-c/13-nano9k-radio-clock-rev1-diagnostic/README.md — reprogram section 追加hardware/phase-c/14-nano9k-inductive-coil-loopback/README.md — wrapper に切替05-11 の 過去 spike project (xor-nand / uart-i2c-scaffold / bme280-phase2 / osco-drift / ring-puf-spike / dfumt8-alu) は 生 programmer_cli 参照を そのまま残す (rewrite せず、 top-level README で wrapper 推奨を明示) — legacy 保存の 保守方針。 新規 spike は 必ず wrapper 経由。
--flash で embFlash (irreversible) を 明示 opt-in する discipline (destructive action への 安全弁)--programmer flag で 上書き-d GW5AST-138B 明示要 (別途 verify 未実施)scripts/gowin-program-verify.sh (~140 line、 pure bash)hardware/phase-c/README.md (Programming protocol section 追加)hardware/phase-c/04, 12, 13, 14/README.md (wrapper 参照に update)