feat(hw): inter-card connector pinout + KiCad footprint + SV port stub for POPC_16A#11
Merged
marcos-mendez merged 4 commits intoMay 6, 2026
Conversation
…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).
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 (
|
| # | 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).
6 tasks
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>
5 tasks
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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).
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:
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
Test plan
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).