Micro-HAPS is a Synopsys-developed test board for at-speed (high-speed I/O) testing, based on a Xilinx Kintex UltraScale+ KU5P FPGA. This project covers E-Sharp's test development work on/with the board.
- Primary domain: test (at-speed test development)
- Secondary domain: electronics (KU5P FPGA-based board)
- Vendor: Synopsys (SNPS); HW designer Martin Wang
- PCBA: SH100008193-R0.0 (PCB SH100008192-R0.0 "KU5P_Generic_Tester"); 49×67 mm, 18-layer, impedance-controlled @1 GHz. Main device: XCKU5P-1 FFVB676; host control via FTDI FT4232H.
- ⚠ Design docs (schematic/BOM/spec) are SYNOPSYS CONFIDENTIAL; the customer BOM is not imported into the Trace component library (see decisions).
- Repository: https://github.com/esharpab/testdevelopment-snps-microhaps
Milestones
No milestones defined.
Items (56)
| Code | Status | Severity | Kind | Title | Date |
|---|---|---|---|---|---|
| E-045 | open | blocking | issue | R0 I2C: Si5340 (CLKA) FET level-translator Q22/Q23 wired backwards — main 3V3 bus clamped via Si5340 1.8V ESD | 2026-06-07 |
| E-007 | open | warning | notice | microHAPS cleanup/final revision in progress — RC schematic to be shared for E# review | 2026-06-04 |
| E-008 | open | warning | notice | Open questions: firmware/RTL ownership, FTDI-vs-header control, host PC vs Raspberry Pi | 2026-06-04 |
| E-009 | open | warning | notice | ACTION: define formal engagement mechanism; SNPS to provide DUT timeline needs | 2026-06-04 |
| E-016 | open | warning | notice | INCOMING MicroHAPS R1.0: big black switch removed, Service Port in AWO domain, automated 12V | 2026-06-04 |
| E-038 | open | warning | concept | JTAG signal chain (FT4232 service port → KU5P) — open-drain TDO buffer (U9, 1.8V VCC + 10K pull-up to 3.3V) is the speed limiter; shared by FTDI & XJTAG | 2026-06-06 |
| E-039 | open | warning | notice | ACTION: Physically verify C10–C13 mount status on real R0 board (PDF says NM, ODB++ says populated 10nF) | 2026-06-06 |
| E-043 | open | warning | notice | R0 I2C: FPGA↔mgmt-bus bridge is repeater U5, jumper-gated by J3 — NM in R0 build | 2026-06-07 |
| E-044 | open | warning | notice | R0 I2C: management bus runs unbuffered on a single FTDI-segment 1k pull-up to P3V3_G | 2026-06-07 |
| E-049 | open | warning | issue | R0 BOM↔schematic mismatch: U56 buffer & R558/R559 bypass populate/DNI are SWAPPED (board built unbuffered, contrary to schematic) | 2026-06-07 |
| E-053 | open | warning | notice | DESIGN FLAW: two TCA9803 static-offset buffers (U56 + U5) drive the same I2C segment with no enable orchestration — buffers latch / V_OL stacks; bites in R1 (U60+U5 both fitted) | 2026-06-11 |
| E-001 | open | info | notice | Micro-HAPS board context: Synopsys at-speed test board, Xilinx KU5P FPGA | 2026-06-04 |
| E-002 | open | info | decision | Engagement scope: E# to deliver turn-key microHAPS production test fixtures; SNPS buys turnkey | 2026-06-04 |
| E-003 | open | info | decision | Control interface: HCI (Host Controller Interface) over full UART via FTDI | 2026-06-04 |
| E-004 | open | info | decision | Mechanics: keep open-frame ATX enclosure; custom top plate per DUT | 2026-06-04 |
| E-005 | open | info | decision | Hardware rollout: Rev0 microHAPS to E# to start; target Rev1 for formal deployments | 2026-06-04 |
| E-006 | open | info | notice | microHAPS board architecture & control (per Dave Upton) | 2026-06-04 |
| E-010 | open | info | notice | microHAPS PCBA fabrication spec (PCB SH100008192 / PCBA SH100008193) | 2026-06-04 |
| E-011 | open | info | notice | microHAPS PCBA functional architecture (from schematic/BOM) | 2026-06-04 |
| E-012 | open | info | decision | microHAPS BOM intentionally NOT imported into PLEASE component library (customer IP) | 2026-06-04 |
| E-013 | open | info | notice | MicroHAPS R0.0 HW verification — HCI FPGA designs & at-speed SSTDM results (Erik Ingemarsson) | 2026-06-04 |
| E-014 | open | info | notice | MicroHAPS adapter cards (3) & NVAM loopback cables | 2026-06-04 |
| E-015 | open | info | notice | MicroHAPS R0.0 bring-up / power-up procedure | 2026-06-04 |
| E-017 | open | info | notice | MicroHAPS host setup & toolchain (NI MAX Service Port, Python/Tcl/Vivado Lab) | 2026-06-04 |
| E-018 | open | info | notice | MicroHAPS resource locations — SharePoint, Empower, Perforce verification stream | 2026-06-04 |
| E-019 | open | info | notice | OpenOCD / XVC server config for FT4232H JTAG (xvc_server.cfg) | 2026-06-05 |
| E-020 | open | info | concept | TODO: Build a native Accordion extension for MicroHAPS (drop the Synopsys vivado/hci/synplex dependency) | 2026-06-05 |
| E-021 | open | info | notice | MicroHapsHandler extension scaffolded in accordionq2 | 2026-06-05 |
| E-022 | open | info | notice | MicroHapsHandler: transport migrated + MPSSE I2C implemented — builds green | 2026-06-05 |
| E-023 | open | info | notice | FTD2XX native loader made cross-platform (linux-arm64 blocker resolved) | 2026-06-05 |
| E-024 | open | info | notice | MicroHapsHandler: native libftd2xx scaffolded (RID-driven); host arch still open | 2026-06-05 |
| E-025 | open | info | decision | MicroHAPS Accordion host = Raspberry Pi (linux-arm64) | 2026-06-05 |
| E-026 | open | info | notice | FT4232H: A/B/C/D are independent interfaces; only A/B have MPSSE | 2026-06-05 |
| E-027 | open | info | notice | MicroHapsHandler: HCI port (FTDI C) wired via Synopsys.HciBus — builds green | 2026-06-05 |
| E-028 | open | info | notice | MicroHAPS R0 Service Port (FT4232H) identity & interface map (from Pi by-id) | 2026-06-05 |
| E-030 | open | info | notice | Non-root USB/D2XX access confirmed on agent64 — no sudo / udev rule needed | 2026-06-05 |
| E-031 | open | info | notice | MicroHapsHandler: Port A (XVC/JTAG) + Port D (GPIO) implemented — all 4 drivers done, builds green | 2026-06-05 |
| E-032 | open | info | notice | MicroHaps implemented as an Accordion Module (channels + IBusHandler I2C); registered + builds | 2026-06-05 |
| E-033 | open | info | notice | HCI: cloned the HciHandler module into the extension, retargeted UART to FTDI Port C | 2026-06-05 |
| E-034 | open | info | notice | MicroHAPS host bring-up working: I2C + power + JTAG IDCODE read on agent64 | 2026-06-05 |
| E-035 | open | info | issue | openFPGALoader doesn't drive the JTAG buffer enable (ADBUS5) — fixed in R1 (BDBUS4); R0 uses slow XVC | 2026-06-05 |
| E-037 | open | info | notice | Host bring-up status: ftdi_sio detach + openFPGALoader path done; HCI link verification is next | 2026-06-06 |
| E-040 | open | info | concept | HCI Bus Specification (HCIBus) — reference for the microHAPS control protocol (UART/byte-wide; commands, device classes, registers) | 2026-06-06 |
| E-041 | open | info | notice | HCI bring-up SOLVED on R0.0 — interface D, 8-O-1, RTS/CTS; full chain enumerates | 2026-06-06 |
| E-042 | open | info | notice | I2C subsystem schematic walkthrough — R0 (pull-ups, domains, SCL/SDA, addresses) | 2026-06-07 |
| E-046 | open | info | concept | I2C Bus B (MUX_I2C) — PCA9547 U47 fan-out diagram | 2026-06-07 |
| E-047 | open | info | notice | R0 I2C buffer/translator pull-up audit — both sides & rail voltage | 2026-06-07 |
| E-054 | open | info | notice | ODB++ shows U5 (TCA9803) POPULATED with its B-side ports (pins 6/7 = SDAB/SCLB) on I2C_SDA0 / I2C_SCL0 alongside U56 — two static-offset I2… | 2026-06-14 |
| E-055 | open | info | notice | [net:JTAG_TDO_3V3] Probe's connectivity review independently corroborates E-038 (open-drain TDO buffer = JTAG-speed limiter). On JTAG_TDO_3… | 2026-06-14 |
| E-056 | open | info | notice | [component:U1] Micro-HAPS R0 — Probe review triage of the WARNING-severity findings (the 2 errors are disposed separately: CON-001 = I2C bu… | 2026-06-14 |
| E-048 | closed | blocking | issue | R0 BLOCKING: FTDI service port cannot control the LTC2980 power manager — bus V_OL (0.4V) exceeds LTC2980 V_IL | 2026-06-07 |
| E-052 | closed | blocking | issue | BLOCKING: LTC2980 (0x5C/0x64) ACK address but NACK every command (incl. STATUS_BYTE) after U56 rework — buffered-segment integrity issue, not config | 2026-06-11 |
| E-036 | closed | warning | notice | Install/boot requirement: detach ftdi_sio from the FT4232H so D2XX/openFPGALoader can claim the interfaces | 2026-06-05 |
| E-050 | closed | warning | notice | ACTION (Daniel, ~2026-06-08): fit U56 TCA9803 on R0 + REMOVE R558/R559 + fix EN strap (R557), test LTC2980 | 2026-06-07 |
| E-051 | closed | warning | issue | Host SW: module unload leaked openFPGALoader --xvc process + FT4232H handles — every MicroHAPS reload failed (fixed) | 2026-06-08 |
| E-029 | withdrawn | info | notice | Bring-up console (microhaps-bringup) built — first hardware smoke test (no ftdi_sio setup) | 2026-06-05 |
Requirements
| Code | Status | Category | Title | Statement | Acceptance |
|---|---|---|---|---|---|
| REQ-TS-001 | draft | coverage | Requirement Coverage | This test system shall cover at least 90 % of the verifiable requirements in the linked project under test. | Coverage report generated; ≥ 90 % of linked project requirements are covered by test steps. |
| REQ-TS-002 | draft | metrology | Measurement Uncertainty | All measurements made by this test system shall have a documented measurement uncertainty. Uncertainty shall be ≤ 25 % of the tightest applicable tolerance. | Measurement uncertainty analysis on file; all uncertainties confirmed within limit. |
| REQ-TS-003 | draft | metrology | Calibration Interval | All reference instruments and standards used in this test system shall have a defined calibration interval and shall be within calibration at all times when the system is in use. | Calibration records reviewed; all instruments are current. |
| REQ-TS-004 | draft | quality | Pass/Fail Criteria | Every test step in this test system shall have a documented, unambiguous numeric or boolean pass/fail criterion defined before the first production unit is tested. | All test steps reviewed; each has an explicit pass criterion. |
| REQ-TS-005 | draft | metrology | Repeatability (GR&R) | The test system shall demonstrate acceptable measurement repeatability. Gauge R&R shall be ≤ 30 % of tolerance (≤ 10 % preferred). | GR&R study completed and documented; GR&R within required limit. |
| REQ-TS-006 | draft | quality | Test Limit Derivation Documented | Every test step in this test system shall have its pass/fail limits derived from the documented tolerance stack of all components in the measurement path (references, dividers, resistors, ADCs, drivers, wiring). | For each test step with numeric limits, evidence of derivation exists — `passCriterion` enumerates the relevant components and their tolerances, OR a linked `please_decision` documents the corner math, OR the implementing Maestro YAML carries a `Limit derivation` comment block. |
Test Cases
| Code | Status | Category | Title / Signal | Target | Pass Criterion | Linked REQ |
|---|---|---|---|---|---|---|
| TC-TS-001 | open | coverage | Coverage Audit | — | Generate a coverage report for the linked project; confirm ≥ 90 % of verifiable requirements are covered by test steps in this system. | REQ-TS-001 |
| TC-TS-002 | open | metrology | Measurement Uncertainty Budget | — | Complete a measurement uncertainty analysis for each measurement type; file the analysis and confirm all uncertainties are ≤ 25 % of tolerance. | REQ-TS-002 |
| TC-TS-003 | open | metrology | Calibration Check | — | Review calibration certificates for all instruments in the test system; confirm all are within their calibration interval. | REQ-TS-003 |
| TC-TS-004 | open | quality | Pass/Fail Criteria Review | — | Review all test steps; confirm each has a documented numeric or boolean pass criterion before first production test. | REQ-TS-004 |
| TC-TS-005 | open | metrology | GR&R Study | — | Perform a gauge repeatability and reproducibility study on the test system; verify GR&R ≤ 30 % of tolerance. | REQ-TS-005 |
| TC-TS-006 | open | quality | Limit Derivation Audit | — | For each test step in this fixture, confirm the limits trace to a documented tolerance stack — passCriterion lists components/tolerances OR a linked `please_decision` exists OR the implementing YAML has a `Limit derivation` block. | REQ-TS-006 |
Verification Records
No verification records.
Concepts
Active exploration (4) — ideas still being shaped.
Hypothesis
Build a new Accordion extension for MicroHAPS in E#'s own codebase (C:\dev\source\accordionq2\Extensions) so E# can drive the board entirely from its own toolchain (Accordion / AGENT) with no runtime dependency on Synopsys packages (vivado wrapper, hci, synplex/tif, NI-VISA Service Port). Realises the SOW's "integration with E-Sharp Accordion infrastructure" direction (E-021, project 44) and the AGENT-native-HCI idea (E-003).
Code target: C:\dev\source\accordionq2\Extensions (accordionq2 — separate from this testdevelopment repo).
accordionq2 extension model (from the HciHandler example)
- C# .NET class library, multi-target
net8.0/net10.0,RuntimeIdentifier = linux-arm64(runs on the Raspberry Pi controller in the fixture). - References:
AccordionUno(core runtime,submodules/accordionuno),EsharpDefinitions.NET10(shared interfaces/types,submodules/protocolserver/submodules/esharpdefinitions), plus sibling extensions as needed (HciHandler refsSynopsys.HciBus). - Handlers are built against
EsharpDefinitions.Interfaces:IFileLogging,IBusHandler,IUartDevice,IBusDevice,IHciBus/IHciDevice,IBusTransaction,IJtagTransaction. Pattern: ctor takes framework interfaces and wraps a bus, e.g.HciHandler(IFileLogging, IBusHandler, IUartDevice)→Bus = new ComHandler(...)(anIHciBusover the UART); exposesScan(),SendReceive(), bus-speed negotiation,Reset(),GetDevice().
FTDI port → function mapping (4 sub-drivers)
The FT4232H Service Port = 4 USB interfaces; the extension implements one driver per port:
| FTDI port | Role | Build vs reuse |
|---|---|---|
| A | XVC server / JTAG (MPSSE) — host XVC on TCP :2542 for Vivado (cf. E-019), driving the KU5P TAP | Implement against existing IJtagTransaction; XVC/JTAG module precedent already in AccordionUno (Modules/ESH*.cs) |
| B | I2C driver (MPSSE I2C) — board-management bus: U15 (PMBus), PU8, clkgen, ADC, fan, IDPROM. Buffered: SCL=B0, SDA-out=B1, SDA-in=B2, buffer-enable B4 | New, but mirror Extensions/MCP2221IO (a USB→I2C+GPIO bridge); reuse PmbusEngine for U15/PU8 power-up |
| C | UART → HCI — FPGA runs HCI over this UART | Reuse HciHandler + Synopsys.HciBus directly: feed FT4232H Port C as the IUartDevice. Lowest effort / biggest win (AGENT-native HCI, E-003) |
| D | GPIO0–7 (bit-bang) — 8-bit parallel link to the KU5P (see schema) | New; mirror the GPIO half of MCP2221IO |
Foundational gap: there is currently no FTDI transport in accordionq2 (grep found none). So the one genuinely new building block is an FT4232H transport that supports MPSSE (A=JTAG, B=I2C), bit-bang (D=GPIO), and exposes C as an IUartDevice — candidate libs: FTD2XX.NET / libftd2xx (has linux-arm64 builds) or libftdi/libMPSSE via P/Invoke. Note driver arbitration: one driver per interface (can't share with NI-VISA/D2XX simultaneously).
FTDI Port D GPIO → KU5P Bank 86 (from schematic) + full port map
flowchart LR
EXT["MicroHAPS Extension<br/>(Accordion .NET, linux-arm64)"]
subgraph FT["FT4232H Service Port (USB 2.0)"]
A["Port A · MPSSE → XVC/JTAG"]
B["Port B · MPSSE I2C"]
C["Port C · UART"]
D["Port D · GPIO0-7 (bit-bang)"]
end
EXT --> FT
BRD["Board-mgmt I2C<br/>U15 PMBus · PU8 · clkgen · ADC · fan · IDPROM"]
subgraph U1["XCKU5P-1FFVB676E — Bank 86 (P3V3_VCCO)"]
TAP["JTAG TAP"]
HCIc["HCI core over UART"]
GP["FPGA GPIO (bank 86):<br/>F9 GPIO0 · F10 GPIO1 · G9 GPIO2 · G10 GPIO3<br/>G11 GPIO4 · H11 GPIO5 · H9 GPIO6 · J9 GPIO7"]
end
A -->|"TCK/TDI/TDO/TMS (+ JTAG buf EN A5)"| TAP
B -->|"SCL/SDA + buf EN (B4)"| BRD
C -->|"E10 TXD / E11 RXD"| HCIc
D -->|"8-bit parallel"| GP
(Port D pin map per the bank-86 schematic; same bank also carries FPGA-driven I2C: FPGA_I2C_SCL0/SDA0 on K9/K10 and MUX_I2C on J10/J11, plus MGB/HT3 control IO — those are FPGA-side, driven over HCI, not FTDI.)
Reusable assets (not Synopsys IP)
Service-Port alias CSV, ClkGen / PSM / MPM config files (Perforce Common/Config) — pure data, carry over. HCI command/register semantics for the MicroHAPS design still needed (from Erik / the hci module map).
Open questions (to reason about next)
- FTDI transport choice on linux-arm64 (FTD2XX.NET vs libftdi/MPSSE P/Invoke); does it cover MPSSE+bitbang+UART on one device across 4 interfaces.
- XVC server: implement MPSSE shift in C# vs wrap OpenOCD as a child process (E-019 cfg). Reconcile with the existing
IJtagTransaction/AccordionUno XVC modules. - How the extension obtains the
IUartDevicefor Port C (does Accordion enumerate the FT4232H COM interface?). - HCI command/register map for the MicroHAPS HCI design (GPIO/I2C/SSTDM/edge-counter blocks).
- Rev-awareness R0 vs R1 (manual switch + I2C enable to U15/PU8 vs automated AWO Service Port; E-016 / R1 note).
- SOW boundary: Phase A still owes Snowball/TestStand/Synplex to SNPS (E-021); this extension is E#'s parallel/longer-term path.
Next step
Decide the FTDI transport approach, then scaffold the extension project (MicroHapsHandler.csproj referencing AccordionUno + EsharpDefinitions + Synopsys.HciBus), reusing HciHandler for Port C and the MCP2221IO pattern for the I2C/GPIO drivers.
Hypothesis
microHAPS R0 FTDI service-port JTAG runs cleanly only at 1 MHz and fails ≥6 MHz. Tracing the chain from the ODB++ (ingested as PLEASE netlist R0, id 15): the TDO return path uses an open-drain buffer (U9 SN74AUP1G07) powered at 1.8 V, whose output is pulled up to 3.3 V by R139 (10 K). The open-drain is the 1.8→3.3 V level-shift, and its RC-limited rising edge caps readback at ~1 MHz. Host shifts data out fine (push-pull TCK/TMS/TDI via U8); only the return path is slow → classic "JTAG dies above X MHz". Carried over unchanged into R1 (see project 46).
Cap correction: original "smoking gun" was 10 nF line caps C10–C13. Confirmed NM — R1 BOM marks them "disable". Not the cause. The open-drain TDO buffer is the root cause.
Block schematic — full JTAG path (both directions)
flowchart LR
subgraph HOST["USB host — Vivado hw_server / MPSSE"]
FT["U10 FT4232HL · VCCIO 3.3V"]
end
subgraph D3V3["3.3 V domain (P3V3_G / R1:P3V3_STBY)"]
MUX["U48 SN3257 · 2:1 mux<br/>common ↔ FTDI / XJTAG<br/>sel = XJTAG_SELN"]
XJ["J20 XJTAG header (no VTREF)"]
end
subgraph XLAT["Translate / buffer"]
U8["U8 SN74AXC4T245<br/>VCCB 1.8 / VCCA 3.3 · DIR fixed<br/>✅ fast, correct"]
U9["U9 SN74AUP1G07 · VCC 1.8V<br/>OPEN-DRAIN, out pulled to 3.3V via R139 10K<br/>❌ speed limiter + level-shift"]
end
subgraph D1V8["1.8 V domain — P1V8_VCCO"]
FPGA["U1 XCKU5P · JTAG TAP"]
end
FT -->|"TCK/TMS/TDI"| MUX
XJ -.->|"alt host"| MUX
MUX -->|"*_3V3"| U8
U8 -->|"SFPGA_JTAG_*"| FPGA
FPGA -->|"TDO (1.8V)"| U9
U9 -->|"TDO_3V3 (common, pre-mux)"| MUX
MUX -->|"to FTDI or XJTAG"| FT
classDef bug fill:#ffd6d6,stroke:#cc0000,stroke-width:3px;
class U9 bug;
U9 is on the COMMON TDO node, upstream of the mux → both FTDI and XJTAG suffer the slow rise (XJTAG can be worse: pull-up also charges cable+pod through the passive SN3257).
Root cause RC
- TDO rise charged only through R139 10K: τ ≈ 10K × ~20 pF ≈ 200 ns, edge ≈ ~440 ns.
- TCK budget: 1 MHz=500 ns (just works ✅); 6 MHz=83 ns (fails ❌); 20 MHz=25 ns (hopeless ❌). Matches the knee.
Voltage chain — consistent (verified)
1.8 V FPGA island ↔ 3.3 V host island; U8 translates TCK/TMS/TDI (VCCB 1.8 / VCCA 3.3); U48 + FT4232H VCCIO = 3.3 V. No mismatch. The only subtlety is TDO's 1.8→3.3 shift done via open-drain + 3.3 V pull-up (legal: AUP1G07 out rated 3.6 V).
Fix (corrected)
- ❌ NOT a push-pull single-rail buffer (e.g. AUP1G17): at 1.8 V it can't reach 3.3 V; at 3.3 V it can't read the 1.8 V FPGA TDO (VIH≈2.15 V). Voltage-naive.
- ✅ Dual-supply directional translator for TDO — e.g. SN74AXC1T45 (VCCB 1.8 / VCCA 3.3, DIR B→A), same family as U8, push-pull, 100s of MHz.
- Bench mitigation only: R139 10K→~470 Ω; scope TDO rise at U48/FTDI side.
Per-stage assessment
| Stage | Part | Verdict |
|---|---|---|
| FTDI | U10 FT4232HL (30 MHz capable, VCCIO 3.3) | ✅ not the limit |
| Mux | U48 SN3257 (FTDI/XJTAG, passive pass-FET) | ✅ but passes slow TDO to both hosts |
| Translator | U8 SN74AXC4T245 | ✅ fast, correct |
| TDO buffer | U9 SN74AUP1G07 open-drain, 1.8V VCC, R139 10K→3.3V | ❌ root cause |
| Caps C10–C13 | 10 nF — NM (BOM "disable") | ✅ not populated |
| Series term | 22R R29–R32 | ✅ fine |
Open questions
- Confirm U9 is powered (PQ1/JTAG_FTDI_EN_N) when XJTAG is the active path; J20 has no VTREF.
- Scope TDO rise to confirm ~hundreds of ns.
Next step
- Scope TDO at U48/FTDI side; confirm slow rise.
- R0/R1 rework: replace U9 with SN74AXC1T45-class dual-rail translator (bench: R139→470Ω), re-test 6/12/20 MHz.
- Next spin: same — raise with Synopsys; carried over unchanged into R1 (project 46 concept).
Source: ODB++ → PLEASE netlist R0 (id 15). R1 comparison: project 46 (netlist id 16). Related: [[microhaps-project]], notice E-039.
Reference capture of the Host Controller Interface Bus (HCIBus) Specification — the protocol microHAPS uses to talk to the FPGA. Full converted markdown (faithful, source of truth): docs/hci/HCI_Bus_Specification.md (git-ignored); source DOCX: …/Synopsys/Documentation/HCI/HCI_Bus_Specification.docx. Doc rev 19, 2022-09-15 (authors: Daniel Rhodin, Jonas Nilsson, Ulf Winberg, Rutger Carlsson). This entry is a digest + lookup tables; see the file for full prose, FSM, and timing figures.
Relevance to microHAPS
HCI is the control plane for the KU5P: host → FT4232H service-port UART → HCI bus → FPGA blocks. The R0 bring-up bitfiles map directly onto HCI device classes — GPIO Expander (0x44), Edge Counter (0x46), Clock Generator (0x45), SSTDM (0x48), Transceiver (0x47). The host driver stack (Synopsys.HciBus.dll + Synopsys.FtdiDriver.dll) is what the planned Accordion-native extension (E-020) would replace/reuse. Related: [[microhaps-project]], [[please-platform]].
Overview
Controller ↔ daisy-chained slaves, each with an 8-bit register space (defined by a per-device CSV). Each slave has upstream + downstream full-duplex ports; requests trickle down to the addressed unit, replies trickle up. HW flow control (CTS/RTS) stalls transmitters. A controller must not issue a new request until the previous reply is received.
Physical link
- UART (default link): startup 57'600 baud, 8N1, CTS/RTS flow control. Link reset = BREAK (TX held low > 2 frame times). Baud set via UART Link Controller register
CURRENT_BUS_SPEED(0x00). Speed is negotiated incrementally up the table (can't jump 57k6→3M686 in one step — risks false BREAK). - Byte-wide link: parallel bus between HCI units inside a device (no link controller); two unidirectional links (cmd down / reply up), subset of the application-side bus.
- UMRBus 3.0 / Hydralink: TBD.
Baud-rate bitmap: 0x01=3'686'400, 0x02=1'843'200, 0x04=921'600, 0x08=460'800, 0x10=230'400, 0x20=115'200, 0x40=57'600 (default), 0x80=28'800.
Frame format (ASCII, upper-case, little-endian ASCII-hex)
- Request:
|SOH| ua:n |EOH| [addr:n] CMD:1 [data:n] |CR|— SOH=<, EOH=>, ua = unit address (decremented as it passes downstream; addressed slave answers empty<>or all-zero<000>). CR = 0x0D. - Reply:
|SOH|[ua:n]|EOH|CMD:1|[data:n]|CR|— originator emits empty ua<>; each upstream hop increments ua. CMD echoes the request. - Any out-of-sequence
SOHstarts a new frame. Multibyte values LSByte/LSNibble first.
Commands
| CMD | Short | Description |
|---|---|---|
| R | READ | Read NUM bytes from ADDR (default ADDR=0x00, NUM=1). Stream regs read from same addr. |
| W | WRITE | Write data bytes from ADDR. Stream regs write to same addr. |
| M | MUTEX | Read-modify-write of a 1-byte mutex register (TBD). |
| Q | QUERY | Read the Device Information Block. |
| X | ERROR | Reply-only; recognised anywhere in a frame; followed by 1-byte error code. |
| Y | RESET | Reset slave, restore default register values (must not be rejected). |
Error codes (Table 3, abridged)
Ranges: 0x01–0x0F protocol/framing (engine), 0x10–0x3F standard application, 0x40–0xFF custom application. 0x00 GENERAL_ERROR.
| Code | Name | Originator |
| --- | --- | --- |
| 0x01 | NO_COMMAND_SUPPLIED | Protocol |
| 0x02 | COMMAND_NOT_SUPPORTED | Protocol |
| 0x03 | DATA_MALFORMED | Protocol |
| 0x04 | ADDR_OUT_OF_RANGE | Protocol |
| 0x05 | DATA_COUNT_OVERFLOW | Protocol |
| 0x06 | MALFORMED_FRAME | Protocol |
| 0x10 | DATA_UNAVAILABLE (e.g. empty input FIFO) | Application |
| 0x11 | DEVICE_BUSY | Application |
| 0x12 / 0x13 | READ_PROTECTED / WRITE_PROTECTED | Application |
| 0x14 | ADDR_PROTECTED | Application |
| 0x15 | DATA_OUT_OF_RANGE | Application |
| 0x16 | NOT_A_REGISTER | Application |
Register types
- Normal — byte values, block-readable via auto-increment (max read =
MAX_READ_SIZE). - Input stream — FIFO read; same addr (no increment); empty →
0x10 DATA_UNAVAILABLE. Read-only. - Output stream — FIFO write; read returns free-slot count. Over-write of a full buffer is undefined/error.
- Handshake — int8 ownership token (positive=host owns, negative=app owns) guarding a protected register set; cooperative, no HW enforcement. (Mutex mechanism = TBD.)
Device Information Block (reply to Q)
| Field | Type | Note |
|---|---|---|
| PROTOCOL_VERSION | uint8 | this doc = version 0 |
| DEVICE_CLASS | uint8 | see table below |
| DEVICE_CLASS_VERSION | uint8 | sub-class (e.g. SSTDM ATG/Bank/SweepRAM) |
| DEVICE_ID | uint16 | ties to a CSV register file |
| DEVICE_REVISION | uint8 | driver-ignored; non-CSV changes |
| ADDRESS_SIZE | uint8 | regs ≤ 2^ADDRESS_SIZE |
| MAX_READ_SIZE | uint8 | max read = 2^MAX_READ_SIZE bytes |
| EXTENDED_QUERY_INFO | list |
optional, NUL-separated (e.g. Design ID) |
(DEVICE_CLASS+DEVICE_CLASS_VERSION+DEVICE_ID select the CSV. Version-change rules in §"When to Change Device Versions".)
Defined device classes
| Class | Function | |
|---|---|---|
| 0x00 | Undefined | dev placeholder |
| 0x01 / 0x02 | Bus Mux / Bus Merge | multi downstream / upstream |
| 0x03 / 0x04 | Design ID / Design ID Query | one per FPGA design; 0x04 is Q-only (special-cased, no regs/RESET) |
| 0x10 | Link UART | 0x0000 upstream / 0x0001 downstream |
| 0x11 | UMR Link | |
| 0x12 | Serial Link | FPGA–FPGA |
| 0x40 | I2C Master/Mux | |
| 0x41 | UART Master | |
| 0x42 | SPI Master | |
| 0x43 | Hydralink Master | |
| 0x44 | GPIO Expander | (microHAPS HCI Basic) |
| 0x45 | Clock Generator | (microHAPS) |
| 0x46 | Edge Counter | (microHAPS HCI Basic) |
| 0x47 | Transceiver | (microHAPS IBERT) |
| 0x48 | SSTDM | (microHAPS) sub-classes 0x00 ATG / 0x01 Bank / 0x02 SweepRAM — strict chain order |
| 0x49 | MIG (DDR ctrl) | |
| 0x4A | Hammer | load/endurance |
| 0x4B | Telemetry | FPGA temp etc. |
| 0x4C | Skew Detector |
Protocol engine + application-side bus
Standard HW protocol engine (VHDL) exposes generics (DEVICE_CLASS/…/MAX_READ_SIZE) and a byte-wide app interface: master drives addr/wdata/R_Wn/valid/first/idle/reset, slave returns rdata/ack/error. Transaction commits on the clock edge where valid='1' and ack='1'. first = start-of-frame (addr may be non-contiguous); idle = engine not in a frame. Back-to-back single-cycle transfers supported when both ends keep valid/ack high.
Host (PC) driver stack
HciBusDriver.dll (Synplex driver) · Synopsys.HciBus.dll (protocol/registers) · Synopsys.FtdiDriver.dll (FTDI UART low-level) · HciUmrCommLibrary.dll/UmrBusAccessLibrary.dll/umr3.dll (UMR) · Synopsys.Common.dll. Interfaces: IBusController (open/close/scan/speed/reset), IBusTransactions (I2c/Hci/GpioBank/Register transactions). Scan = Q with increasing ua until timeout; requires a matching CSV per device. Addressing destinationName = <ua>|<classname> (e.g. 3|GpioExpander), with BusMux channels prepended (1|3|5|GpioExpander) and I2C virtual channels appended (1|I2cMasterMux|3). CSVs at C:\Synplex\Bin\HCI\Csv\.
CSV register-file fields
Name · Group · Address (0x…) · Reg Type (Normal/InputStream/OutputStream) · Data Type (char/uint8…uint64/int·/single/double/sfixM.N/ufixM.N) · Length · Min/Max/Default · Host Rights (RO/RW) · App Rights (RO/RW) · Unit · Description. All values little-endian.
Open items in the spec (marked TBD)
UMRBus 3.0 + Hydralink link types; MUTEX command/mechanism; UART Link Controller detail (§Bus Devices); bit-field data type.
Imported from DOCX → markdown (docs/main_pcba/docx2md.py). Full text & figures: docs/hci/HCI_Bus_Specification.md.
Architecture sketch of the R0 MUX_I2C bus (Bus B) and how it expands through the PCA9547 mux U47. Built pin-by-pin from netlist R0-I2C (id 17). Companion to the full walkthrough [[E-042]].
flowchart LR
subgraph TRUNK["MUX_I2C trunk — 3.3V, FPGA-mastered"]
FPGA["FPGA U1<br/>J10 = SCL<br/>J11 = SDA"]
DNI["C709 / C710<br/>100pF · DNI<br/>(on _R side)"]
RS["R487 / R486<br/>32Ω series"]
ADC["MCP3424 ADC<br/>U16 — 0x68"]
FPGA -. MUX_I2C_*_R .- DNI
FPGA -- "MUX_I2C_*_R" --> RS
RS -- "MUX_I2C_SCL/SDA" --> ADC
end
RS --> U47
RSTN["FPGA F13<br/>R474 0Ω + R471 pull-up"] -- "I2C_MUX_RST_N" --> U47
U47["PCA9547 U47 — 8-ch I²C MUX<br/>0x70 (A2:A0 = p18/23/22 → 000)<br/>up: p19 SCL / p20 SDA · VDD p21 = P3V3_VCCO<br/>RST p24 · ONE channel active at a time"]
U47 -- "ch0 SC0=p2 / SD0=p1" --> HT30["HT3_0 · R466/R465 4.7k→3V3<br/>R44/R43 32Ω · C26/27 DNI<br/>→ J16.144/151 (FMC/DUT)"]
U47 -- "ch1 p4 / p3" --> HT31["HT3_1 · R468/R467<br/>R49/R50 · C29/30<br/>→ J18.144/151"]
U47 -- "ch2 p6 / p5" --> HT32["HT3_2 · R470/R469<br/>R51/R52 · C33/34<br/>→ J17.144/151"]
U47 -- "ch3 p8 / p7" --> HT33["HT3_3 · R473/R472<br/>R54/R53 · C35/36<br/>→ J19.144/151"]
U47 -- "ch4 p11 / p10" --> QSFP0["QSFP_0 · R478/R476<br/>R66/R71 32Ω · R392/393 4k75 DNI<br/>C43/44 · → J10.11/12"]
U47 -- "ch5 p13 / p12" --> QSFP1["QSFP_1 · R481/R479<br/>R72/R73 · R376/377 DNI<br/>C45/46 · → J8.11/12"]
U47 -- "ch6 p15 / p14" --> MGB0["MGB_0 · R483/R482<br/>R78/R79 32Ω · C49/50"]
U47 -- "ch7 p17 / p16" --> MGB1["MGB_1 · R485/R484<br/>R80/R81 32Ω · C51/52"]
MGB0 --> PCA0["PCA9306 U54<br/>3.3V ↔ 1.8V"]
MGB1 --> PCA1["PCA9306 U50<br/>3.3V ↔ 1.8V"]
PCA0 -- "1.8V" --> J15["J15 MGB2A_1<br/>+ EEPROM U28 (0x50)<br/>+ clk U53 (0x60)"]
PCA1 -- "1.8V" --> J13["J13 MGB2A_2<br/>+ EEPROM U21 (0x50)<br/>+ clk U49 (0x60)"]
Review notes
- Trunk: FPGA (
U1.J10/J11) drivesMUX_I2Cdirectly — no buffer.R487/R486(32 Ω) isolate the FPGA pins;C709/C710(100 pF) are DNI on the FPGA-side_Rnode. MCP3424 ADC (U16, 0x68) sits on the trunk alongside the mux upstream port — always visible, not behind a channel. - U47 is a MUX, not a switch: PCA9547 selects exactly one of 8 channels at a time — which is why the identical downstream addresses (both MGB EEPROMs at 0x50, the four HT3 DUT ports) never collide.
- Channel map: ch0–3 = HT3_0..3 (DUT FMC connectors J16/J18/J17/J19), ch4–5 = QSFP_0/1 (J10/J8), ch6–7 = MGB_0/1.
- Uniform per-channel network: 4.7 k pull-up → P3V3_VCCO on the
_Rnode, 32 Ω series to the connector, 100 pF DNI cap — all 3.3 V. - MGB channels special: ch6/ch7 pass through PCA9306 (U54/U50) to 1.8 V before the MGB2A connectors (J15/J13), each with a 1.8 V EEPROM (0x50) + clock (0x60). (R1 swaps these PCA9306 → TCA9803 — log R1.0-016/022.)
- Control: address 0x70 (A0/A1/A2 = 1 k to GND); RESETn from FPGA F13 via R474 (0 Ω) + R471 pull-up.
Open questions
- Bus A (management) companion diagram still to draw (FTDI/FPGA masters, bypassed U56, Q22/Q23 CLKA branch — see [[E-045]]).
Next step
Promote to a decision/reference once the Bus A companion is added and the diagram set is confirmed against R1.
Issues
Raised from the R0 I2C walkthrough (see [[E-042]]), flagged by board owner. Design defect on the CLKA/Si5340 I2C branch.
Topology: Q22/Q23 are an NXP/AN10441-style discrete-NMOS I2C level translator between the management bus (I2C_SCL0/SDA0) and the Si5340 clock generator (U6, nets CLKA_SCL/CLKA_SDA). Intent: 3.3V (main) ↔ 1.8V (Si5340). Gate net CLK_IC_EN is a static 1k pull-up (R552) to P1V8_CLK (1.8V) — gate tied to the low rail, the canonical translator config. The 0Ω FET-bypass R119/R120 is NM, so the FETs are the active path. All translator parts (Q22/Q23 SOT-723, R551/R552/R553 1k) populated.
Defect: translator is oriented backwards and the CLKA-side pull-ups go to the wrong rail: | Terminal | Correct (NXP) | As wired R0 | |---|---|---| | FET source (body-diode, gate-referenced low side) | 1.8V CLKA side | I2C_SCL0/SDA0 (3.3V main) | | FET drain | 3.3V main side | CLKA_SCL/SDA (Si5340) | | CLKA-side pull-ups R551/R553 | → 1.8V (P1V8_CLK) | → P3V3_CLK (3.3V) |
Evidence Si5340 I2C I/O is 1.8V: every Si5340 digital strap — CLKA_I2C_SEL (R114), CLKA_LOS# (R115), CLKA_INTR# (R116), CLKA_LOL# (R117), CLKA_RST# (R118) — pulls to P1V8_CLK (1.8V). So SDA/SCL (U6 pins 13/14) are 1.8V-referenced.
Steady-state behaviour (the real failure signature): the Si5340 input ESD diode clamps CLKA to VDD+0.6 ≈ 2.4V, which propagates back through the Q22/Q23 body diode (anode = main-bus source) — a second 0.6V drop — so the 3.3V management bus idles at only ~3.0V:
P3V3 -[1k]-> MAIN bus --|>|-- CLKA --|>|-- Si5340 VDD(1.8V)
(~3.0V) Q22 body (2.4V) ESD diode
R555/R556 (main pull-up) + R551/R553 (CLKA pull-up) continuously source ~1.2 mA into the Si5340 1.8V rail.
Consequences:
- Whole Bus A high-level clamped, not just the Si5340 — "3.3V" I2C idles at ~3.0V (main)/~2.4V (CLKA).
- Bus still functions for high-V_IH parts (live scan ACKed all 6 devices) — hides as "works fine" while out of spec. ⚠ See CONFIRMED IMPACT below — this does NOT hold for the LTC2980.
- Reliability: continuous ~1.2 mA into Si5340 1.8V VDD; ~2.4V over-voltage on its 1.8V I2C pins; possible back-powering of P1V8_CLK.
- May contribute to Si5340 (0x74) not appearing in the FTDI scan (E-042); CLKA_I2C_SEL gating is an alternative cause.
To confirm: Si5340 digital VDD / I2C I/O rail per datasheet (expect U6 pins 8/9 = VDDA 3.3V; digital VDD = P1V8_CLK group) and pin abs-max vs 2.4V. Scope SDA/SCL idle high (expect ~3.0V, not 3.3V).
CONFIRMED IMPACT — actively BLOCKED the LTC2980 (2026-06-11, DUT H883774)
This defect is not merely an out-of-spec margin nuisance — it functionally broke the primary management device. On reworked DUT H883774, the reversed Q23 (SDA-side FET) body diode loaded/clamped I2C_SDA0 enough to block the LTC2980 (0x5C/0x64): the address byte ACKed in a scan, but every command NACKed (incl. STATUS_BYTE) — full symptom + diagnosis in [[E-052]]. Unmounting Q23 (Q22 already lifted) restored full LTC2980 comms. So consequence #2 above holds for high-V_IH parts but NOT for the LTC2980, whose input/clamp behaviour the back-drive actually broke. Severity escalated warning→blocking accordingly.
R0 rework — correction to the "not reworkable on R0" note below: you do NOT need to fix the FET orientation. Simply remove Q22 + Q23 (the CLKA/Si5340 branch is not needed for bench management-bus work); this fully isolates the parasitic tap and is confirmed effective on H883774.
Design-log status (SH100008193_R1.0 DesignLog): the passFETs are addressed by R1.0-008 (eriki, 2026-02-03, vs R0.0 sheet 7): clock gen moved to the FPGA power domain + onto the FPGA_I2C segment, and the "passFET buffer interferes with the I2C buffer that is being used" → passFETs removed in R1 (disposition also replaces the 2-pin header with an empty pull-down). So the component is known and removed in R1, but the reverse-orientation / Si5340-ESD back-clamp mechanism documented here is NOT in the log (recorded only as "interferes"). R1 removal incidentally resolves it; this entry preserves the root cause — and the H883774 result above is the empirical confirmation of what "interferes" actually meant.
Fix (R1, if a translator is retained anywhere): FET source + gate(1.8V) reference + pull-up on the 1.8V side, drain + pull-up on the 3.3V side; pull-ups to the matching rail. (Orientation fix is a layout change — not reworkable in place on R0, but outright removal is, see above.) Verify on R1 schematic SH100008193_R1.0.
Confirmed schematic-vs-BOM/board discrepancy on the FTDI I2C buffer (sheet 8). This is the root mechanism behind the blocking [[E-048]].
The mismatch
| Part | Schematic intent (sheet 8) | BOM + physical board |
|---|---|---|
U56 TCA9803 (FTDI I2C buffer) |
POPULATED (no DNI) | NM ([Disabled]) |
R558 / R559 (0Ω bypass) |
DNI (both marked DNI) | fitted (0Ω) |
So the populate/DNI is swapped. Schematic = buffer in, bypass out; board = buffer out, bypass in. The board was built to the (incorrect) BOM, so the FTDI sits directly on the management bus, unbuffered ([[E-044]]) → the 0.4 V V_OL the LTC2980 rejects ([[E-048]]).
Likely true origin — an enable-polarity bug (Daniel's reconstruction)
The buffer was probably swapped out because it didn't work as strapped, not for the backfeed reason the R1 log cites:
U56EN (pin 5) net isI2C_FTDI_EN_N— named active-low, but the TCA9803 EN is active-HIGH. Mislabel.R557(4.75k) pulls EN to GND → default LOW = buffer DISABLED. So out-of-the-box the buffer is off and the FTDI can't talk through it.- Same polarity bug Erik later hit in firmware ([[E-022]]/E-023: "EN active-high, must be driven HIGH; code assumed active-low and drove it low → I2C never reached the bus") — inherited from the net name.
- Wrong response: instead of fixing the enable strap, the build removed U56 and fitted the 0Ω bypass (R558/R559) to hard-wire the FTDI onto the bus. That "works" but discards the buffer → unbuffered V_OL → E-048. This also explains the two board builds: firmware path (Erik kept U56, drove EN high) vs hardware path (this board, bypassed).
Correct fix
Keep U56; change R557 to pull EN to P3V3_G (default HIGH/enabled, mislabel notwithstanding); DNI R558/R559. A one-resistor polarity flip instead of deleting the buffer. (See bench plan [[E-050]].)
Caveat
Even Erik's enabled-buffer board scanned 0x5B (global) but never 0x5C/0x64 — so the TCA9803 B-side static V_OL offset may itself exceed the LTC2980 V_IL (project 46 / E-004). So fixing the buffer+EN may restore global power control but not necessarily the per-die addresses; verify, and weaken the pull-up if needed.
Action
- Bench-test per [[E-050]] (fit U56, lift R558/R559, fix R557/EN), check 0x5C/0x64.
- Fix the BOM (U56 populated, R558/R559 DNI) and the EN strap polarity (R557 → P3V3_G); flag to Synopsys. This is the 2nd schematic-vs-BOM NM discrepancy on R0 (cf. [[E-039]] C10–C13) → audit the BOM generation across the board.
Links: [[E-048]] (blocking V_OL), [[E-044]] (unbuffered bus), [[E-022]] (EN polarity, firmware), [[E-039]] (sibling NM discrepancy), [[E-050]] (bench plan), [[E-042]] (walkthrough).
The board's JTAG signals pass through an on-board buffer gated by ADBUS5 = JTAG_FTDI_EN_N (active-low; must be driven low to enable). See E-034.
Problem (R0)
openFPGALoader's generic ft4232 cable drives only ADBUS0–3 (TCK/TDI/TDO/TMS) and leaves ADBUS5 as an input, so the buffer stays disabled → openFPGALoader -c ft4232 --detect runs at 6 MHz but reports found 0 devices (or garbage IDCODE 0x00040003) even when powered. openFPGALoader has no CLI option to assert an arbitrary ADBUS output (--pins only remaps TDI:TDO:TCK:TMS). Synopsys's own R0 pin-map flags ADBUS5/JTAG_FTDI_EN_N as "Inaccessible when using Vivado" — the same wall.
Our in-module XvcServer does drive ADBUS5 low (DIR 0x2b), which is why the IDCODE reads correctly over XVC (E-034) — effectively the only path that makes FTDI-JTAG usable on R0.
Two host-side workarounds were tested and REJECTED (both fail)
- Pre-drive A5 low, release, then run openFPGALoader: A5 was driven low (
FT_SetBitModeasync-bitbang; readback0xDF→ A5=0), but openFPGALoader's libftdi init rewrites the whole ADBUS direction byte (A5→input) on open → buffer dropped → garbage. The latched state does not survive the handoff. - EEPROM default on the pin: the FT4232H has no EEPROM-configurable ADBUS power-on output (ADBUS5 = DSR# UART input by default;
FT_EEPROM_4232Hexposes only SlowSlew/SchmittInput/DriveCurrent/RI-is-TXDEN/DriverType per channel). The CBUS-default-state feature is FT232R/FT-X/FT232H only — not FT4232H. And MPSSE init would override it regardless.
Root cause: whoever sets MPSSE on interface A owns all 8 ADBUS directions; only A5-as-output-low enables the buffer, and nothing external survives the JTAG tool's init.
Resolution
- R1.0 fixes this at the board (see E-016): the R1 pin-map moves JTAG_FTDI_EN_N from ADBUS5 (interface A) to BDBUS4 (interface B) ("Moved from ADBUS"). Interface B is owned by MicroHapsHandler (D2XX), so on R1 we hold the JTAG buffer enable on BDBUS4 independently of whoever drives JTAG on interface A — openFPGALoader / Vivado then work with no cable patch and no tricks. R1 also puts
SFPGA_DONE_N(BDBUS5),SFPGA_PROG/PROG_B (BDBUS6) andPSON(BDBUS7) on interface B → a clean program/verify/power pipeline on the interface we own (I2C_EN shifts BDBUS4→BDBUS3). - R0 decision — accept the slow path: use the in-module
XvcServer(bit-bang, drives ADBUS5) for JTAG on R0. Do not invest in a throwaway openFPGALoaderft4232+ADBUS5 cable patch or a native clocked-MPSSE programmer for R0 — both would be R0-only and obsoleted by R1. Fast clocked programming arrives on R1 via openFPGALoader (interface A) + our BDBUS4 enable.
Status: open, deferred to R1 (next_revision). On R0, JTAG works via the slow XVC path only.
BLOCKING on R0. Confirmed by scope measurement + DC1613A cross-check. On stock R0 there is no working path to control the on-board power system from the intended FTDI service port — the power-system manager will not talk to the FTDI.
Symptom
The FTDI (FT4232H) I2C master gets no response from the LTC2980 power manager (U15) at its die addresses 0x5C (die A) / 0x64 (die B). An external DC1613A dongle does reach them (scan = 4C, 50, 57, 5B, 5C, 64) — but only with the FTDI USB unplugged; a powered FTDI blocks the bus entirely (FTDI ↔ dongle are mutually exclusive on the unbuffered bus).
Root cause (measured)
The management-bus low level is marginal:
- Bus pull-up = a single 1 kΩ → P3V3_G (
R555/R556; trunkR69/R70+ LTC locals are NM — see [[E-044]]), and the FTDI is hard-wired onto the bus (bufferU56NM, bypassed by 0 ΩR558/R559). - V_OL = I_sink × R_driver-on; 1 kΩ ⇒ ~3.3 mA sink.
- FT4232H V_OL ≈ 0.4 V at that current (weak I/O); DC1613A V_OL ≈ 0.2 V.
- The LTC2980 / LTC297x has a tight V_IL and rejects the 0.4 V "low" (well-known LTC PMBus sensitivity to high V_OL), so it ignores the FTDI master. Other devices (EEPROM 0x50 / TMP441 0x4C / fan 0x57) tolerate 0.4 V and do ACK — which is exactly why Erik's FTDI scan returned
30,4C,50,57,58,5Bbut never 0x5C/0x64.
Why blocking
The LTC2980 (U15) is the power-system manager. From the service port you cannot read or configure it per-die/per-rail: set VOUT, HT3_VCCO control, telemetry, etc. — the bring-up code's psm["A"]@0x5C / psm["B"]@0x64, set_vcco, and step_16 program_power_supplies all target 0x5C/0x64 (only global on/off uses 0x5B). So per-rail power control is non-functional from the service port, and the DC1613A side-load works only with the FTDI removed (not a usable operating mode). ⇒ the power system cannot be controlled on stock R0.
Fixes
- R0 rework (recommended): swap bus pull-up
R555/R5561 kΩ → ~4.7 kΩ. Sink ~0.7 mA ⇒ FTDI V_OL ≈ 0.1 V, well under the LTC threshold. Two-resistor change; verify rise time vs total bus C. (Alternative: fitU56TCA9803 to regenerate a clean low.) - Interim: DC1613A / LTpowerPlay with the FTDI USB unplugged (works; confirms 0x5C/0x64).
- R1: FTDI is buffered (U60) so its weak V_OL no longer reaches the bus — but verify the TCA9803 static V_OL offset doesn't re-introduce a marginal low at the LTC2980 (project 46 / E-004).
Evidence
- Scope: FTDI V_OL ≈ 0.4 V vs DC1613A V_OL ≈ 0.2 V.
- DC1613A scan
{4C,50,57,5B,5C,64}— only with FTDI unplugged. - FTDI scan
{30,4C,50,57,58,5B}— never the LTC dies. - ASEL straps physically confirmed correct (die-A L/L = R331/R332 fitted; die-B H/H = R321/R322 fitted, R329/R330 empty) → decode to 0x5C/0x64. Not a strap error.
Links: root cause [[E-044]]; address map [[E-042]]; bring-up power sequence [[E-015]].
RESOLVED on R0 board by bench rework (E-050), 2026-06-08. Daniel fitted U56 (TCA9803) and removed the R558/R559 0Ω bypass jumpers. Result: full I2C scan now returns all expected addresses, including the LTC2980 power-manager dies 0x5C/0x64 that the unbuffered FTDI could not reach. The buffer regenerates a clean V_OL, so the FTDI service port can now control the power system. Bench fix verified; the corresponding BOM/schematic correction for the next board build is tracked under the still-open E-049 (flag to Synopsys).
Bench finding after the [[E-050]] rework (U56 TCA9803 fitted, R558/R559 0Ω bypass removed, EN strap fixed). The [[E-048]] "resolved" verdict was premature — a passing address scan only proves the address byte + ACK path works, not that the management bus is usable. E-048 stays closed per Daniel; this is the new blocking tracker.
Symptom
- I2C scan over the FTDI now ACKs all expected addresses, including 0x5C and 0x64 (the two LTC2980 internal controllers).
- BUT as soon as you transact with the LTC2980, every command NACKs — including commands it must ACK such as STATUS_BYTE (0x78).
- Failure is identical on both 0x5C and 0x64 (same die, shared I2C pins).
Interpretation
The address phase ACKs but the command/data byte NACKs. That means:
- The LTC2980 is alive, at the right address, EN/power OK — not a dead device, wrong address, or enable problem.
- Both 0x5C and 0x64 failing identically ⇒ a board / buffered-segment electrical cause, not per-die config (PEC, WP, page, fault state). Software/config explanations are largely ruled out.
- Clock stretching ruled out (Daniel: this LTC2980 setup has been used before, never required clock stretch; FTDI master handshake is known-good).
Aggressors ruled out
- U5 (FPGA-bridge TCA9803) and R64/R65 (0Ω bypass) confirmed NM ⇒ FPGA bridge is not driving the segment. On R0 the only active driver on the LTC's segment is U56.
Lead hypothesis — TCA9803 B-side V_OL vs LTC2980 V_IL margin (the project-46 / E-004 concern materialising)
U56's regenerated low (static offset ~0.4–0.6 V) sits near the LTC2980 V_IL. Marginal margin lets a single byte + ACK through but fails under sustained toggling ⇒ consistent command NACK. Aggravated by:
- Strong 1k bus pull-ups R555/R556 (more sink current ⇒ higher buffer V_OL).
- R0 has no dedicated B-side pull-up (R1 explicitly added one at U60 B-side, and put the LTC2980 direct-on-bus — R1.0-016/022). Root mechanism is the same family concern flagged in [[E-049]] and project-46 / E-004.
Decisive tests (in order)
- Scope SDA + SCL at the LTC2980 pins (B-side) during a STATUS_BYTE read. Measure V_OL on both lines and rise times. V_OL sitting ~0.5 V near the LTC V_IL ⇒ confirms margin failure.
- Weaken R555/R556 1k → ~4.7k (and/or add the dedicated B-side pull-up R1 uses) and retry — the E-050 fallback fix.
- Talk to the LTC over the DC1613A / native PMBus header (bypassing FTDI+U56). Clean comms there ⇒ problem is 100% the U56/FTDI buffered path.
- Drop FTDI I2C clock (e.g. 10–50 kHz) and retry — NACKs clearing at low speed corroborates a rise-time / level-margin issue.
Related
- Design concern that two static-offset buffers can't share the segment without enable orchestration — separate note (most relevant to R1). See sibling notice.
- [[E-048]] (kept closed), [[E-049]] (BOM↔schematic swap root cause), project-46 / E-004 (V_OL/V_IL margin).
RESOLVED 2026-06-11 on DUT H883774. Root cause = Q23, the reversed CLKA↔main I2C passFET ([[E-045]]). Its body diode (source mis-wired onto the 3.3 V main side = I2C_SDA0) clamped/loaded the LTC2980 SDA line: a single address byte squeaked through (→ ACK in a scan) but sustained command/data toggling was corrupted → NACK on every command incl. STATUS_BYTE. Fix: with Q22 (SCL tap) already lifted, unmounting Q23 (SDA tap) fully isolated the CLKA branch from the main bus → LTC2980 0x5C/0x64 now communicate as expected.
The original lead hypothesis (TCA9803 B-side V_OL vs LTC2980 V_IL margin, project-46/E-004) is exonerated for this symptom — the U56 buffered build is fine once the parasitic SDA tap is gone; no pull-up change (R555/R556) was needed.
Proper R0 fix = remove/correct the reversed Q22/Q23 passFETs (see E-045, now escalated). R1 already removes these from the I2C path (passFETs repurposed to LTC2980 CONTROL buffers, Si5340 moved to FPGA_I2C — R1.0-007/008/011/021), so R1 does not carry this defect.
Test-host software defect (AccordionQ2 / MicroHapsHandler extension), not a board issue. Recorded for the R0 bring-up history.
Symptom
Unloading the MicroHAPS module and loading it again always failed. The reload log showed:
- FT4232H interface A enumerating as
FT_DEVICE_UNKNOWN/MISSING(empty serial/desc,loc=0x0). XVC: unable to claim usb device. Make sure the default FTDI driver is not in use(openFPGALoader-5).- Board I2C MPSSE
read timeout: got 0/2 byteson power-cycle, EnsureBoardPowered, and both PMBus engine scans.
First load after a service (re)start always worked; only reloads failed.
Root cause
ExtensionModuleService.UnloadModule dropped the module reference without ever calling Dispose(), and MicroHaps had no teardown anyway. The abandoned instance kept everything live:
- The persistent
openFPGALoader --xvcchild process kept running and held interface A (libftdi claim) + TCP port 2542. A .NETProcessfinalizer does not kill its child, so GC could never reclaim it — the one truly unrecoverable leak. - The board I2C (B), HCI (C/D) and GPIO (D) D2XX handles stayed open, disturbing the shared FT4232H.
On reload the new instance therefore could not claim any interface.
Fix
Commits: AccordionQ2 parent b6e5087; accordionuno submodule 02a459b.
ExtensionModuleService.UnloadModulenow calls(module as IDisposable)?.Dispose()(best-effort) before dropping it — benefits every disposable module.MicroHaps : IDisposable— tears down JtagPort (kills XVC → frees interface A + port), PMBus engines, HCI/Ftdi, board I2C, GPIO.Ftdi : IDisposable— closes its lazily-cachedUart(D2XX) handles, so the HCI interface is actually released.JtagPort.KillStrayXvcServers— Linuxpkill -f "openFPGALoader.*--port <port>", called fromReset()as belt-and-suspenders against a leak from an older host or an externally-launched loader.
Verification (agent64, 2026-06-08)
- Unload:
XVC server stopped (interface A + port :2542 released)→MicroHAPS disposed — FT4232H interfaces released→Finished unloading. - Reload: interface A present, MPSSE I2C opened, POWER cycle completed (I2C ACKed), XVC server up (
TCP:agent64:2542), PMBus MPM (0x30) engine loaded.
Known follow-up (separate, next)
The reload now exposes intermittent LTC2980 (LTPP / U15 @ 0x5B/0x5C) no-ACKs right after power-on: EnsureBoardPowered: no ACK from 0x5B and LTPP init/load failed: no ACK from 0x5C on STATUS_WORD (0x79) — even though the scan just found 0x5c/0x64. Signature looks like the LTC2980 being accessed before it finishes booting after rails-on (MPM3695 comes up faster, unaffected). To be tracked + fixed as a post-power-cycle settle/retry issue. This is distinct from the handle leak fixed here.
Fixed and verified on agent64 (2026-06-08). AccordionQ2 parent commit b6e5087 + accordionuno submodule 02a459b: UnloadModule now disposes IDisposable modules; MicroHaps/Ftdi implement IDisposable to release the XVC process and all FT4232H D2XX handles; JtagPort.KillStrayXvcServers sweeps orphaned --xvc at load. Unload→reload cycle confirmed clean (interface A present, XVC up, I2C/PMBus-MPM OK). LTC2980/LTPP post-power-on no-ACK is a separate follow-up, not part of this issue.
Decisions
Confirmed by Dave Upton (Synopsys) on the "RE: KU5P Test board" thread (early Feb 2026): the direction is aligned.
Agreed direction:
- For PCBA-level assemblies where it makes sense to leverage microHAPS (mainly daughter cards, adapters, and some panel boards), E-Sharp will develop, build, test, deliver, and maintain production PCBA test fixtures leveraging the microHAPS hardware.
- End-state business model: E# develops test suites for future SNPS products with this tester, and SNPS does turnkey purchases from E# of KU5P test equipment + the AGENT environment.
Extent E# could cover (Daniel's offer, extent TBD by SNPS): turn-key supplier of microHAPS incl. electronics, PCBA, firmware/RTL, software stack, GUI, and test development; plus test-fixture mechanics / test boards that fit microHAPS; plus CM deployment, bring-up, and support (as in other E# projects).
Rationale: SNPS built microHAPS as a low-cost at-speed tester using HAPS connectors; E# brings the AGENT test environment, fixture design, and CM/support capability. Alternative considered & rejected: using E#'s existing Accordion product instead of a dedicated board — rejected by SNPS because microHAPS enables at-speed functional test of daughter cards (HT3/HT4/MGB) that Accordion could not.
Open: exact extent of E# scope and the formal engagement/contract mechanism still to be defined (see action entry).
Decision (Daniel's strong recommendation, accepted in principle by Dave Upton): use HCI (Host Controller Interface) as the host↔board communication layer, running over UART through the microHAPS FTDI chip.
Rationale:
- HCI was specified by Daniel while at Synopsys precisely for this use case — an extensible host controller with a predictable communication layer. It solves enumeration, data coercion, and extension problems that ad-hoc register maps do not.
- HCI is UART-based and works with FTDI. Constraint: a full UART is required — RX/TX/CTS/RTS (4-wire). SNPS confirmed they already use a 4-wire UART during board bring-up, so HCI via FTDI should not be an issue.
- A large number of ready-made HCI blocks already exist in SNPS Perforce: UART / I2C / JTAG / Clock / Counter / SSTDM.
- AGENT natively supports the HCI bus → GUI support with zero code when the FPGA design is loaded. A dedicated microHAPS graphical panel would greatly reduce work when adding functionality or adapting to a new DUT.
Alternatives considered: a simple custom UART register map/interface (Dave's initial sketch for the fixed GPIO firmware). HCI is preferred as the general layer; a low-level register map may still coexist for the fixed GPIO bit-bang firmware.
Action: reach out to Ulf Winberg (HCI expert) for the spec; Daniel also has a copy.
Decision (SNPS proposal, agreed): retain the existing base mechanics — an open-frame ATX case — because it is simple and cheap.
- DUTs are held by a custom "top plate" on the open-frame enclosure.
- New top plates are designed as needed, per DUT, and swapped on a build-by-build basis (not in the factory).
- There is space in the open-frame enclosure to host a Raspberry Pi controller (E# uses RPi as controller in other projects).
E# scope opportunity: design of new top plates / fixture mechanics fits within E#'s offered turn-key scope.
Plan (Dave Upton): assuming the engagement moves forward, SNPS will get Daniel a Rev0 microHAPS so E# can start working with it. Rev1 microHAPS is the target for any formal deployments.
Context: first prototypes came back ~4 weeks before the email (≈ early Jan 2026); current firmware is mainly board-validation / bring-up and still needs maturing. A cleanup/final revision is in progress (see related notice).
Decision (Daniel): do not create BOM components or component-library entries in PLEASE for the microHAPS BOM (docs/main_pcba/BOM_SH100008193_R0.csv, ~160 line items).
Rationale: this is a customer (Synopsys) project and its BOM uses Synopsys SH… part numbers. We do not want customer part numbers entering E-Sharp's own / shared component database (the global component library is reused across E# projects). The BOM is retained only as the source CSV; functional architecture is captured qualitatively in the architecture notice.
Consequence: please_component_* / please_bom_* / netlist ingestion are deliberately left empty for this project. A feature request has been filed to support separate per-customer component libraries so customer BOMs can be captured in isolation in future (see PLEASE feature request).
Decision: the MicroHAPS Accordion deployment host (running the MicroHapsHandler extension that drives the FT4232H Service Port) is a Raspberry Pi, 64-bit (linux-arm64) — consistent with the accordionq2 fixture convention and the enclosure's RPi provision (E-004).
Resolves the long-open "host PC vs Raspberry Pi" question (project 44, E-008 / E-024).
Consequences:
- Project
RuntimeIdentifierstayslinux-arm64(already set). - Native FTDI lib needed:
libftd2xx.sofrom the FTDI Linux 1.4.34 ARMv8 build →runtimes/linux-arm64/native/. - The
linux-x64build/lib is retained only for desktop dev/testing, not deployment. - Pi setup still required: detach
ftdi_siofrom the MPSSE interfaces (A/B/D), udev rule for FTDI VID 0x0403 (see runtimes/README.md / E-024).
Note: this is the host for E#'s own Accordion-based control; the Synopsys flow (Vivado Lab / NI-VISA / Synplex) remains on an x86 PC separately.
Notices
Key context for this project, as provided by the engineer:
- Micro-HAPS is a test board developed by Synopsys (SNPS).
- Purpose: run tests at-speed — i.e. exercise high-speed I/O at full operating I/O rates rather than reduced/structural speeds.
- Core device: Xilinx Kintex UltraScale+ KU5P FPGA.
- This PLEASE project covers E-Sharp's test-development work on/with the board (primary domain test, secondary electronics).
Open questions to resolve:
- Which DUT(s) / target project(s) is Micro-HAPS used to test? (link via target-under-test once known)
- What at-speed I/O standards/rates are targeted (e.g. specific SerDes/GTY line rates, LVDS, memory I/F)?
- Is the physical board owned/maintained by Synopsys, or is E-Sharp building a derivative/fixture around it?
Technical description of the microHAPS (a.k.a. "KU5P Test Board") from Dave Upton:
Origin/intent: inspired by HAPS systems previously used as test equipment (daughter cards etc.). Goal: a low-cost tester with HAPS connectors that can test things at-speed or via GPIO.
Control: primary control interface is an FTDI chip exposing JTAG, I2C, UART, and GPIO into the FPGA, plus I2C into the power controllers. There is a native JTAG connector and an I2C header. The cleanup revision adds headers on the UART and GPIO interfaces.
Connectors (native): HT3, MGB2A, QSFP. Adapters developed: HT3→HC3, HT3→HT4, MGB2A→NVAC (internal MGB2). A cable converts MGB2A→MGB2B/C.
Firmware model — loaded per purpose:
- A generic/fixed GPIO RTL firmware giving total GPIO control of the HT3 connectors via a simple UART register map — for low-level bit-bang tests.
- An at-speed firmware loaded to test things not possible with GPIO (e.g. at-speed DDR4 daughter-card test) with status comms back to the host via FTDI / UART / GPIO headers.
Drivers for building this board (vs. reusing Accordion): at-speed functional test of HT3/HT4/MGB daughter cards.
SNPS is doing minor updates for a final revision of microHAPS. Known changes:
- Add headers on the UART and GPIO interfaces.
- Add power on/off control of the ATX PSU via FTDI (currently a manual switch).
Action: Dave will share the release-candidate schematic for E# review once available. → review when received, and confirm HCI's full 4-wire UART (RX/TX/CTS/RTS) is broken out on the UART header.
Unresolved items raised in the thread that need decisions:
- Firmware/RTL ownership — Dave: "We could discuss who owns the firmware (not sure if you have those capabilities)." Daniel's position: E# can own firmware/RTL as part of turn-key scope. → confirm split.
- Control path — interface to the board via the FTDI chip vs. directly to a header (UART/GPIO) — TBD.
- Host — host PC vs. Raspberry Pi in the open-frame enclosure (E# typically uses RPi as controller) — TBD.
Dave Upton asked: "How do you want to formally move this forward?" — E# needs to propose the formal engagement/contract mechanism for the microHAPS test-fixture program.
SNPS commitment: Dave to provide timeline needs for the target PCBAs later that week (≈ early-mid Feb 2026). → chase the timeline and pair it with the four target DUTs.
From the Synopsys PCB Specification (docs/main_pcba/SH100008192_R0.0_KU5P_Generic_Tester_PCB-Specification.pdf). ⚠ SYNOPSYS CONFIDENTIAL.
- PCB:
SH100008192-R0.0"KU5P_Generic_Tester" — part of the PCBASH100008193-R0.0(the microHAPS board referenced throughout these projects). - HW designer: Martin Wang (Synopsys, PMG / HAV System Design, Mfg & Ops — wang@synopsys.com). Board created in Empower 2025-10-03. Underlying board ref SH100007434-R1.0.
- Mechanical: 49 × 67 mm; 2 mm thick (±10%); min hole 10 mil; routed edges.
- Stackup / electrical: 18 layers (8 signal: 1,3,5,7,12,14,16,18); base material DS-7409DVC; impedance-controlled — 50 Ω single-ended (microstrip/stripline), 90 Ω & 100 Ω differential, all specced @ 1 GHz, ±10%; VIPPO (all vias filled & covered, IR-6P), back-drilled; no blind/buried vias.
- Finish / standards: ENIG (Ni 3 µm / Au 0.05 µm); green soldermask; white silkscreen both sides; IPC-6012 Class 2; UL required; repaired boards not accepted.
- Production files (in Empower): ODB++, Gerber, NC drill. Local docs: schematic (31 p), assy drawings top/bottom, PCB spec — under
docs/main_pcba/.
Functional block summary of the microHAPS PCBA (derived from the schematic + BOM; qualitative — no customer part numbers imported). ⚠ SYNOPSYS CONFIDENTIAL design.
- Main device: Xilinx Kintex UltraScale+ XCKU5P-1 FFVB676 FPGA (U1) with dedicated heat sink; configuration 2 Gbit SPI NOR flash + SPI EEPROM.
- Host control: FTDI FT4232H quad USB-to-UART (U10) via USB-B (J4) — provides JTAG / I2C / UART / GPIO into the FPGA and power controllers (matches the control story in E-006). 12 MHz crystal.
- Clocking: Si5340A clock generator (U6); 2:10 1.25 GHz fanout/mux (U7); Si53307 buffers; I2C-programmable oscillators (10 kHz–350 MHz); 50 MHz crystal.
- Power: multi-rail — 16-channel PMBus Power System Manager (U15) for sequencing/telemetry; DC/DC modules (quad 4×5 A, 8 A, 3.3 V 25 A, dual-output, MPM3630 3 A); TPS7A8101 1 A LDOs; eFuses + slew-rate load switches; ATX input via Mini-Fit Jr (PJ1 24-pos / PJ2 8-pos) + 6 A slide switch (SW1).
- Monitoring/thermal: 4-channel 18-bit ADC (U16); temperature sensor; precision fan-speed controller (U55) + PWM fan header (J21).
- I2C infra: 8-channel I2C mux (U47); level translators; I2C EEPROM with pre-programmed EUI-48 MAC.
- High-speed I/O connectors: 2× QSFP+ (cages J7/J11 + connectors J8/J10); Samtec SEAF-20 high-density arrays (J16–J19); ARF6-RA 16-pin "Accelerate" (J13/J15) — these carry the HT3 / MGB2A / QSFP interfaces noted in E-006.
- UI/headers: 16 green LEDs; tactile + slide switches; native JTAG & I2C headers; UART/GPIO headers (per the cleanup revision, E-007).
No PLEASE component/BOM records were created for these — see the BOM decision entry.
From Erik Ingemarsson (Synopsys, HW Engineering Staff Engineer — the microHAPS technical contact; Erik.Ingemarsson@synopsys.com), nearing the end of MicroHAPS R0.0 hardware verification. Several FPGA designs (bitstreams) have been generated, all with at least some HCI:
- HCI Basic — GPIO, I2C, and edge-counters (count clock pulses). Loaded in the FPGA SPI-FLASH as the always-present initial design (also validates the SPI-FLASH).
- HCI IBERT — HCI Basic + IBERT on all four GTY banks (used a few times, works well).
- HCI SSTDM — GPIO on non-HT3 IO, I2C, and SSTDM on banks 64–67. Comes in several variants, some SSTDM-only (no GPIO/I2C). These were generated from an older module; Erik bundled a copy of the matching Python module in his stream as a workaround.
SSTDM at-speed characterization (different signaling/speeds/IO pairings). Differential designs expose all four HPIO banks simultaneously; single-ended fits only 2 HPIO banks at a time, so single-ended ships as 3 copies covering banks 64-65, 64-66, 66-67. Results so far:
| Signaling | Mode | Rate | Result |
|---|---|---|---|
| DIFF SSTL18 | Differential | 2200 Mbps | Good |
| SSTL18 | Single-ended | 1000 Mbps | Poor (as expected) |
| POD12 | Single-ended | 1000 Mbps | Very good |
| POD12 | Single-ended | 1600 Mbps | Pending (~by the weekend) |
Perforce: all designs are under Imported/Bitfiles in the stream (pulled when you create a workspace). This is the at-speed capability that the program's high-speed testing (cf. B12-N Phase C, project 44 E-018) would build on.
Three adapter cards have been created (per Erik Ingemarsson) to test specific projects via MicroHAPS:
- SH100008569 — HC3-HT3 Adapter: benched project.
- SH100008541 — MGB2A-NVAM: assumed to relate to one of the new B12 panels.
- SH100008643 — HT3-HT4 Adapter: to test the HT3-HT4_External_Adapter; cards expected through reflow that week. (This is the adapter relevant to the B12-N project — ETT00000009, where it appears as DUT 13 / fixture kit SH100009012.)
Also: ~16 NVAM-loopback cables exist (heard via Ops), assumed to relate to card 2 (MGB2A-NVAM). Erik has a few of each card for verification but does not know the deployment plan.
(Synopsys SH part numbers — recorded as reference only; not imported into the component library, per decision E-012.)
Procedure to power up and activate a MicroHAPS R0.0 board (from Erik Ingemarsson — answers E#'s getting-started questions):
- It does NOT auto-start when 12V is applied. Enable commands must be sent via I2C to both U15 (16-ch PMBus power-system manager) and PU8 (3.3 V 25 A module). This command is in the example script at line 62.
- Three soldered wires go to an I2C header — soldered because that header is not pin-compatible with the Analog Devices or MPS dongle. You can keep them soldered or remove them.
- With the ATX PSU on, flip the big black switch next to the QSFP ports so the button is closest to the front edge of the board → 12V from the ATX turns on.
- Plug in USB to enumerate — standard FTDI (FT4232), no special driver. The example script contains the basic "activate MicroHAPS" steps.
SPI-FLASH: the board holds HCI Basic in SPI-FLASH as an always-present initial design, so you do not need to load a bitstream every boot (designs can still be loaded as needed; see HCI designs notice).
Verification scripts (Perforce): beyond the example script, many scripts verify aspects of MicroHAPS and are organized in folders matching verification-plan steps — e.g. initial Service Port (FTDI FT4232) programming is in step_07_setup_service_port. Several should be easy to adapt to instead use MicroHAPS to test another DUT.
Heads-up from Erik Ingemarsson: R1.0 is being sent to production now. Key differences vs R0.0:
- The big black 12V switch is removed.
- The Service Port is moved into the AWO (always-on) domain.
- 12V on/off can be automated (no manual switch). This is the FTDI-controlled ATX power on/off noted in E-007, and addresses the "power control is critical for DUT load/unload" point raised on the B12-N project (project 44, E-004).
Erik has included the PCBA revision in his board-control class to branch behaviour by R0.0 vs R1.0, but the code is not yet updated to handle the difference (time constraints).
Implication for E#: bring-up tooling/driver must be revision-aware (R0.0 manual switch + I2C enable to U15/PU8 vs R1.0 automated). Confirms the rollout plan (E-005: Rev0 to E# to start, Rev1 for deployment) and the cleanup-revision changes (E-007).
From "MicroHAPS User Resources" (Erik Ingemarsson, rev 0 / 2026-01-27; docs/main_pcba/MicroHAPS_User_Resources.docx, git-ignored/confidential).
The Service Port = FTDI FT4232H, USB 2.0 → on-board control of JTAG, I2C, UART, and some GPIO.
Host software — full install list is in SharePoint: Instruction_for_Boa_Synplex_Test_Station_Bring up.docx (contact your local Synopsys contact for install help).
NI MAX — Bsp (Service Port) driver session must be configured:
OpenByType: 7OpenByTypeArgument: ^.*Service PortOpenPort_A: FalseOpenPort_B: TrueOpenPort_C: FalseOpenPort_D: False
(i.e. only port B of the FT4232H is opened for the Service Port.)
Toolchain versions:
- Python 3.10.11 — primary scripting language.
- ActiveTcl 8.6.13 — for AMD Vivado Lab automation.
- Vivado Lab 2024.2 — handles JTAG for the KU5P: device-temperature reads, IBERT bit-error counts, FPGA bitfile programming, etc.
Reference locations for the MicroHAPS, from "MicroHAPS User Resources" (Erik Ingemarsson).
Naming note: MicroHAPS was initially "KU5P Generic Tester"; some paths/docs still use that name (renaming in progress). The PCB SH100008192 is named "KU5P_Generic_Tester" and the Perforce stream follows that name.
SharePoint (work-in-progress specs/presentations):
BOA > Documents > Board Development > Generic_Tester > **SH100008193_MicroHAPS**. Adapter-board info one level up under Tester Adapters.
Empower (production documentation):
- PCBA SH100008193: schematic, Parts List/BOM tab, assembly drawings, pick-and-place data, assembly specification.
- PCB SH100008192: NC drill, Gerber, ODB++, PCB specification.
Perforce (verification scripts & modules):
- Server
p4p-vg01, Port 7004 (US) / 1888 (EU), Depothaps, Stream//haps/KU5P_Generic_Tester_verification/ - Structure:
Common(project-specific modules/config),Imported(modules imported from other streams — incl. the bitfiles underImported/Bitfiles, cf. E-013),step_X(one per hardware-verification-plan step, e.g.step_07_setup_service_port). - Running any script auto-creates
Results(generated data per PCBA serial number, ≥ latest run) andLogs(timestamped log per run). - Example script:
//haps/KU5P_Generic_Tester_verification/example.py— connects to the Service Port, scans the I2C bus, turns on the on-board power supplies, then toggles LEDs (matches the bring-up sequence in E-015).
Working OpenOCD configuration to expose the MicroHAPS FT4232H Channel A (JTAG) as a Xilinx Virtual Cable (XVC) server on port 2542, so Vivado can attach to the KU5P JTAG via OpenOCD (an alternative to the native FTDI / hw_server path used by the step scripts).
xvc_server.cfg:
# Enable the standard FTDI driver loop
adapter driver ftdi
# Select JTAG transport layer
transport select jtag
# Standard FTDI Vendor ID and Product ID
ftdi vid_pid 0x0403 0x6011
# CRITICAL: Force Channel 0 to lock onto ADBUS (Channel A)
ftdi channel 0
# Pin layout mask for FT4232HL lower 8 bits (0b00001011)
# Pin 0 (TCK), Pin 1 (TDI), Pin 3 (TMS) set as Outputs. Pin 2 (TDO) as Input.
ftdi layout_init 0x00 0x0b
# Lower the JTAG speed to 1000 kHz to avoid high-speed noise while testing
adapter speed 1000
# Open the XVC loop for Vivado on port 2542
xvc_port 2542
# Launch the hardware sequence
init
Notes / how it maps to the board:
ftdi vid_pid 0x0403 0x6011= FT4232H (FTDI VID 0x0403, PID 0x6011).ftdi channel 0= Interface A / ADBUS = the JTAG port. This matches the Service-Port alias:A0=TCK, A1=TDI, A2=TDO, A3=TMS(E-017 /..._Service_Port_Alias_Rev0.csv).layout_init 0x00 0x0b→ direction mask0b1011: TCK(0)/TDI(1)/TMS(3) outputs, TDO(2) input; all initial values 0.adapter speed 1000= 1 MHz TCK (deliberately slow for noise-free testing).xvc_port 2542= Vivado connects via Hardware Manager → "Add Xilinx Virtual Cable (XVC)" atlocalhost:2542.
⚠ Caution — JTAG buffer enable: the alias lists PORT_A_PIN_05 = JTAG_FTDI_EN_N ("FTDI JTAG buffer enable, unreachable when using Vivado"). This OpenOCD config drives only the lower nibble (A0–A3) and does not assert A5; if the on-board JTAG buffer is gated by JTAG_FTDI_EN_N, verify it is enabled (pull/strap or extend layout_init/layout_signal) or the chain may not be visible. Also note the driver-arbitration point — OpenOCD (libusb) and NI-VISA/D2XX cannot both claim Interface A at once.
Scaffolded the Accordion extension for the E-020 design at C:\dev\source\accordionq2\Extensions\MicroHapsHandler.
Decisions: vendor the FTD2XX driver into the extension; name MicroHapsHandler; target net10.0 (linux-arm64). References AccordionUno + EsharpDefinitions.NET10 + Synopsys.HciBus.
Created:
MicroHaps.cs— the port facade (IBusHandler): owns one FT4232H, wires the 4 interface drivers, exposes board orchestration.Ports/—XvcServer(A: MPSSE JTAG→XVC :2542),I2cDriver(B: MPSSE I2C, B4 buffer-enable),HciPort(C: UART→Synopsys.HciBus),GpioDriver(D: bit-bang GPIO0..7→bank 86, with the schematic pin map).Board/PowerControl.cs— concrete U15+PU8 enable/disable (the E-015 PMBus sequence).Transport/— vendored FTD2XX driver (Native/ P/Invoke + Driver/ + Ftdi.cs + Uart.cs).README.md+Config/README.md.
Status: SKELETON — does not build yet. Remaining work:
- Migrate vendored
Transport/Ftdi.cs+Uart.csfrom net6/old EsharpDefinitions → EsharpDefinitions.NET10 interface surfaces. - Implement MPSSE sequencing on
SetBitMode: I2C (B), JTAG/XVC (A), bit-bang (D). UART (C) already present. - Wire the
MicroHapsctor (open FT4232H by description, bind A/B/C/D). - HCI via
Synopsys.HciBus.ComHandlerover interface C. - Add project to the solution.
IP note: the Synopsys config data (alias/clkgen/psm/mpm) is not copied in — Config/ holds a placeholder; re-express as E#-owned config from the schematic, or import with IP clearance. Supersedes E-020 "Next step".
Progress on the MicroHapsHandler extension (follows E-021):
Transport migrated to EsharpDefinitions.NET10 — the only real change was IBusHandler moving to EsharpDefinitions.Interfaces.Devices (added the using in Ftdi.cs + MicroHaps.cs); also inlined a missing Helpers.GetHexBytes (debug formatting) in Uart.cs. The Native/ (FTD2XX_NET P/Invoke) + Driver/ layers ported unchanged.
Port B I2C implemented (Ports/I2cDriver.cs) — full MPSSE bit-banged I2C over the FT4232H low-byte GPIO: idle/start/stop, write-byte (+ACK), read-byte (+ACK/NACK), and Scan() / Write(addr,reg,data) / Read(addr,reg,count). Handles the buffered split-SDA (SDA-out B1 / SDA-in B2) and asserts the B4 buffer-enable. Board/PowerControl (U15 PMBus + PU8, the E-015 sequence) sits on it; MicroHaps.Activate() opens I2C and powers the rails.
Status: the project BUILDS — bin/.../net10.0/linux-arm64/MicroHapsHandler.dll, 0 errors (verified via dotnet build).
⚠ Runtime blocker for the Pi target: the vendored FTD2XX_NET loads the native lib via Windows LoadLibrary("FTD2XX.DLL") — compiles, but will not load on linux-arm64. Needs a cross-platform loader (System.Runtime.InteropServices.NativeLibrary → libftd2xx.so) before it runs on the Raspberry Pi.
Remaining: implement Port A (XVC/JTAG), C (HCI via Synopsys.HciBus), D (GPIO bit-bang); fix the native loader; bench-validate the I2C MPSSE timing and confirm the I2C_FTDI_EN_N polarity (assumed active-low); add the project to the solution.
Resolved the linux-arm64 runtime blocker flagged in E-022. In Transport/Native/FtdiD2XX_NET.cs, replaced the three Windows kernel32 externs (LoadLibrary/GetProcAddress/FreeLibrary) with managed shims of identical signatures backed by System.Runtime.InteropServices.NativeLibrary (TryLoad/TryGetExport/Free). All ~80 GetProcAddress call sites unchanged. LoadLibrary now tries platform candidates: ftd2xx.dll on Windows; ftd2xx / libftd2xx.so / libftd2xx.so.1 on Linux/arm. Still builds green.
Deployment note (Pi): the host needs FTDI's D2XX shared lib (libftd2xx.so for ARM) installed, and the Linux ftdi_sio kernel driver must be detached from the device for MPSSE/D2XX access (the Linux equivalent of the Windows driver-arbitration point).
Wired the native FTDI D2XX lib into the MicroHapsHandler extension so the cross-platform loader (E-023) finds it:
runtimes/<rid>/native/layout;.csprojcopiesruntimes/$(RuntimeIdentifier)/native/*.so*next to the build output (empty-safe, RID-driven).- x64 build in place: FTDI Linux 1.4.34 (x64)
libftd2xx.soplaced inruntimes/linux-x64/native/. Verified:dotnet build -r linux-x64copies it tobin/.../linux-x64/libftd2xx.so. Defaultlinux-arm64build also green. - arm64 pending:
runtimes/linux-arm64/native/has a placeholder; for the Raspberry Pi target download the FTDI 1.4.34 ARMv8 build and droplibftd2xx.sothere. runtimes/README.mddocuments the matrix + Linux setup (install/ldconfig; detachftdi_siofrom the MPSSE interfaces A/B/D; udev rule for FTDI VID 0x0403).
⚠ Open decision (ties to E-008 host PC vs Raspberry Pi): the project RID is linux-arm64, but the downloaded build is x64. Resolve the actual MicroHAPS host arch:
- x86_64 Linux (test PC / dev box) → set
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>(x64 .so already in place), or - Raspberry Pi 64-bit → keep
linux-arm64+ add the ARMv8 .so.
Clarification underpinning the 4-driver design (E-020):
- The FT4232H's four interfaces A/B/C/D are fully independent — separate pins, FIFOs, and USB interfaces; each opened as its own D2XX handle. They run simultaneously: XVC/JTAG (A), I2C (B), UART/HCI (C), GPIO (D) do not block one another. Running the XVC server on A does not hog the chip.
- Only channels A and B have an MPSSE engine on the FT4232H (C/D are UART/bit-bang only). This is exactly why the board puts the two MPSSE functions — JTAG on A, I2C on B — there, UART→HCI on C, and bit-bang GPIO on D. The Synopsys pin allocation is deliberate and matches the chip's capability map.
- Shared resources (non-blocking): (1) one 480 Mbps USB link shared across all four (ample headroom); (2) the single-owner rule is per interface — conflict only arises if two drivers claim the same interface (e.g.
ftdi_sio+ D2XX on A). On the Pi, detachftdi_siofrom A/B/D; C may be D2XX or attyUSB. - Functional caveat: HCI (C) and GPIO (D) live in the FPGA fabric — JTAG reconfig (A) drops them until reload; I2C (B) is board-management (power/clock chips, not in the FPGA) so it's independent and usable before the FPGA is even loaded (needed for the U15/PU8 power-up).
Ports/HciPort.cs implemented — reuses the AGENT-native HCI stack (E-003): builds a concrete UartDevice for FT4232H interface C and drives it through Synopsys.HciBus.ComHandler (IHciBus) with the facade's Ftd2xxDriver.Ftdi as the IBusHandler. Exposes Scan() (→ List<IHciDevice>), SendReceive(string), Reset(), SetMaxBusSpeed(), TreeVisualization. Wired in MicroHaps ctor; builds green.
Config set per E-003 (HCI needs full UART RX/TX/CTS/RTS): RS232 + RTS/CTS flow, CR-terminated frames, default 921600 baud.
TODOs (confirm against board/design):
- The vendored
Uartopens by serial (BySerialNumber), so the Port-C identifier must be the FT4232H interface-C serial (≈<baseSerial>"C"), not the description used for I2C (OpenByDescription). Reconcile serial-vs-description across the drivers. - HCI baud must match the FPGA HCI core (assumed 921600).
- HCI only responds once an HCI FPGA design is loaded (so
Scan()is not part of bare power-upActivate()).
Driver status: A (XVC) stub · B (I2C) done · C (HCI) done · D (GPIO) stub.
Enumerated on the Pi (ls -l /dev/serial/by-id/) for the on-hand MicroHAPS R0 board:
- Manufacturer: Xilinx · Product / D2XX description base:
KU5P Generic Tester Service Port· FTDI serial:H883774· VID:PID0403:6011. - Interface map (bInterfaceNumber → FT4232H channel → our role):
- if00 → A → JTAG/XVC — non-VCP (absent from by-id;
ftdi_siodoes not bind it → free for D2XX/MPSSE). ✓ - if01 → B → I2C (MPSSE) — ttyUSB1
- if02 → C → UART/HCI — ttyUSB2
- if03 → D → GPIO (bit-bang) — ttyUSB3
- if00 → A → JTAG/XVC — non-VCP (absent from by-id;
- D2XX identifiers (channel letter appended): description
"KU5P Generic Tester Service Port {A|B|C|D}"; serial"H883774{A|B|C|D}". ConfirmsI2cDriver(OpenByDescription "… B") targets if01.
ftdi_sio: B/C/D are bound as ttyUSB1/2/3 and must be detached for D2XX (udev rule unbinding ftdi_sio for 0403:6011 + MODE 0666/plugdev). A is already free.
Driver action: standardize all four port drivers on OpenByDescription (stable string) rather than serial, resolving the serial-vs-description TODO from E-027.
Added a standalone console Extensions/MicroHapsHandler.BringUp (net10.0/linux-arm64, apphost microhaps-bringup) to exercise the extension on the Pi without any AccordionUno host. Also added public Diagnostics.ListDevices() (enumerates D2XX devices, no open).
Test flow: (1) enumerate FTDI devices via libftd2xx; (2) open I2C on interface B by description ("… Service Port B"), scan; (3) optionally enable rails (U15+PU8) and re-scan.
Purpose: verify the "try without touching ftdi_sio" path — run as root (sudo) and rely on libftd2xx auto-detaching ftdi_sio on D2XX open. Decision criterion: if I2C opens & scans → no ftdi_sio config needed; if it fails "device busy/not opened" → ftdi_sio still holds B → then blacklist/unbind (E-024/discussion).
Output dir bundles the apphost + all DLLs + the arm64 libftd2xx.so. This is the MS-002 (µHAPS platform smoke test) first run.
Verified on the Pi (agent64) as the accordion user, no sudo:
lsusb -v -d 0403:6011 resolved the string descriptors (iManufacturer=Xilinx, iProduct="KU5P Generic Tester Service Port", iSerial=H883774) with no "Couldn't open device" warning → a non-root libusb open succeeded, which is the access D2XX/libftd2xx requires.
Conclusion: the MicroHapsHandler extension can open the FT4232H without sudo, without a udev permissions rule, and without blacklisting ftdi_sio (the Pi-OS image already grants the device to the session user; libftd2xx auto-detaches ftdi_sio from B/C/D on open using the same usbfs access — no root needed).
Caveat / final proof: lsusb opened the control endpoint but did not claim interface B; the definitive confirmation is the first non-sudo D2XX open of interface B in the running app (the bus that detaches ftdi_sio). Expected to work.
Completed the remaining two interface drivers; the extension now builds with all four ports implemented.
Port D — GpioDriver (FTDI interface D): FT async bit-bang. Open(directionMask), SetDirection, Write(byte), Read() (instantaneous pin state via new FtdiD2XXDriver.GetBitMode() → native GetPinStates), plus SetPin/GetPin. GPIO0..7 → bank-86 F9/F10/G9/G10/G11/H11/H9/J9. Opens by description "… Service Port D".
Port A — XvcServer (FTDI interface A, MPSSE): a TCP Xilinx Virtual Cable server on :2542 for Vivado Hardware Manager. Implements the XVC protocol (getinfo/settck/shift); each shift bit-bangs per-bit TMS/TDI over the MPSSE low byte (A0=TCK, A1=TDI, A2=TDO, A3=TMS; dir 0x0b per E-019) and samples TDO while TCK is high. Start()/Stop() on a background thread. Opens by description "… Service Port A".
Both wired into the MicroHaps facade. Build: succeeded (1 benign warning).
TODOs / bench validation:
- XVC
shiftis correct but bit-bang-slow (fine for IDCODE/boundary-scan/ILA; large bitstream loads want a future MPSSE-clocked path). - Confirm the A5 JTAG buffer-enable behaviour — current dir mask (0x0b) matches the working OpenOCD cfg (E-019) and does not drive A5; verify the chain is visible on hardware.
- Confirm TDO sampling edge and GPIO direction defaults on the bench.
Driver status: A ✅ · B ✅ · C ✅ · D ✅ — feature-complete pending hardware bring-up.
Rewrote MicroHaps as the AGENT-visible Module, following the LedTower/ModuleForwarder pattern (guided by the user).
MicroHaps : Module, IAdditionalModule, IBusHandler— ctor(IBusHandler, IFileLogging, IModuleDiscovery, byte, IModuleSettings).Reset(): clears all channels, power-cycles the board (I2C → U15/PU8 disable→enable, E-015, tolerant of missing HW), then rebuilds the channel set + firesOnChannelsUpdated.- Channels (each tagged with
DeviceNamefor routing): BOARDCONNECTED(bool) +SERIAL(FT4232H serial, e.g. H883774 via D2XX enumeration); POWERENABLE; I2CSCAN/SCANRESULTS; GPIO0..7; JTAGXVC(start/stop the :2542 server).Get/SetValuesroute to the sub-drivers. - I2C via
IBusHandler(per ModuleForwarder):PerformBusTransaction(I2cTransaction)executes Scan/Send/Receive/SendReceive on the MPSSEI2cDriver(added rawWriteRaw/ReadRaw/WriteReadRaw) — so the board's I2C joins the framework bus model and other modules (PmbusEngine, IDPROM Identity) can sit on it. Non-I2C transactions delegate to the vendoredFtdi(HCI UART path). - Registered in
accordionq2/config/modules.config(Name=MicroHAPS, ClassName=MicroHaps, Namespace=MicroHapsHandler, Enabled=false, empty InitialData). Build: succeeded.
Open / next: HCI channel enumeration not yet wired — per guidance "HCI should already handle all the enumerations of channels"; need the existing mechanism that turns IHciDevice/registers into channels. Also: subsystems are routed by DeviceName but not yet formalized as IDevice instances; bench-validate Reset power-cycle + GPIO direction handling.
Per guidance ("clone this whole project, just change the UART target"), copied the full working HciHandler implementation into Extensions/MicroHapsHandler/Hci/ (Hci.cs, HciHandler.cs, HciHelpers.cs, IHciTransaction.cs), namespace → MicroHapsHandler. The Scan→channel-enumeration (Hci.cs ~190-269: register/GPIO/type-specific channels read off the live target HCI image) is kept verbatim.
Only change = the UART target: the original resolves a parent module via UartTransactionPath (native-RPi UART) and forwards transactions via ModuleParent.TransactValue. The clone instead opens the FT4232H Service Port interface C by D2XX description ("KU5P Generic Tester Service Port C") through the vendored Ftd2xxDriver.Ftdi bus handler; PerformBusTransaction runs the UART directly on it. HCI params unchanged: 57600 baud, parity Even, RTS/CTS, term 0x0D.
- Registered as its own module
MicroHAPS-HCI(ClassNameHci, NamespaceMicroHapsHandler, same DLL, Enabled=false) — it owns FTDI interface C;MicroHapsowns A/B/D (+power). Independent interfaces, no contention (E-026). - Removed the now-orphaned
Ports/HciPort.cs(superseded by the clone). - Build: succeeded.
Architecture: MicroHaps (BOARD/POWER/I2C/GPIO/JTAG) + Hci (full HCI channel tree on Port C). Bench-validate the HCI link (57600/Even/RTS-CTS) once an HCI FPGA design is loaded.
The MicroHapsHandler extension now brings the R0 board fully up host-side on agent64 (Raspberry Pi, linux-arm64). Continues from E-033 (HCI merge).
Root-cause fixes that unblocked it
- FTDI D2XX marshalling —
byte[]out-buffers (FT_GetDeviceInfoDetail,FT_Read,FT_GetDeviceInfo) are not copied back throughMarshal.GetDelegateForFunctionPointeron linux-arm64; switched to unmanagedIntPtrbuffers. This was why interface descriptions enumerated empty and I2C/JTAG reads returned nothing (cf E-023). - I2C buffer enable polarity (ADBUS4) — it is ACTIVE-HIGH (
I2C_FTDI_EN, must be driven HIGH). The code assumed active-low and drove it low, so I2C never reached the bus and phantom-ACKed off a floating SDA-in (masking the failure). With this fixed, power control finally reaches U15.I2C.Scannow finds 0x30, 0x4C, 0x50, 0x57, 0x58, 0x5B (power mgr / EEPROM-IDPROM / ADC / clock). - JTAG buffer enable (ADBUS5) —
JTAG_FTDI_EN_Nmust be driven low;XvcServernow holds ADBUS5 low (DIR 0x0b → 0x2b) and board power is ensured before JTAG ops (cf E-015, E-019).
Result
Via the in-module XVC server (FT4232H interface A) the TAP returns the real IDCODE 0x04A62093 = XCKU5P (vendor 0x049), single-device chain. Full stack proven: power → I2C → JTAG buffer → TAP.
Also done
- Merged the cloned
Hcimodule intoMicroHaps(HCI comes up with the board); namespaced HCI/I2C/JTAG channels; added aJtagPortarbiter (interface A: XVC server vs openFPGALoader loader-mode, clean handoff) andJTAG.XVC/JTAG.Scan/JTAG.ScanResultchannels.
Committed in accordionq2 (branch upgrade-to-NET10): 86828d4 (MicroHAPS bring-up), de0a7c0 (deploy-script SSH hardening).
Remaining: see the two action entries — openFPGALoader ADBUS5 buffer-enable, and the ftdi_sio detach install requirement.
Cross-reference — 0x5C/0x64 reconciliation (added 2026-06-08)
Erik's I2C.Scan here found 0x5B (LTC2980 global) but never 0x5C/0x64 (the per-die addresses), even though his fix had the buffer enabled. That left open whether the TCA9803 B-side static V_OL offset is itself marginal for the LTC2980 V_IL (the project-46 / [[E-004]] concern). This is now resolved: Daniel's R0 bench rework (fit U56, remove R558/R559, strap EN→P3V3_G — see [[E-048]] / [[E-049]] / [[E-050]]) produced a full scan including 0x5C and 0x64. So the buffered build does regenerate a clean enough low for the LTC dies — the missing-die symptom on Erik's board was not the buffer offset. Note the EN-polarity fix is now in both places: Erik drives ADBUS4 (I2C_FTDI_EN) high in firmware; the hardware strap holds U56 EN high (R557→P3V3_G).
The Linux kernel ftdi_sio (VCP) driver auto-claims all four FT4232H interfaces (A/B/C/D) at USB enumeration, creating /dev/ttyUSB0..3 and blocking both our D2XX access (MicroHapsHandler) and libftdi (openFPGALoader). They must be detached.
This is separate from the non-root access question in E-030 (which is fine: accordion ∈ plugdev). Detaching ftdi_sio is an additional, required step.
During bring-up (E-034) this was done with a manual, non-persistent unbind — lost on every reboot/USB replug (and an openFPGALoader run can re-trigger it). It must be made persistent in the installation script / boot config.
What to add to the install script
Recommended — udev rule (persistent; handles boot AND hot-replug):
Create /etc/udev/rules.d/99-microhaps-ftdi.rules:
ACTION=="add", SUBSYSTEM=="usb", DRIVER=="ftdi_sio", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", RUN+="/bin/sh -c 'echo -n %k > /sys/bus/usb/drivers/ftdi_sio/unbind'"
then:
sudo udevadm control --reload
This unbinds ftdi_sio from every interface of VID:PID 0403:6011 as it appears. All four must be freed — the merged HCI module uses D2XX on interface C as well, so we do NOT leave C on ftdi_sio.
Alternative — boot-only (simpler, but misses hot-replug): a systemd oneshot / rc.local at boot:
for i in /sys/bus/usb/drivers/ftdi_sio/*:1.*; do
d="/sys/bus/usb/devices/$(basename "$i" | cut -d: -f1)"
[ "$(cat "$d/idVendor" 2>/dev/null)" = "0403" ] && [ "$(cat "$d/idProduct" 2>/dev/null)" = "6011" ] \
&& echo -n "$(basename "$i")" | sudo tee /sys/bus/usb/drivers/ftdi_sio/unbind >/dev/null
done
Also install on the Pi for the JTAG loader path: openFPGALoader (e.g. sudo apt install openfpgaloader, or a source build for a recent version).
Verify after install
ls /sys/bus/usb/drivers/ftdi_sio/ | grep ':1\.' should show no 0403:6011 interfaces, and ls /dev/ttyUSB* should not list the FT4232H ports.
Status update following E-034 (full power→I2C→JTAG bring-up on agent64).
Done since E-034:
- Persistent
ftdi_siodetach (was E-036) — udev rule unbindingftdi_siofrom FT4232H0403:6011is now wired into the install/boot path, so D2XX (MicroHapsHandler) and libftdi (openFPGALoader) reliably claim the interfaces across reboot/replug. Implemented/fixed. - openFPGALoader JTAG path — openFPGALoader installed on the Pi and the ADBUS5 JTAG buffer-enable confirmed for the loader path. Implemented/fixed.
Next: verify the HCI link. The cloned HCI module on FT4232H interface C (57600 baud / Even parity / RTS-CTS, CR-terminated — see E-033) is wired and builds, but has not yet been validated on hardware. It only responds once an HCI FPGA design is loaded. Bench-validate the HCI channel enumeration against a loaded HCI design.
Check on a physical R0 board whether C10, C11, C12, C13 (the JTAG line caps on TCK/TMS/TDI/TDO at U1/U8) are actually populated.
Why it matters: sources disagree.
- PDF schematic: C10–C13 = NM (not mounted).
- ODB++ extract
ku5p_generic_tester_r0_1002(2025-10-02): lists them asCAP_0= populated 10 nF (the design uses a separateCAP_NPpart for genuine no-pops, so this isn't just a placeholder).
If they are physically stuffed, the 10 nF shunt is a second JTAG-speed killer (~650 ns edges → ~1 MHz ceiling) stacked on top of the open-drain TDO buffer issue.
How to apply: visual check + DMM/cap-meter across one of C10–C13. Record result here.
- If populated → depopulate them and re-test; flag the BOM/PDF-vs-ODB mismatch for the next-rev cleanup.
- If NM (empty pads) → confirms the ODB extract is stale on these refs; the open-drain TDO buffer (U9 + R139 10K) remains the sole root cause.
Related: [[microhaps-project]] — see concept E-038 (JTAG signal chain) and E-007 (RC schematic review).
The MicroHapsHandler HCI scan now enumerates the full chain on the R0.0 board (agent64). Complete recipe / root causes, in the order they had to be fixed:
HCI is on FT4232H interface D, not C. R0.0 wires only a 2-pin UART (TX/RX) to the FPGA, which lands on interface D (design log SH100008193 R1.0-012: "Having only a 2-pin UART... forces HCI to be on port D"; R1.0 adds a 4-pin UART on C). The bringup code agrees:
uut_data.py HCI_INIT_INFO com="KU5P Generic Tester Service Port D". The Service Port alias CSV labels C as UART — that's the R1.0 intent, misleading for R0.0. Module config:HciInterface=D(configurable; set "C" for R1.0).Reset the FTDI bit-mode to serial on open. Interface D had been left in async bit-bang mode (by the GPIO driver); FTDI bit-mode is sticky per-interface across opens and survives a service restart. In bit-bang mode
FT_Readreturns continuous PIN-STATE samples (constant byte that tracks power: 0x07 powered / 0x00 off, independent of baud) instead of real RX. Fix:FT_SetBitMode(0x00,0x00)inFtdiD2XXDriver.Open.Framing = 57600, 8 data, 1 stop, parity = ODD, term 0x0D. (Spec §UART says 8N1, but this design/board is empirically 8-O-1 — Daniel confirmed Odd; None gives nothing.)
HW flow control RTS/CTS is REQUIRED. The HCI daisy-chain uses RTS/CTS to stall transmitters (spec). With flow=None, device 0's short reply fit but multi-device relayed replies overran the receiver → dropped bytes → truncated frame / "No CR character found". Setting
flowCtrl=RTS_CTSmade all devices stream cleanly.End-of-chain timeout must propagate as TimeoutException. The scan probes
<n>Quntil a unit doesn't answer;ComHandler.EnumeratecatchesTimeoutExceptionas end-of-chain. Our vendoredFtdi.PerformBusTransactionswas wrapping it in a generic Exception → scan failed on the (expected) last probe. Fix: re-throw TimeoutException unwrapped.Don't reconfigure the port per transaction. The Uart re-applied the FTDI driver timeout every transaction (ComHandler flips it 200/1000 ms); a short write timeout can abort
FT_Writewhile the FPGA legitimately stalls us via CTS. Now configured once at open;Receive()enforces the per-transaction timeout itself; it also waits until it actually dequeues the 0x0D rather than trusting the eager event-char flag.
Result: chain enumerates dev0 UART-up (GeneralTester_UART_US), dev1 GPIO Expander (class 0x44, 34 banks), dev2 Design-ID Query (0x04), dev3 Edge Counter (0x46), dev4 UART-down; dev5 = clean end-of-chain. The HCI GPIO-expander channels surface FPGA GPIO. On-board QSFP LEDs: QSFP_0_LED bank 0x20 pin 7, QSFP_1_LED bank 0x21 pin 4 (HciGpioExpander alias).
Persisted config (modules.config InitialData): HciInterface=D, baudRate=57600, parity=Odd, flowCtrl=RTS_CTS, term 0x0D. JTAG side: patched openFPGALoader (microHAPS cable holds ADBUS5/JTAG_FTDI_EN_N low) at 1 MHz. Commits on branch upgrade-to-NET10.
Comprehensive I2C walkthrough of MicroHAPS R0 (PCBA SH100008193-R0.0). Evidence: full-board ODB++ netlist (microhaps_r0_netlist.json), BOM_SH100008193_R0.csv (values + NM/[Disabled]), schematic SH100008193_R0.0_MicroHAPS_Schematic.pdf (sheets 4/6/7/10/11/25/27), an FTDI live bus scan, a DC1613A scan (FTDI unplugged), Erik's p4v bring-up code, and the SH100008193_R1.0 DesignLog. Connectivity stored as netlist id 17, rev R0-I2C (please_netlist_search protocol=i2c).
⚠️ The JTAG-scoped
R0netlist and the reduced staged JSON drop most power/GND pads — pull-up rails & NM status were re-derived from the BOM.
Architecture — two independent I2C buses
Bus A — board management (I2C_SCL0/SDA0), mastered by FTDI FT4232H (U10) via MPSSE. Bus B — FPGA mux trunk (MUX_I2C, FPGA U1 J10/J11) → PCA9547 U47 (0x70) → 8 isolated channels: HT3_0..3 (J16/J18/J17/J19), QSFP_0/1 (J10/J8), MGB_0/1 (via PCA9306 to J15/J13).
Address map — RESOLVED & confirmed
Bus A: | Addr | Device | Ref | Notes | |---|---|---|---| | 0x30 | PMIC MPM3695 | PU8 | + IDPROM hidden 0x30 WP; collide fixed R1 (R1.0-006 → 0x31) | | 0x4C | Temp TMP441 | U3 | | | 0x50 | EEPROM/IDPROM AT24MAC402 | U4 | EUI-48 part | | 0x58 | IDPROM MAC/serial block | U4 | same chip as 0x50 — AT24MAC402 EUI-48 + 128-bit-serial read-only zone (1011_xxx). Resolved (was "unidentified"; not the LTC2980) | | 0x5B | LTC2980 global | U15 | | | 0x5C | LTC2980 die A | U15 | confirmed via DC1613A; ASEL die-A = L/L | | 0x64 | LTC2980 die B | U15 | confirmed via DC1613A; ASEL die-B = H/H | | 0x57 | Fan MAX31760 | U55 | | | 0x74 | Si5340 | U6 | on FET branch — see E-045 |
Bus B: 0x68 MCP3424 (U16), 0x70 PCA9547 mux (U47). Downstream (mux-isolated): 0x60 MGB clock src (U49/U53), 0x50 MGB EEPROMs (U28/U21).
LTC2980 addressing (closed): global 0x5B + die A 0x5C + die B 0x64 — confirmed by DC1613A scan {4C,50,57,5B,5C,64} (FTDI off) and Erik's init_power_control (psm A=0x5C, B=0x64). ASEL straps physically verified on-board: die-A R331/R332 fitted (L/L), die-B R321/R322 fitted (H/H), pull-downs empty — decode to 0x5C/0x64. The earlier "0x5C/0x64 no-response" was NOT an address/strap error — it's the FTDI V_OL blocking issue [[E-048]].
⚠️ Critical — BLOCKING: FTDI can't control the LTC2980 [[E-048]]
The FTDI bus low is V_OL ≈ 0.4 V (weak FT4232H I/O into the strong 1k pull-up, unbuffered — [[E-044]]); the LTC2980 has a tight V_IL and rejects it, so the FTDI never reaches 0x5C/0x64. A DC1613A (V_OL ≈ 0.2 V) reaches them, but only with the FTDI unplugged (a powered FTDI jams the shared bus). ⇒ per-rail power-system control via the service port is non-functional on stock R0. Fix: bus pull-up 1k→4.7k (or fit U56). Full detail + evidence in E-048.
Signal path on Bus A — buffers bypassed, not used
Both TCA9803 repeaters are NM (BOM line 132, U5+U56 "Disabled"). FTDI side is bypassed by 0 Ω: U10 → R143/R144/R145 (0 Ω) → FTDI_I2C → R558/R559 (0 Ω) → I2C_SCL0/SDA0 (no R58/R59 exists). FPGA side is not bridged in R0 (U5 NM + R64/R65 NM; U5's enable jumper-gated by J3) — see E-043. This hard-wired, unbuffered FTDI is the basis of the V_OL/contention problem (E-048).
Check 1 — Pull-ups
- Mux channels (Bus B): all 8 = 4.7k → P3V3_VCCO, populated. ✅
- Bus A: nominal pulls NM (
R69/R701k; LTC2980R265/268/269/27110k); effective =R555/R5561k → P3V3_G (~3.3 mA sink → marginal V_OL, root of E-048). See E-044 (also raised in R0 review, log R0.0-031). - MGB 1.8V: hi 4.7k→P3V3_VCCO, lo 4k75→P1V8_MGB2_OUT;
_INpulls NM. ✅
Check 2 — Voltage domains
Uniform 3.3V on Bus A / mux trunk / channels. Crossings: PCA9306 U54/U50 3.3↔1.8V (proper ✅; R1 → TCA9803, log R1.0-016/022). Si5340 FET translator Q22/Q23 — ⚠️ DEFECT (E-045): source on 3.3V main side + CLKA pull-ups to 3.3V ⇒ Si5340 ESD diode back-clamps the whole bus to ~3.0V (R1 removes passFETs, log R1.0-008). No 5V on I²C.
Check 3 — SCL/SDA orientation
SCL↔SCL / SDA↔SDA holds through every device/connector pin. FTDI IN_SDA/OUT_SDA = standard MPSSE (DO+DI tied), not a swap. ✅ Spot-check off-board pins on HT3/QSFP/MGB connectors.
Check 4 — Addresses
See the map above — fully resolved and measured-confirmed. 0x30 conflict (PU8 vs IDPROM hidden WP, log R1.0-006, fixed R1→0x31). MGB module EEPROMs both 0x50 on separate mux channels → isolated. ✅ No conflicts.
Design-log reconciliation (SH100008193 R0→R1)
- E-044 (pull-ups DNI) = R0.0-031 · U56 removal = R1.0-001/002 · E-043 (FPGA/U5) = R1.0-018 · E-045 (Q22/Q23 passFETs) = R1.0-008 (removed R1; root cause only in E-045) · 0x30 conflict = R1.0-006. The log mentions no LTC2980 I2C address (only 0x30/0x31 and 0x60 appear anywhere).
NM / unpopulated (per BOM) — not live
U5 & U56; R69/R70; R265/R268/R269/R271; R64/R65; R119/R120; MGB _IN R421/R428/R406/R408; QSFP alt R376/R377/R392/R393. (FTDI bypass R558/R559 + R143/R144/R145 mounted 0 Ω; CLKA FET Q22/Q23 + R551/R552/R553 mounted.)
Findings (linked)
- FPGA↔mgmt-bus bridge (U5, jumper J3) unpopulated in R0 — E-043.
- Bus A unbuffered on a single 1k pull-up to P3V3_G — E-044.
- Si5340 CLKA FET translator Q22/Q23 wired backwards (back-clamps bus to ~3.0V) — E-045.
- 0x30 address conflict (PU8 vs IDPROM WP) — log R1.0-006, fixed R1.
- BLOCKING: FTDI cannot control the LTC2980 power manager (V_OL 0.4V > LTC2980 V_IL; FTDI↔dongle mutually exclusive) — E-048.
Resolved (not defects)
- HT3_1 / QSFP_0 "missing channel pull-up" = reduced-netlist extraction artifact; all 8 channels populated.
- "Signal passes despite disabled U56" = bypassed by mounted 0 Ω R558/R559 (no R58/R59 exists).
- 0x58 = IDPROM MAC block (U4); 0x5C/0x64 = LTC2980 dies — address map fully closed & confirmed.
- LTC2980 ASEL straps physically verified correct (A=L/L, B=H/H).
Correction/refinement of the R0 I2C walkthrough (see [[E-042]]). Supersedes the earlier "permanent isolation" wording — the FPGA↔management-bus connection is a designed, jumper-gated bridge, currently unpopulated.
Mechanism (design intent): The FPGA management-bus I2C port (U1 K9/K10 → FPGA_I2C_SCL0_R/SDA0_R) is bridged onto the board-management bus I2C_SCL0/SDA0 by a TCA9803 I2C repeater U5 (A-side pins 2/3 = FPGA, B-side pins 6/7 = mgmt bus). U5's enable I2C_0_EN_R (pin 5) is gated by header J3 with default-state resistor R55 (4k64); TCA9803 EN is active-high:
- J3 not installed → R55 holds EN high → U5 enabled → FPGA driven across onto the mgmt bus.
- J3 installed → EN pulled low → U5 disabled → FPGA isolated from the mgmt bus.
(Confirmed by board owner. The reduced netlist dropped the far ends of R55/J3, but the polarity matches the "J3 disables the cross-drive" behaviour.) This mirrors the FTDI side, where repeater U56 carries the equivalent role (there held disabled via I2C_FTDI_EN_N low + bypassed by 0Ω R558/R559).
As-built R0 (per BOM): U5 is NM — it shares BOM line item 132 with U56, both flagged "Disabled". The alternative direct 0Ω bypass R64/R65 is also NM. So in the R0 build neither FPGA→mgmt-bus path is fitted, and J3 has nothing to gate. Net result as-built: the FPGA reaches only the mux trunk (MUX_I2C → PCA9547 U47 + 8 channels + MCP3424 U16), not the mgmt-bus devices (EEPROM/PMIC/temp/fan/LTC2980).
This is a populate-time option, not a hard isolation. To give the FPGA management-bus access on a board: fit U5 (then J3 selects enable), or stuff R64/R65 (0Ω, unconditional bridge — but then FTDI + FPGA share the bus unbuffered, multi-master). Contrast the FTDI side, where the equivalent bypass R558/R559 is fitted, making FTDI the live mgmt-bus master.
Why it matters: If a use-case needs the FPGA to read mgmt-bus telemetry (power/thermal) without the host, that requires fitting U5 (J3 open) — it is not present on stock R0.
Next step: Confirm intended config with Synopsys — is FTDI-only management deliberate for R0, and is U5+J3 the sanctioned mechanism to add FPGA access? Confirm the R55/J3 default state (stock = J3 off ⇒ U5 would be enabled if fitted) and the R55→3V3 pull on R1 schematic SH100008193_R1.0.
Observation from the R0 I2C walkthrough (see [[E-042]]). As-built record, not asserted as a defect.
What: On the management bus I2C_SCL0/SDA0 the intended pull-ups are all unpopulated per BOM:
- trunk
R69/R70(1k → P3V3_STBY) →[Disabled] - LTC2980 local pull-ups
R269/R271(A) andR265/R268(B), 10k → VDD33IN →[Disabled]
The TCA9803 buffer U56 is also NM and bypassed by 0Ω R558/R559, so the only live pull-up on the whole bus is R555/R556 (1k → P3V3_G) on the FTDI segment. Net effect:
- Pull-up rail = P3V3_G (the FTDI/USB-area 3.3V). The bus loses its pull-up if P3V3_G is down even when P3V3_STBY/board are up. Confirm P3V3_G sequencing vs the devices that must be reachable.
- Drive strength: ~3.3V/1k ≈ 3.3 mA sink, at/above the 3 mA I²C I_OL budget. Verify the weakest open-drain driver on the bus (EEPROM/TMP441/LTC2980/MAX31760/PMIC) meets V_OL at 3.3 mA, or consider moving to the nominal pull-up scheme.
- Unbuffered: with U5/U56 NM the bus has no buffering/level-isolation; total bus capacitance (all mgmt devices + FET-isolated CLKA branch + connector stubs) sits on one segment — check rise time at target SCL frequency.
How to apply / next step: Confirm intended pull-up scheme with Synopsys; if the nominal R69/R70 (and/or LTC2980) pulls were meant to be stuffed, flag the BOM. Re-verify on R1.
Per-buffer pull-up check for every I2C buffer/translator on R0: are there pull-ups on both sides, each on the correct rail for that side's voltage? Derived from netlist R0-I2C (id 17) + BOM. Companion to [[E-042]].
| Buffer / translator | Side A | A pull-up | A rail | Side B | B pull-up | B rail | Verdict |
|---|---|---|---|---|---|---|---|
| PCA9306 U54 (MGB_0) | high (mux ch6) | R483/R482 4.7k | P3V3_VCCO 3.3V ✓ | low (MGB2A_1) | R430/R429 4k75 | P1V8_MGB2_OUT 1.8V ✓ | ✅ both sides, correct rails |
| PCA9306 U50 (MGB_1) | high (mux ch7) | R485/R484 4.7k | P3V3_VCCO 3.3V ✓ | low (MGB2A_2) | R404/R403 4k75 | P1V8_MGB2_OUT 1.8V ✓ | ✅ both sides, correct rails |
| TCA9803 U56 (FTDI) — NM | FTDI | R555/R556 1k | P3V3_G 3.3V ✓ | main bus | R69/R70 — NM | (P3V3_STBY) | ⚠️ B-side pull-up unpopulated |
| TCA9803 U5 (FPGA) — NM | FPGA | R67/R68 1k | P3V3_VCCO 3.3V ✓ | main bus | R69/R70 — NM | (P3V3_STBY) | ⚠️ B-side pull-up unpopulated |
| FET Q22/Q23 (CLKA) | main 3V3 | R555/R556 (trunk) | 3.3V ✓ | CLKA (Si5340) | R551/R553 1k | P3V3_CLK 3.3V | ❌ wrong rail — should be 1.8V |
Reading
- PCA9306 MGB translators (U54/U50): correct. Pull-ups present on both sides, each tied to the matching rail (3.3V high / 1.8V low). PCA9306 VREF pins (
U54.2/U50.2) correctly biased to P1V8_VCCO (1.8V), the low-side reference. ✅ - TCA9803 buffers (U5/U56): shared B-side = the main bus, whose pull-ups
R69/R70are NM. Each buffer's A-side (FTDI/FPGA) is properly pulled, but the main-bus side has no dedicated pull-up. As-built this is moot (both buffers NM; FTDI 0Ω-bypassed so the A-side 1k reaches across — see [[E-044]]), but if a TCA9803 is ever populated here the main-bus side would come up with no pull-up of its own → flag on the BOM/assembly. - FET Q22/Q23 (CLKA): the only outright-wrong rail — CLKA-side pull-up (
R551/R553) goes to 3.3V (P3V3_CLK) instead of 1.8V, on top of the reversed source/drain. Tracked as defect [[E-045]].
Summary
Pull-ups exist on both sides of every buffer/translator. Rails are correct everywhere except the CLKA FET branch (wrong rail, [[E-045]]), with the caveat that the shared TCA9803 B-side (main-bus) pull-up is NM ([[E-044]]) — only an issue if a TCA9803 is fitted.
Bench rework to test the [[E-048]] / [[E-049]] fix — build the FTDI I2C buffer per the schematic AND fix its enable strap. Daniel has TCA9803DGKT in stock; planned ~2026-06-08.
Rework steps (do all three)
- Fit
U56= TCA9803DGKT (FTDI I2C buffer, sheet 8). VSSOP-8. - REMOVE
R558andR559(the 0Ω bypass). ⚠️ Critical: if you fit U56 but leave R558/R559 in, the 0Ω bypass shorts across the buffer (A↔B) and it does nothing. Lift them. (0402, top side, on FTDI_I2C_SCL/SDA → I2C_SCL0/SDA0 near U56.) - Fix the EN strap (the real original bug — see [[E-049]]):
U56EN (pin 5, netI2C_FTDI_EN_N) is active-HIGH, butR557(4.75k) pulls it to GND → buffer DISABLED by default (the_Nname is a mislabel; same polarity bug Erik hit in firmware, [[E-022]]/E-023). MoveR557from GND to P3V3_G (turn it into a pull-up → EN defaults HIGH/enabled). Keep it a resistor pull-up so the FTDI GPIO (U10.30) can still override; or bodgeU56.5→U56.1(VCCA) for a hard enable if FTDI EN control isn't needed. (If using Erik's fixed firmware that already drives EN high, step 3 is optional — but the hardware strap removes the firmware dependency.)
Expected result / what to check
- Scan the bus over the FTDI and look specifically for 0x5C and 0x64 (LTC2980 dies) — not just "I2C works."
- 0x5C/0x64 ACK → buffer regenerates a clean low; E-048 resolved by the schematic-correct buffered build (E-049 root cause confirmed).
- Only 0x5B works, still no 0x5C/0x64 → matches Erik's enabled-buffer board → the TCA9803 B-side static V_OL offset itself exceeds the LTC2980 V_IL (project-46 / E-004 concern). Then weaken bus pull-up
R555/R5561k → ~4.7k and/or scope LTC SDA/SCL idle-low. - Re-confirm FTDI↔DC1613A coexistence: with the buffer in + EN gating, a powered-idle FTDI should no longer jam the bus.
Capture
Record scope V_OL + FTDI scan (before/after) and update [[E-048]] / [[E-049]] with the outcome.
Design concern raised by Daniel while debugging the LTC2980 NACK (sibling blocking issue).
The flaw
Static-offset I2C repeaters (TCA980x / PCA9517 family) cannot share a bus segment. Each buffer's driven low sits at its ~0.5 V static offset; a second repeater on the same net reads that offset-low as a real bus low and re-drives, so the two latch each other low (bus stuck) — or, at best, their offsets stack and destroy V_OL margin for downstream slaves. The only safe way to put two such buffers on one segment is to orchestrate their enables so exactly one drives at a time (mux-like), which this design does not do.
Where it occurs
- The design ties U56 (FTDI I2C buffer) and U5 (FPGA↔main bridge buffer) — both TCA9803 — onto the same management-bus lines, with independent/static enables.
- R0 (this board): masked because U5 is NM (confirmed), so only U56 drives. Latent, not active.
- R1 (project 46): both U60 (FTDI buffer) and U5 are fitted & enabled (R1.0-002 / R1.0-008). The flaw becomes real on R1 unless the enables are sequenced or one buffer is removed.
Why it matters here
Even in the R0 single-buffer case, the offset-stacking principle underlines the [[E-049]] / E-004 V_OL-margin risk that is the lead suspect for the LTC2980 command-NACK. With two buffers active (R1) the margin and latch-up risk are worse.
Recommended action
- Confirm the R1 netlist: do U60 and U5 B-sides land on the same segment, and can both be enabled simultaneously? If so, this is an R1 design issue — gate the enables (only one active per access) or drop one buffer.
- TODO: mirror this note into project 46 (R1) as a design-rule / blocking concern; cross-reference there.
Sibling: BLOCKING LTC2980 command-NACK issue. Related: [[E-049]], project-46 / E-004.
ODB++ shows U5 (TCA9803) POPULATED with its B-side ports (pins 6/7 = SDAB/SCLB) on I2C_SDA0 / I2C_SCL0 alongside U56 — two static-offset I2C repeaters contending on one bus segment (the E-053 flaw). E-053 assumes U5 is NM on R0, which would mask this. The as-built connectivity contradicts that assumption. Verify U5's actual mount status on the physical R0 board: if U5 is fitted, the dual-repeater contention is LIVE on R0 (not just R1), changing E-053's 'latent, not active' disposition to an active defect; if U5 is truly NM, the ODB++ extract is stale on U5 — a THIRD BOM↔ODB discrepancy after E-039 (C10–C13 NM-vs-ODB) and E-049 (U56 populate/DNI swap), warranting a BOM-generation audit.
Receipts: ["net:I2C_SDA0", "net:I2C_SCL0", "component:U5", "component:U56", "E-053", "E-039", "E-049"]
— odb board 1, concern CON-001
Probe's connectivity review independently corroborates E-038 (open-drain TDO buffer = JTAG-speed limiter). On JTAG_TDO_3V3: U9 = SN74AUP1G07DBVR (a single-gate OPEN-DRAIN buffer) drives the net from the FPGA's SFPGA_JTAG_TDO; R139 (10K) pulls it up; U48 (SN3257) is the source-select mux. Open-drain output + 10K pull-up on an otherwise push-pull/actively-driven JTAG bus = the slow-rise TDO speed limiter E-038 describes (engine finding: OpenDrainBusContention, error, on JTAG_TDO_3V3, pin U9.4). Known/intended design — linked here to the existing E-038 worry rather than re-raised as a new concern. Carry into the R1 re-check (project 46): confirm whether R1 keeps the open-drain '07 + 10K on TDO or moves to a push-pull buffer.
Subject: net:JTAG_TDO_3V3
— odb board 1 (comment)
Micro-HAPS R0 — Probe review triage of the WARNING-severity findings (the 2 errors are disposed separately: CON-001 = I2C buffer contention / U5 BOM↔ODB; comment on JTAG_TDO_3V3 = open-drain TDO ↔ E-038).
I2cPullupMissing (25) — split by topology: • BOUNDARY (off-board): HT3_0/1/2/3_I2C_* and MGB_0/1_I2C_* leave the board through the HT3/MGB daughter-card connectors (e.g. HT3_0_I2C_SCL → J16, ASP-199280 Samtec array). Their SCL/SDA pull-ups belong on the connected adapter/daughter card, not the motherboard — not an on-board defect. ACTION: confirm each adapter (HT3→HC3/HT4, MGB2A→NVAM) provides pull-ups. • ON-BOARD, verify: the management-bus segments (MUX_I2C_, FTDI_I2C_, LTC2980A/B_, FAN_) should each carry a local pull-up pair — verify (some may be served via the trunk/mux). NOTE: LTC2980A/B_SCL/SDA pull-up strength ties to the E-048/E-049 LTC2980-NACK V_OL history; confirm the value alongside that rework.
SinglePointNet (14) — BOUNDARY/expected: HT3_*_B12/C12/B13/C13 and A13/D13 are connector ball-stubs whose other end lands on the off-board daughter card; VRP/VRN are the ADC reference taps (single-point by design). No defect.
ModelPinmapConflict (U1 ×2) — DATA-QUALITY, board is fine: the imported XCKU5P model places TCK@C1 / TMS@C2, but the board correctly has GND on those balls (FFVB676). The engine quarantined the wrong model facts. ACTION: fix the KU5P pin-model source for this package; no board change.
CrystalLoadCaps (Y1) — VERIFY: Y1 (CLKA, 50 MHz) has no discrete load caps on CLKA_XA/XB. Likely the Si5340A driver integrates them — confirm against its crystal-interface datasheet; if not, add load caps or the oscillator may not start.
PartLifecycle (PU6) — SOURCING: PU6 is vendor-flagged 'Not For New Designs' (NRND). Longevity risk for production; evaluate a replacement (Trace/BOM owns the decision).
Subject: component:U1
— odb board 1 (comment)
Design Rule Status
■ No violations ■ Warning ■ Error ■ Waived