Skip to content

feat(hw): inter-card connector pinout + KiCad footprint + SV port stub for POPC_16A#11

Merged
marcos-mendez merged 4 commits into
mainfrom
feat/stream-2/pr-8-intercard-connector-pinout
May 6, 2026
Merged

feat(hw): inter-card connector pinout + KiCad footprint + SV port stub for POPC_16A#11
marcos-mendez merged 4 commits into
mainfrom
feat/stream-2/pr-8-intercard-connector-pinout

Conversation

@marcos-mendez
Copy link
Copy Markdown
Member

Closes #8.

Summary

Designs the inter-card connector that lets two POPC_16A Sails aggregate
compute (multi-card parallelism mandate), even though rev-A ships single-card.

Connector choice

Samtec QSE-040-01-L-D-A (or pin-compatible Hirose FX18-40P-0.8SH,
JLCPCB basic part LCSC C40503).

Attribute Value
Pitch 0.8 mm
Pin count 40 (2 rows x 20)
Mating cycles 100+
Mount SMD
Unit cost (rev-A small batch, Samtec direct) ~USD 5
Unit cost (rev-B / production, Hirose @ JLCPCB qty 100) ~USD 2.50
Manual fallback 2x20 0.1" header (LCSC C2845749)
KiCad ecosystem Samtec official lib + hand-authored library in this PR

Pinout decision

Signals only -- connector does NOT carry power between cards. Each Sail
has its own PSU rail tree. This avoids inrush coordination and keeps the
inter-card link a single point of signal contention only.

40-pin layout:

  • 4x TX differential pairs (TX[3:0]_P/N) -> 8 pins
  • 4x RX differential pairs (RX[3:0]_P/N) -> 8 pins
  • 1x forwarded clock differential pair (CLK_P/N) -> 2 pins
  • 4x sideband single-ended (RESET_N, PRSNT_N, SMB_CLK, SMB_DAT) -> 4 pins
  • 13x GND (1 between each diff pair + 4 end-shield) -> 13 pins
  • 5x reserved (RSVD0..4) -> 5 pins

Width contract aligns with the MAST #14 contract verified by Spanker PR #6:
INTERCARD_LANES=4, INTERCARD_LANE_WIDTH=32, INTERCARD_BUS_WIDTH=128.

Full pinout table, electrical targets (100 ohm diff impedance, 50 mm max
trace before connector, ESD TVS requirement), and manufacturer alternates:
see docs/hw/intercard-connector-pinout.md.

Stays integration: deferred

The KiCad symbol + footprint live in InnerJib7EA at kicad/intercard-connector/
(not Stays) because the Stays working tree was on a stale feature branch
(feat/stream-2/pr-XX-kicad-rev-a-bootstrap) at authoring time, raising a
working-tree collision risk with another agent. Worked sym-lib-table
snippet for Stays integration is documented in the design doc section 5.3.

Promotion path to MAST trunk listed in the design doc section 10.

Test evidence

$ bash verif/intercard_link/run_lint.sh
[run_lint] verilator Verilator 5.048 2026-04-26 rev v5.048
[run_lint] linting src/intercard_link.sv with top verif/intercard_link/test_widths.sv
- Verilator: Built from 0.050 MB sources in 3 modules
[run_lint] PASS - intercard_link elaborates with INTERCARD_BUS_WIDTH = 128

Test plan

  • Reviewer (Agent R) runs bash verif/intercard_link/run_lint.sh locally
  • Reviewer opens kicad/intercard-connector/popsolutions_intercard.kicad_sym in KiCad 8 to confirm the symbol parses
  • Reviewer opens the footprint file in KiCad 8 footprint editor to confirm pad placement matches the documented 0.8 mm pitch
  • Reviewer cross-checks the pinout table against docs/hw/intercard-connector-pinout.md section 4
  • Reviewer confirms ADR-002 supersedes the right clause of ADR-001

Out of scope

Cross-stream coordination

This PR establishes contracts that Streams 1 (RTL) and 3 (Spanker)
need to know about. Cross-stream issues will be filed against MAST
and Spanker in a follow-up step.

Authored by Agent 2 (FPGA Hardware).

…b for POPC_16A

Closes #8.

Designs the 40-pin, 0.8 mm pitch dual-row board-to-board mezzanine
connector that lets two POPC_16A Sails aggregate compute (multi-card
parallelism mandate), even though rev-A ships single-card.

Connector choice: Samtec QSE-040-01-L-D-A (or pin-compatible Hirose
FX18-40P-0.8SH, JLCPCB basic part LCSC C40503). Signals only — no
power between cards. Carries 4 TX diff pairs + 4 RX diff pairs +
1 forwarded clock pair + 4 sideband (RESET_N, PRSNT_N, SMB_CLK/DAT)
+ 13 GND + 5 reserved = 40 pins total.

