Repository navigation
E2: TRI-NET node over UDP on the AX7203 (Ethernet job link instead of UART) #8327
Description
Refs #6655 (Verified Compute EPIC). Follows E1, the Ethernet beacon (#7788, PR #7802).
Goal
Run the TRI-NET MAC32 node on the ALINX AX7203 over its Ethernet port instead of the CP2102N UART: a host on the LAN sends TRI-NET requests in UDP datagrams, the board answers each with a keyed receipt, and the existing receipt checks accept them unchanged. Only the transport changes; the 24-byte request, the 19-byte v2 response and the SipHash-2-4 tag stay exactly as gHashTag/trinity-fpga src/trinet/protocol.zig defines them.
Where we are
- E1 works on the bench board.
specs/fpga/eth_beacon.t27(PR fpga: the bench board is an ALINX AX7203, and a t27 Ethernet beacon for it (Closes #7788) #7802) was rebuilt from master95ae4bcd6forxc7a200tfbg484-2with the open flow (yosys 0.69, nextpnr-xilinx 0.9.7, prjxray-db a90f27c1; post-route 214 MHz against 125 MHz) and loaded into SRAM of the AX7203 with DNA0x00389c0c2d85e85c. On 2026-10-09 a Mac on the same LAN over Wi-Fi received 149 of 176T27Edatagrams from 192.168.1.227:27027 in 30 s (losses are Wi-Fi broadcast, not the board). PHY link LED on. - The UART transport is the bottleneck and the fragile part. The CP2102N under macOS 26.7.1 (
AppleUSBSLCOM) refused everytcsetattrwithEINVALthree times on 2026-10-09 until the cable was replugged (log:Failed to get modem status,Failed to get current flow control settings). The transport ceiling is ~4,770 jobs/s at 1,144,744 baud (trinity-fpga/docs/TRI_NET_HANDOFF.md), while the cell is idle for all but ~30 of ~200 clocks per job. - The plan already exists in
trinity-fpga/conformance/NODE_ETHERNET_PLAN.md: keep the frames, carry them in UDP. Derived ceilings: 100BASE-TX ~133k jobs/s (1 job per datagram), 1000BASE-T ~5M jobs/s (60 jobs per datagram). - Reference RTL exists but is foreign.
trinity-fpga/fpga/portable/trinet_node_core.vandfpga/openxc7-synth/trinet_siphash24.vare Verilog. Per the own-language rule the logic here is written as.t27specs; the Verilog is a cross-check, not an import. - Open risk: RGMII receive at 1000 Mb/s.
specs/fpga/rgmii_sniff.t27samples RXD on the rising edge only because the open-flow IDDR is half-dead (openXC7#114). Full-rate receive needs both edges. Two candidates, to be decided on silicon in E2d: fabric flip-flops on both RXC edges, or forcing 100 Mb/s through MDIO (at 10/100 both edges carry the same nibble).
Sub-tasks
- E2a
specs/fpga/eth_rx.t27: byte-stream receive path. Preamble and SFD, destination MAC (ours02:27:00:00:00:01or broadcast), EtherType 0x0800, IPv4 (IHL 5, protocol 17, destination 192.168.1.227 or the subnet broadcast), UDP destination port 27028, CRC-32 FCS check, payload bytes out, source MAC/IP/port latched for the reply, counters for accepted and dropped frames. Pure logic, tested in the spec. - E2b
specs/fpga/trinet_node.t27: node core. Request parse (magicAA 55), MAC32 over 32 trits, SipHash-2-4 over the 26-byte preimage,setkeywrite-once with a signed acknowledgement,NO_KEYbefore a key is installed, v2 response. - E2c
specs/fpga/eth_tx_udp.t27: reply datagram builder generalised fromEthBeacon. Unicast to the requester's latched MAC/IP/port, so no ARP is needed for the reply. - E2d board integration on the AX7203: receive capture (decide between the two candidates above), top wrapper (owner-approved exception list), host harness, measurement.
Rules for every agent on this epic
- Specs first. Logic lives in
.t27; hand-written Verilog only for primitives and wiring, and only on the owner-approved exception list. - Do not change the TRI-NET wire format. Bit-exactness against
protocol.zigis the acceptance test for E2b. - SRAM only on the bench board. No flash, eFUSE or BBRAM writes without an explicit owner yes. Take the board lock
/private/tmp/claude-501/ax7203-board.lockbefore any JTAG or UART access on the bench Mac. - Keys never enter git, issues or logs. Only the
.pub/node id is public. - The board has no authentication: LAN only, no port forwarding.
Boundary
- New:
specs/fpga/eth_rx.t27,specs/fpga/trinet_node.t27,specs/fpga/eth_tx_udp.t27, their seals under.trinity/seals/, a top wrapper and XDC underfpga/verilog/(E2d only), a dated section infpga/HARDWARE_SSOT.md. - Out of bounds:
specs/fpga/eth_beacon.t27andrgmii_sniff.t27stay as they are (reuse by copy of idioms, not by edit); no compiler changes; no changes to the TRI-NET protocol or totrinity-fpga.
User Scenarios & Testing
- The operator loads the node bitstream into SRAM, installs a key with
setkeyover UDP and gets a signed acknowledgement. - The host sends N MAC32 requests in UDP datagrams to 192.168.1.227:27028; every answer carries the right dot product and a tag that verifies under the node key.
- A frame with a bad FCS, a wrong MAC, a wrong IP or a wrong port is dropped and counted, never answered.
- Before a key is installed the node answers
NO_KEYwith a real dot product.
Requirements
- R1. E2a accepts exactly the frames listed above and drops everything else; tested by spec tests with hand-built frames, including a good frame, one per drop reason, broadcast, and a runt.
- R2. E2b output equals
protocol.zigencodeResponseV2byte for byte for every vector in its test set (MAC32 corners, random operands, setkey, NO_KEY). - R3. E2c output frames carry a correct FCS, IPv4 checksum and UDP header (spec tests recompute them; the OS accepting the frames is the silicon check).
- R4. Every spec passes
t27cparse, typecheck and tests, and is sealed with the compiler built from the PR tree.
Success Criteria
- E2a, E2b, E2c merged, each with
Closes #N, green required checks, and a seal. - On the bench AX7203 (DNA
0x00389c0c2d85e85c):setkeyacknowledged, then 1000 MAC32 requests over UDP from a wired host give 1000/1000 correct dot products and at least 990/1000 receipts that verify under the node key, with zero wrong answers. - A measured jobs/s figure over UDP, counted on verified receipts only, recorded in
fpga/HARDWARE_SSOT.mdwith the board, the link speed and the date.
Requirements
FR-001: The eth_rx.t27 spec MUST accept exactly the frames defined in the issue (destination MAC 02:27:00:00:00:01 or broadcast, EtherType 0x0800, IPv4 with IHL 5, protocol 17, destination 192.168.1.227 or subnet broadcast, UDP destination port 27028, valid CRC-32 FCS) and MUST drop all other frames with per-reason counters.
FR-002: The eth_rx.t27 spec MUST output payload bytes and MUST latch the source MAC, IP, and port for the reply path.
FR-003: The trinet_node.t27 spec MUST parse requests with magic AA 55, compute MAC32 over 32 trits, compute SipHash-2-4 over the 26-byte preimage, handle setkey write-once with signed acknowledgement, return NO_KEY before a key is installed, and produce the v2 response format.
FR-004: The trinet_node.t27 spec output MUST equal protocol.zig encodeResponseV2 byte for byte for every vector in its test set (MAC32 corners, random operands, setkey, NO_KEY).
FR-005: The eth_tx_udp.t27 spec MUST build reply datagrams unicast to the latched requester MAC/IP/port with correct FCS, IPv4 checksum, and UDP header.
FR-006: Every new spec (eth_rx.t27, trinet_node.t27, eth_tx_udp.t27) MUST pass t27c parse, typecheck, and tests, and MUST be sealed with the compiler built from the PR tree.
FR-007: The implementation MUST NOT change the TRI-NET wire format (24-byte request, 19-byte v2 response, SipHash-2-4 tag) as defined in gHashTag/trinity-fpga src/trinet/protocol.zig.
FR-008: The implementation MUST use only SRAM on the bench board; no flash, eFUSE, or BBRAM writes without explicit owner approval.
FR-009: Keys MUST never enter git, issues, or logs; only the .pub/node id is public.
FR-010: The board MUST be accessed only via the lock /private/tmp/claude-501/ax7203-board.lock before any JTAG or UART access on the bench Mac.
Activity
dmitrii-f-t27 commentedon Oct 11, 2026
@gHashTag, the E2 job link is ready to land. Four PRs from my fork; I cannot merge in gHashTag/t27. The order is #8532 → #8538 → #8772. #8890 is independent of them on the source side.
fpga/HARDWARE_SSOT.mdspecs/trinet/eth_top_ax7203.t27, with no hand Verilog or XDCBoard result (AX7203, SRAM only), with the top that #8890 generates and the modules of #8772:
Heads updated 2026-10-11 14:55Z: #8532 and #8772 have master
5e5493cabmerged in, with no conflicts, and their seals verify with the merged tree's t27c.The red non-required checks come from master. Each PR has a comment naming the master specs behind them.
Update 2026-10-11 15:50Z: #8890 head is now c9ab3e7 (master merged in, seals re-made). The full merge list with order is in #9136.
Dmitrii Fedorov (@dmitrii-f-t27)