STEP 1427 — Tang Nano 9K Ring oscillator PUF spike (Option A)

2026-08-27 · STEP 1415 OSCO drift の sibling · STEP 1409 5-step spike template の end-to-end 完走 2 例目 · Tang Nano 9K 物理 silicon 8 例目 · wiring 能力 boundary 遵守 手元 hardware 完結 spike

目的

藤本さん 3-task 順番処理 directive 中、 「Tang Nano 9K では代替 になりませんか?」 → Option A OSC drift (STEP 1415)、 続いて 発注 stance 探索 → wiring 能力 boundary 明示 (「私の能力では BME280 の 接続が 出来ません」) → feedback rule 2 追加 → 次 spike arc 3 選択肢 A/B/C 提示 → 藤本さん directive 「両方お願い致します」 → 私 (Claude) の 推奨 A (Ring PUF) で proceed → STEP claim 1427 → 5-step 実装 → 実測 verify。

本 spike の primary purpose = combinational feedback loop を 使う LUT-based ring oscillator が Gowin GW1NR-9C で 実現可能か の 検証。 副 goal = STEP 1350 verdict primitive の 「不確実性 → NEITHER」 原則が operational に働くか の 確認。

設計

27 MHz crystal (pin 52) ──┬── clk_27m domain 1-second gate (27M count)
                          └── ring_slow edge detect (2-FF sync + rise)
                                    │
                                    ▼
                            edge counter (24-bit)
                                    │
              gate expires ──▶ latch slow_cnt / reset / sec_cnt++
                                    │
                                    ▼
                    UART TX (115200 8N1) → USB VCP → PC COM9
                    "RPUF:REF=27000000,DIV=XXXXXX,SEC=YY\r\n"

51-stage LUT chain (combinational feedback, syn_keep = "true")
    ring[0] = ~ring[50]
    ring[i] = ~ring[i-1] for i > 0
       ↓
    async ripple divider 16 stages (÷ 65536)
       ↓
    ring_slow (~164 Hz @ ring 10.77 MHz)
       ↓
    (sampled into clk_27m domain, safe << 13.5 MHz Nyquist)

実装

Files (6、 hardware/phase-c/11-tang-nano-9k-ring-puf-spike/)

FileLinesPurpose
ring_puf_top.v~26051-stage LUT chain feedback loop + 16-stage ripple divider + edge counter + UART emitter
uart_tx.v~758N1 UART TX (STEP 1410/1411/1415 verbatim copy)
tang_nano_9k.cst~28Pins: clk 52, LED[0-3] 10/11/13/14, uart_tx 17、 ring LUT LOC 制約なし
build.tcl~15Gowin V1.9.12.02_SP2 build script
pc_ring_puf_reader.py~230pyserial + rolling baseline (3 samples) + ring freq est + STEP 1350 verdict subset
README.md~350design + honest scope + verify record

実測結果 (2026-08-27)

Build (Gowin V1.9.12.02_SP2)

Build PASS + Gowin ACCEPTS combinational loop — 398 LUT/ALU (5%) + 180 FF (3%) + 222 CLS (6%)、 bitstream 2,070,608 bytes、 syn_keep = "true" attribute で combinational feedback loop を Gowin GowinSynthesis が accept、 errors 0、 warnings TA1132 x2 (clk_27m + ring[0] SDC 未 create、 cosmetic)。 STEP 1415 (339 LUT / 164 FF) と 近い resource footprint、 +59 LUT (ring chain) + +16 FF (divider chain) の 増加。

SRAM Program

初回 FTDI channel stuck — 0.0 sec cost + no User Code (STEP 1411 と同 pattern、 3 例目)。 COM9 が Windows WMI serial list に 未認識、 JTAG channel A は 認識 (0x1100481B) だが Program 実 write せず。
藤本さん USB 抜き差し 3-5 秒 hold 後 再試行 → Program PASS — User Code 0x0000A59D / Status 0x0003F020 (Ready) / Cost 3.51 sec、 Cable FT2CH cable-index 1。 FTDI channel A (JTAG) + Channel B (VCP COM) 双方 復帰。

PC 側実測 15 秒 (pc_ring_puf_reader.py --port COM9 --duration 15)

