Skip to content

E2: TRI-NET node over UDP on the AX7203 (Ethernet job link instead of UART) #8327

Open

Description

@dmitrii-f-t27

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 master 95ae4bcd6 for xc7a200tfbg484-2 with 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 DNA 0x00389c0c2d85e85c. On 2026-10-09 a Mac on the same LAN over Wi-Fi received 149 of 176 T27E datagrams 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 every tcsetattr with EINVAL three 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.v and fpga/openxc7-synth/trinet_siphash24.v are Verilog. Per the own-language rule the logic here is written as .t27 specs; the Verilog is a cross-check, not an import.
  • Open risk: RGMII receive at 1000 Mb/s. specs/fpga/rgmii_sniff.t27 samples 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 (ours 02:27:00:00:00:01 or 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 (magic AA 55), MAC32 over 32 trits, SipHash-2-4 over the 26-byte preimage, setkey write-once with a signed acknowledgement, NO_KEY before a key is installed, v2 response.
  • E2c specs/fpga/eth_tx_udp.t27: reply datagram builder generalised from EthBeacon. 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.zig is 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.lock before 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 under fpga/verilog/ (E2d only), a dated section in fpga/HARDWARE_SSOT.md.
  • Out of bounds: specs/fpga/eth_beacon.t27 and rgmii_sniff.t27 stay as they are (reuse by copy of idioms, not by edit); no compiler changes; no changes to the TRI-NET protocol or to trinity-fpga.

User Scenarios & Testing

  1. The operator loads the node bitstream into SRAM, installs a key with setkey over UDP and gets a signed acknowledgement.
  2. 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.
  3. A frame with a bad FCS, a wrong MAC, a wrong IP or a wrong port is dropped and counted, never answered.
  4. Before a key is installed the node answers NO_KEY with 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.zig encodeResponseV2 byte 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 t27c parse, 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): setkey acknowledged, 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.md with 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

  1. dmitrii-f-t27 commented on Oct 11, 2026

    @dmitrii-f-t27
    ContributorAuthor

    @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.

    PR What Head Required checks
    #8532 (Closes #8530) EthReply that runs on the board; timing for the three modules together ea7ee77 all pass
    #8538 (Closes #8536) the board record in fpga/HARDWARE_SSOT.md cb75ec2 all pass
    #8772 (Closes #8770) Mdio100m, Rgmii100, JtagStatus: the 100 Mb/s board logic in t27 7581137 all pass
    #8890 (Closes #8889) t27b verilog pin declarations; the board top specs/trinet/eth_top_ax7203.t27, with no hand Verilog or XDC c9ab3e7 all pass

    Board result (AX7203, SRAM only), with the top that #8890 generates and the modules of #8772:

    • 10000/10000 keyed jobs verified one at a time;
    • 30000/30000 with 64 in flight;
    • timing closed: 200 MHz domain 251 MHz, 25 MHz domain 104.77 MHz.

    Heads updated 2026-10-11 14:55Z: #8532 and #8772 have master 5e5493cab merged 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions