Template #2 — 非接触端子 (inductive coil-pair)

STEP: 1578 / Date: 2026-08-30 / Test: 69/69 PASS / Type: chat-Claude 電波時計 arc 「非接触結合の実機実験」 提案の spec 化 + HDL 生成器 cross-verify

非接触デジタル通信 の 最小 skeleton。 GPIO → 数百Ω抵抗 → エナメル線コイル → 空間 数 cm → 同じコイル → 分圧 → FPGA 入力、 の chat-Claude 提案回路を spec 化。 100 kHz Manchester carrier 前提 (40/60 kHz JJY 電波時計 干渉 回避)。

STEP 1570 spec schema の 汎用性 validation 第 2 データポイント — encoding/clock/power/physical 4 軸 全て radio-clock と非重複、 5 軸 schema が 「異なる design point を 同じ枠で表現できる」 evidence。

STEP 1574 HDL 生成器 が 無改変で 新 template を処理 — Verilog + .cst + testbench を そのまま emit。 generateArtifacts() 汎用性が 実証された。

Chat-Claude arc からの引用

「非接触結合の実機実験:GPIO→数百Ωの抵抗→エナメル線を数十回巻いたコイル、受信側も同じコイル→分圧してFPGA入力。数cmは届きます。前回話した「非接触端子」の最小実験がこれです。」
「周波数は 40/60kHz を避けて 100kHz 以上にしてください(本物の電波時計への干渉回避)。」

Design point delta (vs Template #0 radio-clock-jjy)

radio-clock-jjyinductive-coil-pair
roles5 全て (受信/復号/自走/調停/出力)3 (受信/復号/出力) — 調停/自走 不要
linessingle × 1 (+GND)single × 1 (envelope 後)
encodingpulse-width (JJY)manchester (self-clocking)
clockself-plus-syncembedded
powernoneinductive-coupling
physicalpmodcoil-pair
frame60 秒 × 1 bps + minute marker + even parity32 bit (sync 8 + payload 16 + CRC-8 8)
throughput target1 bps50 kbps (100 kHz Manchester)
drift 許容≤ 100 ppm (自走前提)≤ 1000 ppm (embedded clock で 復元)
estimated LUT800 (Nano 9K 9%)500 (Nano 9K 5.8%) — TX/RX 各側

Chat-Claude 実機実験 recipe (spec の honest note より)

⚠ 電波法 注意: 送信出力を増幅すると 微弱電波規制 (総務省告示) を 超えて 抵触 risk 発生。 数 mW 以下 + microA 級 の GPIO 直結 experiment に留めれば無縁だが、 amp 追加時は 事前確認必要。 40/60 kHz 帯を避けるのは、 干渉ではなく 本物の JJY 時計を狂わせないため。

ConnectorSpec (id: inductive-coil-pair)

{
  id: 'inductive-coil-pair',
  name: '非接触端子 (inductive coil-pair, 100kHz Manchester)',
  roles: ['receiver', 'decoder', 'output'],  // arbiter/oscillator 不要
  lines: { kind: 'single', count: 1 },
  encoding: 'manchester',
  clock: 'embedded',
  power: 'inductive-coupling',
  physical: 'coil-pair',
  frame: {
    lengthDescription: '32 bit (sync 8 + payload 16 + CRC-8 8)、 preamble で bit sync 確立',
    syncMarker: true,
    parity: 'crc',
  },
  verification: {
    maxThroughputBps: 50_000,
    allowedErrorRate: 0.01,
    driftPpmTolerance: 1000,  // Manchester 復元で緩い
  },
  target: {
    estimatedLUT: 500,        // TX / RX 各側
    clockDomains: 2,          // TX carrier + RX sample
    boards: ['tang-nano-9k'],
  },
}

HDL 生成例 (STEP 1574 generator 無改変)

1. Verilog (connector_inductive_coil_pair.v)

// ═══════════════════════════════════════════════════════════════
// connector_inductive_coil_pair.v — auto-generated skeleton (STEP 1574 HDL generator)
// Spec: 非接触端子 (inductive coil-pair, 100kHz Manchester) (id=inductive-coil-pair)
// Roles: receiver, decoder, output
// Encoding=manchester / Clock=embedded / Power=inductive-coupling
// ───────────────────────────────────────────────────────────────
// This is a STRUCTURAL SKELETON, not a complete implementation.
// Every layer sub-module contains a TODO marker; the defaults are
// synthesizable pass-throughs so the top compiles as-is.
// Actual protocol logic must be filled in by hand or Phase C spike.
// ═══════════════════════════════════════════════════════════════

`timescale 1ns / 1ps

module connector_inductive_coil_pair (
  input  wire        clk,
  input  wire        rst_n,
  input  wire        rx_line_0,
  output wire        frame_valid,
  output wire        parity_ok,
  output wire [63:0] decoded_frame,
  output wire        output_pulse
);
// ── receiver layer ─────────────────────────────────────────────
// TODO(receiver): implement physical signal capture per spec.encoding=manchester.
// For manchester: detect transitions at bit boundaries, recover clock from mid-bit edge.
// This stub wires raw_bit to a default source for downstream wiring only.
wire raw_bit;
wire raw_valid;
assign raw_bit   = rx_line_0;
assign raw_valid = 1'b1;

// ── decoder layer ──────────────────────────────────────────────
// TODO(decoder): implement manchester → frame parser.
// Frame: 32 bit (sync 8 + payload 16 + CRC-8 8)、 preamble で bit sync 確立
// Sync marker: true
// Parity: crc
// This stub emits zero frame + parity_ok=1 as pass-through default.
reg [63:0] decoded_frame_r = 64'h0;
reg        frame_valid_r   = 1'b0;
reg        parity_ok_r     = 1'b1;
assign decoded_frame = decoded_frame_r;
assign frame_valid   = frame_valid_r;
assign parity_ok     = parity_ok_r;

// ── output layer ───────────────────────────────────────────────
// TODO(output): implement downstream driver. For step-motor: 1 pulse per second.
// This stub drives output_pulse from an available source depending on which
// upstream layers exist (oscillator → local_tick, else decoder → frame_valid, else 0).
assign output_pulse = frame_valid;

endmodule

2. .cst (Tang Nano 9K profile)

// ═══════════════════════════════════════════════════════════════
// Gowin .cst pin constraint skeleton (STEP 1574 HDL generator)
// Spec: 非接触端子 (inductive coil-pair, 100kHz Manchester) (id=inductive-coil-pair)
// Board profile: tang-nano-9k
// Default IO_TYPE: LVCMOS33
// Assumed clk: 27 MHz (create_clock -period 37.037 ns)
// ═══════════════════════════════════════════════════════════════
IO_LOC "clk" 52;
IO_PORT "clk" IO_TYPE=LVCMOS33;
IO_LOC "rst_n" 4;
IO_PORT "rst_n" IO_TYPE=LVCMOS33;
IO_LOC "rx_line_0" 25;
IO_PORT "rx_line_0" IO_TYPE=LVCMOS33;
IO_LOC "frame_valid" __PIN_TBD__;
IO_PORT "frame_valid" IO_TYPE=LVCMOS33;
IO_LOC "parity_ok" __PIN_TBD__;
IO_PORT "parity_ok" IO_TYPE=LVCMOS33;
IO_LOC "decoded_frame" __PIN_TBD__;
IO_PORT "decoded_frame" IO_TYPE=LVCMOS33;
IO_LOC "output_pulse" 10;
IO_PORT "output_pulse" IO_TYPE=LVCMOS33;

3. Testbench (connector_inductive_coil_pair_tb.v)

// ═══════════════════════════════════════════════════════════════
// connector_inductive_coil_pair_tb.v — auto-generated testbench skeleton (STEP 1574)
// Does NOT verify protocol correctness — that is Phase C spike work.
// ═══════════════════════════════════════════════════════════════

`timescale 1ns / 1ps

module connector_inductive_coil_pair_tb;
  reg clk   = 1'b0;
  reg rst_n = 1'b0;
  reg rx_line_0 = 1'b0;
  wire        frame_valid;
  wire        parity_ok;
  wire [63:0] decoded_frame;
  wire        output_pulse;

  always #(18.519) clk = ~clk;

  connector_inductive_coil_pair dut (
    .clk(clk), .rst_n(rst_n),
    .rx_line_0(rx_line_0),
    .frame_valid(frame_valid), .parity_ok(parity_ok), .decoded_frame(decoded_frame),
    .output_pulse(output_pulse)
  );

  initial begin
    #(370.370) rst_n = 1'b1;
    #(3703.704) rx_line_0 = 1'b1;
    #(3703.704) rx_line_0 = 1'b0;
    #(37037.037) $finish;
  end

  initial begin
    $dumpfile("connector_inductive_coil_pair_tb.vcd");
    $dumpvars(0, connector_inductive_coil_pair_tb);
  end
endmodule

Honest scope

V0.2+ candidate (defer)

Files