# ECP5 physical-board test record — 2026-08-25

## Status

Company-authored engineering record. This file is reproducible evidence of a
specific volatile-board test; it is not independently witnessed, signed,
certified, or a product-safety claim.

## Board and connection

| Item | Recorded value |
|---|---|
| Board | Lattice ECP5 Evaluation Board, `LFE5UM5G-85F-EVN` |
| FPGA | LFE5UM5G-85F, CABGA381 package |
| JTAG identity | ECP5 IDCODE `0x81113043` (previously observed on 10 consecutive detections) |
| Configuration transport | USB/FTDI JTAG using `openFPGALoader`; SRAM/volatile configuration only |
| Clock | 12 MHz board reference-clock input |
| Outputs observed | Eight onboard LEDs only; active-low hardware mapping |
| UART / external I/O | External 3.3 V FT232 adapter; UART diagnostic only, no product I/O |
| Configuration flash | Not written |

## Composite PMP result

The image enables NEORV32 user mode and three locked PMP regions: a protected
16 KiB monitor-state block at `0x80000000`–`0x80003fff`, general DMEM, and executable IMEM.
Its user-mode probe attempted, in order:

1. a store to protected RAM (expected store-access fault);
2. a load from protected RAM (expected load-access fault);
3. a write to `pmpcfg0` (expected illegal-instruction fault).

The trap sequence completed, then the image ran the loader/VM/monitor smoke
workload. The final GPIO value was `0x3c`, shown by the board as the four
middle LEDs lit. This image's result is therefore a pass for this specific
three-operation, three-region logical PMP test.

It does **not** demonstrate a production monitor-memory layout, full hostile
code isolation, physical independence, product I/O, complete physical product
timing, reset or power-fault behaviour, persistent configuration, or certification.

## UART diagnostic and physical timing additions

After the LED/PMP record, the board was connected to an external 3.3 V FT232
adapter at 9,600 baud. Adapter TX was connected to FPGA receive and adapter RX
to FPGA transmit; the adapter ground was common with the board. This interface
was used only for diagnostic text and trigger bytes.

| Check | Observation | Scope |
|---|---|---|
| Adapter loopback | Sent and received `LOOP-9600` exactly | Establishes the adapter's local TX/RX path at the selected baud |
| FPGA UART transmitter | Repeated clean `U` characters received | Establishes board transmit through the selected FPGA pin and adapter RX |
| CPU UART echo | Host input `E` caused the board CPU to return `U` | Establishes the board receive path, CPU peripheral path, and transmit return path; it is not a framed-loader test |
| Loader/VM counter run | 16 / 16 valid records at each clock: 12 MHz `463`/`2941`; 24 MHz `464`/`2796`; 48 MHz `464`/`2796` cycles, loader/VM respectively | Counters bracket only the two workloads; serial reporting is outside each interval |
| Monitor counter run | warm worst of 64 permits: 12 MHz `12916`; 24 and 48 MHz `12823` cycles. Refusal worst of 8: `232` cycles with `permit=0` at all three clocks | Separate monitor workload, not integrated with the VM or physical actuator path |

At 12 MHz, the measured values convert to 38.6 µs (loader validation), 245.1
µs (five-instruction VM sample), 1,076.3 µs (warm monitor permit worst-of-64),
1,075.5 µs (stale monitor permit worst-of-2), and 19.3 µs (refusal worst-of-8).
At 24 MHz, loader/VM are 19.3/116.5 µs and the warm monitor sample is 534.3
µs. At 48 MHz, loader/VM are 9.7/58.3 µs and the warm monitor sample is 267.1
µs. The timing records are exact counter values from these small test programs,
not an assertion about an integrated 500 Hz product cycle. In particular, adding
loader, VM and monitor values would not constitute a measured control loop:
loader admission is not per tick, and product I/O, feedback, output timing, and
logging are absent.

The physical monitor warm samples are 302 cycles (2.3%) below the published RTL
simulation baseline of 13,218 cycles at 12 MHz and 395 cycles (3.0%) below it
at 24/48 MHz. This is useful corroboration of scale, not validation of the
simulation model or an exact 25 MHz result: the board points are 12, 24 and 48
MHz, and no integrated physical control loop has been measured.

## Reproducibility identifiers

Repository baseline at record creation: `e3dfe2b14d4dcc32388376f044cd1dc9e9dfacd3`.
The test changes were still in the working tree, so the source hashes below—not
that baseline alone—identify the tested inputs.

| Input or output | SHA-256 |
|---|---|
| `endstop-bringup/board_timing_top.vhd` | `0d3c8fdb8a1a701525bd9de7ffbedbe21682071788bd8154e9ba6871ef2e2dd6` |
| `endstop-cycles/src/bin/board_pmp_smoke.rs` | `583d892a299b3d0e11dee118bc0e2c233246ac79710c04ce85445e5a927c5f9a` |
| `endstop-cycles/Cargo.toml` | `55b30da736c16db791b0d3f14ab26b18ae7632dabb61ebfc8148e4ca1f5306c7` |
| Volatile FPGA bitstream | `18fb6ad9c0cc37be31f8b12f6906b63176abfe713f7c80e19040dccb77a2234f` |

## Build and instrumentation

The firmware was built as the `board-pmp-smoke` bare-metal Rust binary for
`riscv32imc-unknown-none-elf`. The volatile bitstream was produced using the
open-source Yosys/GHDL/nextpnr ECP5 flow, then loaded over the board's existing
JTAG connection. Recorded tool versions include Yosys `0.68+120` and
nextpnr-ecp5 `0.11.1-9-gb17408e2`.

The first runtime instrument was the board's LED bank. It established the
specified terminal marker but could not measure execution time, expose trap
addresses/registers, or witness intermediate events. The later UART additions
provided textual captures and a start trigger; the hardware counter values were
read and printed by the test firmware. Neither method is an external logic
analyser, a calibrated oscilloscope measurement, or an independent witness.

## Reference-image provenance

The board reference image shown on the silicon page is locally hosted at
`/assets/ecp5-evaluation-board-newark.webp`, SHA-256
`b328723e654cf3be89970c3520848f8b18bc701e324c3add425331efe6a691ea`.
It originated from the Newark product-image URL linked in that page's caption;
it identifies the board model and is not test evidence.