[  1] sec=0x3F  ref=27000000  div=   164  ring~=10.75 MHz  collecting baseline  drift=     ---
[  2] sec=0x40  ref=27000000  div=   164  ring~=10.75 MHz  collecting baseline  drift=     ---
[  3] sec=0x41  ref=27000000  div=   165  ring~=10.81 MHz  base=   164.3  drift=     ---
[  4] sec=0x42  ref=27000000  div=   164  ring~=10.75 MHz  base=   164.3  drift= -2028.4 ppm
[  5] sec=0x43  ref=27000000  div=   164  ring~=10.75 MHz  base=   164.3  drift= -2028.4 ppm
...
[ 16] sec=0x4E  ref=27000000  div=   164  ring~=10.75 MHz  base=   164.3  drift= -2028.4 ppm

total packets    : 16
parsed packets   : 16
malformed        : 0
baseline (DIV)   : 164.3  (3 samples)
baseline ring freq: ~10.770 MHz (est. DIV × 65536)
DIV min/max/mean : 164 / 165 / 164.2
drift ppm range  : [-2028.4, +4056.8]  span=6085.2
verdict          : NEITHER
  reason         : drift span 6085.2 ppm exceeds ±5000 ppm tolerance

解釈: Ring oscillator は 正常動作

★ 核心 finding: verdict NEITHER が 「不確実性」 を 正しく検出

Verdict NEITHER の 正しい 意味:

改善 path (defer)

5-step spike template mapping

Step内容状態
1STEP claim 1427 (claim-step.ts) + Ring oscillator 設計 (syn_keep verify)
2benchtop-mcp mock (defer — real hardware 直接動作で mock 不要、 STEP 1415 pattern 継承)⏸ defer
3ring_puf_top.v + Gowin build PASS (398 LUT)
4SRAM Program (0x0000A59D、 USB 挿し直し 経由) + 実測 verify (16 packets、 verdict NEITHER = quantization detected)
5README + memory + Inbox pattern 経由 hook + site 反映 (本 page)

Honest scope (7 条)

1. Ring oscillator = Gowin accept 済syn_keep = "true" attribute で combinational loop reject 回避 verify。 GW1NR-9C 上 LUT-based ring oscillator 実現可能性 evidence
2. "PUF" 主張は controllable — 単一 ring は 1 dimension per-die signature、 challenge-response 型 cryptographic PUF ではない。 名前は 教育的/概念的、 crypto 用途 保証なし
3. 1 board のみ実測 — per-die variance の 実測は 別 board 必要、 現状 evidence は 「1 die 上の 10.77 MHz 実測」 のみ
4. Quantization noise > drift signal — 現 設計 で drift span 6085 ppm は 分解能不足の帰結、 temperature-induced drift detection には 改善 path 実装必要
5. Novelty ゼロ — FPGA ring oscillator は 電子工作/PUF 研究 の 定番 primitive、 「初」 主張なし
6. Placement uncontrolled — LUT chain の 物理位置 uncontrolled、 rebuild ごとに frequency 変動可能、 per-die identity 議論には 固定 LOC 制約必要
7. Ripple divider = non-standard clock use — Gowin warning TA1132 で ring[0] を clock として 検出、 dedicated clock network 経由でない async design、 実動作 verify 済だが 商用設計 非推奨

Rei stack alignment

Reproducing

# 1. Build
cd C:/Users/user/rei-aios/hardware/phase-c/11-tang-nano-9k-ring-puf-spike
"/c/Gowin/Gowin_V1.9.12.02_SP2_x64/IDE/bin/gw_sh.exe" build.tcl

# 2. Program (SRAM, flash 保護、 FTDI stuck 時は USB 抜き差し)
"/c/Gowin/Gowin_V1.9.12.02_SP2_x64/Programmer/bin/programmer_cli.exe" \
  --cable "Gowin USB Cable(FT2CH)" --cable-index 1 \
  --device GW1NR-9C --operation_index 2 \
  --fsFile impl/pnr/ring_puf_top.fs

# 3. PC verify (COM9 auto-bound VCP)
python pc_ring_puf_reader.py --port COM9 --duration 15 --baseline-samples 3

Related