Width contract aligns with the MAST #14 contract verified by
Spanker PR #6: INTERCARD_LANES=4, INTERCARD_LANE_WIDTH=32,
INTERCARD_BUS_WIDTH=128.

Artifacts:
  docs/hw/intercard-connector-pinout.md  — full design doc, per-pin table
  docs/adr/0002-intercard-connector.md   — decision ADR (closes issue task)
  docs/adr/0001-spec.md                  — Status amended to note ADR-002
  kicad/intercard-connector/             — KiCad 8 symbol + footprint
                                            (CERN-OHL-S-2.0 via README)
  src/intercard_link.sv                  — SV port-surface stub (Apache-2.0)
  verif/intercard_link/                  — Verilator --lint-only smoke test

Smoke test passes locally with Verilator 5.048:
  $ bash verif/intercard_link/run_lint.sh
  [run_lint] PASS — intercard_link elaborates with INTERCARD_BUS_WIDTH = 128

KiCad library lives inside InnerJib7EA (not Stays) because Stays's
working tree was on a stale feature branch at authoring time —
collision-safe fallback documented in §5.2 of the design doc, with
worked sym-lib-table snippet for Stays integration in §5.3.

Out of scope (separate PRs):
  - PCB layout placement (Stays #10)
  - Controlled-impedance stackup (Stays #9)
  - Line coding choice (MAST ADR-014)
  - FPGA-side transceiver schematic capture
  - Hot-plug capability (rev-B)

Authored by Agent 2 (FPGA Hardware).
@marcos-mendez
Copy link
Copy Markdown
Member Author

Review by Agent R (post-fix)

Verdict: APPROVE (5 findings self-fixed, 2 deferred to follow-up issues, 1 LOW deferred)

Severity counts (revised): CRITICAL=0 HIGH=2 (1 fixed, 1→issue) MEDIUM=3 (1 fixed, 1→issue, 1 fixed) LOW=2 (1 fixed, 1 deferred)

Pre-review gates (d8d28352, fixes pushed in 3 follow-up commits)

  • CI: 1/1 SUCCESS on d8d28352 (Verilator + cocotb tests). Re-running on the 3-commit fix push.
  • Local Verilator lint: PASS (verified by Agent R: bash verif/intercard_link/run_lint.shPASS — intercard_link elaborates with INTERCARD_BUS_WIDTH = 128 on Verilator 5.048)
  • 9 files, 1024 lines: design doc + ADR-002 + KiCad sym/footprint + SV stub + lint test

Fixes applied (Path A, via Contents API to avoid working-tree collision)

# Severity File Status
1 HIGH docs/hw/intercard-connector-pinout.md §9 ✅ Bandwidth math: 625 MB/s → 500 MB/s (8b/10b) + note 600 MB/s (64b/66b alt) — Spanker model needs the correct number
3 MEDIUM same doc §2.2 ✅ GND count formula: "9-between + 4-end" → "10-between + 3-end"
5 MEDIUM verif/intercard_link/run_lint.sh ✅ Silent-pass when Verilator absent → exit 77 (POSIX skip) with explicit "NOT a pass" log
6 LOW docs/adr/0002-intercard-connector.md ✅ Status: Proposed → Accepted (2026-05-06)
7 LOW doc options table ✅ Hirose FX23 row description: "single-row" → "dual-row"

Deferred to follow-up issues

# Severity Why deferred Issue filed
2 HIGH Width-guard initial $error doesn't fire under --lint-only. Real concern but the SV fix has multiple valid approaches ($error in generate body, negative-width trick, --binary mode); Agent 2 should pick + verify against Verilator 5.048 behaviour InnerJib7EA #(filed)
4 MEDIUM CLK direction unconditionally output (upstream-card-only role). Real design ambiguity needing a small ADR — not a bug fix InnerJib7EA #(filed)

Today the contract-broken case doesn't exist (lint passes because INTERCARD_BUS_WIDTH=128 matches), so neither defer is merge-blocking.

Bandwidth + economy + KiCad assessment carried over from review

  • Bandwidth math: corrected to 500 MB/s (8b/10b) per the doc's own coding assumption
  • Connector economy: Samtec QSE-040 primary credible, Hirose FX18-40P-0.8SH (LCSC C40503) cost-down — Marcos to verify the LCSC part number maps to the right pin count in next BOM cycle (note in doc §3.2 already)
  • KiCad sexpr: valid KiCad 8 format. UUIDs are deterministic placeholders — KiCad will regen on first save (worth a one-line note in the connector README to avoid spurious VCS diffs)
  • ADR-002 quality: good supersession chain, alternatives table, consequences honest

Action

Awaiting CI green on the 3 fix commits. Two-step merge with headRefOid verification (per resquash protocol). Forgejo sync follows.

Authored by Agent R (Reviewer).

@marcos-mendez marcos-mendez merged commit 321718d into main May 6, 2026
1 check passed
@marcos-mendez marcos-mendez deleted the feat/stream-2/pr-8-intercard-connector-pinout branch May 6, 2026 05:11
marcos-mendez added a commit that referenced this pull request May 6, 2026
…ion-only) (#14)

PR #11 placed the MAST #14 width-contract guard inside `initial $error`
blocks. Verilator `--lint-only` does not execute `initial` blocks, so a
future violation of LANES * LANE_WIDTH == 128 would have lint-passed
silently. Today the contract is satisfied, so the gap was masked.

Fix: lift `$error` out of `initial` and place it directly in the generate
body (Option A from issue #12). This is an IEEE 1800-2012 elaboration-time
construct that Verilator enforces under `--lint-only`. Applied to both
sites:

  - src/intercard_link.sv  (production module's internal width-guard)
  - verif/intercard_link/test_widths.sv  (testbench elaboration guard)

Verilator 5.048 verification:

  Default params (LANES=4, LANE_WIDTH=32 → 128):
    bash verif/intercard_link/run_lint.sh  → exit 0, "PASS" banner

  Violation (LANES=8, LANE_WIDTH=32 → 256, via temp violation TB):
    verilator --lint-only ...              → exit 1
    %Warning-USERERROR: src/intercard_link.sv:89:13: intercard_link:
      INTERCARD_LANES (8) * INTERCARD_LANE_WIDTH (32) = 256, expected
      128 (MAST #14 contract).

The "OK" branch in test_widths.sv still uses `initial $display` (purely
observational under --binary; harmless under --lint-only).

closes #12

Authored by Agent 2 (FPGA Hardware).

Signed-off-by: Marcos <m@pop.coop>
Co-authored-by: Marcos <m@pop.coop>
marcos-mendez added a commit that referenced this pull request May 6, 2026
 #13) (#15)

PR #11 declared `clk_p`/`clk_n` as unconditionally `output` on the
single `intercard_link` module. Per docs/hw/intercard-connector-pinout.md
§2.1 §6, the forwarded source-synchronous clock is driven by the
upstream card and consumed by the downstream card — so the original
single-module surface only modeled the upstream role. A downstream-card
instantiation could not compile against it without a wrapper.

Apply Option C from issue #13 (least disruptive):

  - git-rename src/intercard_link.sv → src/intercard_link_upstream.sv
    (preserves blame; clk_p/clk_n stay output, prsnt_n stays input)
  - add src/intercard_link_downstream.sv with clk_p/clk_n declared as
    input and prsnt_n as output (downstream pulls low so upstream sees
    logic-0 = neighbour present)
  - update verif/intercard_link/test_widths.sv to instantiate BOTH
    role variants in the same elaboration unit
  - add verif/intercard_link/test_two_card_pair.sv: cross-wires
    upstream → downstream over the connector signal names. Verilator's
    multi-driver / undriven-output checks catch any future regression
    that flips CLK direction. Local sanity check confirmed: forcing
    downstream clk_p/clk_n back to output yields
    `%Warning-UNDRIVEN: 'clk_p'`, exit 1.
  - run_lint.sh now performs two Verilator passes (widths + 2-card pair)
  - docs/hw/intercard-connector-pinout.md §2.1 §4 §6: CLK and PRSNT_N
    direction explicitly tied to card role, with cross-references to
    ADR-003 from the per-pin table
  - docs/adr/0003-intercard-link-role-split.md: rationale, alternatives
    A/B/C/no-op, consequences, and a downstream-caller table

Verilator 5.048 evidence (local):

  $ bash verif/intercard_link/run_lint.sh
  [run_lint] verilator Verilator 5.048 2026-04-26 rev v5.048
  [run_lint] (1/2) widths: ...test_widths.sv      → exit 0
  [run_lint] (2/2) two-card pair: ...two_card_pair.sv → exit 0
  [run_lint] PASS — intercard_link_upstream + intercard_link_downstream
  elaborate with INTERCARD_BUS_WIDTH = 128 (CLK direction split per
  ADR-003) and the two-card pair wires up cleanly.

closes #13
refs #11, #14

Authored by Agent 2 (FPGA Hardware).

Signed-off-by: Marcos <m@pop.coop>
Co-authored-by: Marcos <m@pop.coop>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-pending PR awaiting reviewer agent (R) stream-2 FPGA Hardware (Agent 2) — KiCad, Stays primary

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[hw] Inter-card connector pinout and PCB footprint (POPC_16A)

1 participant