Skip to content

Add wolfTPM fwTPM on AMD Spartan UltraScale+ SCU35 MicroBlaze V - #6

Open
dgarske wants to merge 1 commit into
mainfrom
scu35
Open

Add wolfTPM fwTPM on AMD Spartan UltraScale+ SCU35 MicroBlaze V#6
dgarske wants to merge 1 commit into
mainfrom
scu35

Conversation

@dgarske

@dgarske dgarske commented Aug 13, 2026

Copy link
Copy Markdown
Member

Summary

A firmware-TPM 2.0 server (wolfTPM fwtpm) on a MicroBlaze V (RISC-V rv32imc) soft core instantiated in the fabric of an AMD Spartan UltraScale+ SCU35 (xcsu35p) - a pure FPGA with no hardened CPU. It is the AMD analog of the PolarFire Mi-V example: driven from a host over UART with the same raw swtpm / mssim framing, so the stock wolfTPM swtpm client drives it unmodified.

The interesting problem: fitting a TPM in 192 KB

The xcsu35p has only 48 block-RAM primitives = 192 KB total, no UltraRAM, and the board has no external DDR. The full RSA+ECC fwTPM is ~652 KB and does not fit. This example shows how a genuinely minimal fwTPM is brought under the device limit and validates it on hardware.

A minimal ECC-only build (-DFWTPM_TINY_ECC) fits in ~190 KB (1.9 KB to spare) via:

  • ECC-P256 only (no RSA, no P-384), SHA-256 only (no SHA-1), table-free AES, reduced fwTPM context/NV slots.
  • wolfTPM's finer command gating from the companion wolfTPM PR - the individual FWTPM_NO_* command-group macros, selected explicitly in user_settings.h (there is no umbrella macro; each gate is a deliberate choice) - compiling out the key-migration / ECDH / hash-command / context / symmetric-encrypt / clock command groups (~20 KB).
  • A fabric hardware TRNG: the on-die SYSMONE4 System Monitor, read over an AXI System Management Wizard, replaces wolfCrypt MemUse entropy (removes ~30 KB of state + conditioner and provides real electrical noise).

What is included

  • Self-contained bare-metal MicroBlaze V HAL (wolfSSL-authored): AXI UARTLite console, AXI Timer time base, RV32 startup, newlib retarget.
  • fwTPM server (fwtpm-mbv/) with clock and volatile-NV HALs and the SYSMONE4 TRNG seed source (fwtpm_trng_sysmon.c, -DFWTPM_TINY_HWTRNG).
  • FPGA integration that adds the TRNG without modifying any AMD source: fpga/add_sysmon.tcl (overlay that adds the System Management Wizard at 0x44A30000) and fpga/build_sysmon.tcl (build driver that sources the stock TRD block design unmodified, applies the overlay, and produces a device image).
  • A hello sanity image and sizing analysis.

Hardware validation (SCU35, Vivado 2025.1)

  • SYSMON registers read live over JTAG: plausible temperature / VCCINT / VCCAUX ADC codes whose low bits jitter run-to-run, confirming the wizard is configured, the register map (0x400/0x404/0x408) is correct, and the noise source is real (not a stuck read that would give a constant DRBG seed).
  • The minimal fwTPM boots on Hart #0: TPM2_Startup and TPM2_GetRandom return rc=0x00000000, and GetRandom returns different bytes across three cold boots - end-to-end proof the Hash-DRBG is seeded from real System-Monitor entropy.
  • Footprint 194,710 bytes (190 KB), fits the 192 KB device.

Notes

The full RSA+ECC firmware also builds and is ready for a larger MicroBlaze V target. No vendor bitstream or BSP is redistributed; the TRD is obtained from AMD and wolfSSL/wolfTPM are sibling source trees.

@dgarske dgarske self-assigned this Aug 13, 2026
Copilot AI lite review requested due to automatic review settings August 13, 2026 20:06
@dgarske

dgarske commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

Requires wolfSSL/wolfTPM#574

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds a bare-metal MicroBlaze V (rv32imc) firmware-TPM (wolfTPM fwtpm) example for the AMD Spartan UltraScale+ SCU35, including an FPGA overlay to instantiate SYSMONE4 as a hardware entropy source so a minimal ECC-only build can fit in 192 KB BRAM.

Changes:

  • Introduces Vivado TCL scripts to rebuild the AMD SCU35 Zephyr TRD bitstream with an AXI System Management Wizard (SYSMONE4) mapped for a TRNG seed source.
  • Adds bare-metal MicroBlaze V HAL, a hello-world bring-up image, and the fwTPM UART server with NV/clock/TRNG integrations and size-tuned build settings.
  • Adds SCU35-specific documentation and top-level README entry describing capabilities, constraints, and build/run steps.

Reviewed changes

Copilot reviewed 24 out of 25 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Xilinx/fwtpm-scu35-microblazev/fpga/build_sysmon.tcl Vivado batch build driver to regenerate TRD design and produce a PDI with SYSMON added.
Xilinx/fwtpm-scu35-microblazev/fpga/add_sysmon.tcl Block-design overlay that instantiates and connects SYSMONE4 AXI System Management Wizard.
Xilinx/fwtpm-scu35-microblazev/fpga/README.md FPGA rebuild instructions, memory sizing discussion, and address map for SYSMON integration.
Xilinx/fwtpm-scu35-microblazev/firmware/hello/mbv-bram.ld Linker script for the hello-world BRAM-resident image.
Xilinx/fwtpm-scu35-microblazev/firmware/hello/main.c Hello-world UART output + timer heartbeat bring-up program.
Xilinx/fwtpm-scu35-microblazev/firmware/hello/Makefile Build recipe for the hello-world image using the Vitis RISC-V toolchain.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/vivado.log Checked-in Vivado run log for SYSMON validation.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/vivado.jou Checked-in Vivado journal for SYSMON validation.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/user_settings.h wolfSSL/wolfTPM configuration tuned for tiny ECC-only + optional SYSMON-seeded DRBG.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/mbv-bram.ld Linker script for the fwTPM image (larger BRAM target for full build).
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/main.c fwTPM initialization + UART server loop implementing swtpm/mssim framing.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/fwtpm_trng_sysmon.c SYSMONE4 oversampling seed generator for Hash-DRBG under FWTPM_TINY_HWTRNG.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/fwtpm_nv_ram.c Volatile RAM-backed NV HAL implementation with tiny-build sizing.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/fwtpm_clock_mbv.c Clock HAL using AXI Timer + XSLEEP_MS shim + entropy hi-res timer.
Xilinx/fwtpm-scu35-microblazev/firmware/fwtpm-mbv/Makefile fwTPM build recipe (wolfSSL/wolfTPM sibling trees) plus tiny-build flags guidance.
Xilinx/fwtpm-scu35-microblazev/firmware/common/startup.S Minimal RV32 startup code for MicroBlaze V.
Xilinx/fwtpm-scu35-microblazev/firmware/common/scu35_board.h Board constants (addresses, console UART choice, clock frequency).
Xilinx/fwtpm-scu35-microblazev/firmware/common/retarget.c Newlib syscall stubs mapping stdio to UARTLite and implementing _sbrk.
Xilinx/fwtpm-scu35-microblazev/firmware/common/mbv_uart.h AXI UARTLite minimal polled driver header.
Xilinx/fwtpm-scu35-microblazev/firmware/common/mbv_uart.c AXI UARTLite minimal polled driver implementation.
Xilinx/fwtpm-scu35-microblazev/firmware/common/mbv_time.h AXI Timer timekeeping API with wrap-handling requirements.
Xilinx/fwtpm-scu35-microblazev/firmware/common/mbv_time.c AXI Timer timekeeping implementation (32-bit hw counter extended to 64-bit).
Xilinx/fwtpm-scu35-microblazev/README.md Top-level SCU35 example documentation (layout, build, run).
Xilinx/fwtpm-scu35-microblazev/.gitignore Ignores build artifacts and FPGA outputs for this example.
README.md Adds a repository-level entry pointing to the new SCU35 MicroBlaze V example.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +77 to +92
static int UartRecvTO(uint8_t* buf, uint32_t sz, uint32_t timeoutMs)
{
uint32_t i;
uint64_t deadline;

for (i = 0; i < sz; i++) {
deadline = mbv_millis() + timeoutMs;
while (mbv_uart_getc(SCU35_CONSOLE_UART_BASE, &buf[i]) == 0) {
(void)mbv_ticks();
if (mbv_millis() >= deadline) {
return -1;
}
}
}
return 0;
}
Comment on lines +3 to +4
* Volatile RAM-backed FWTPM_NV_HAL for the MicroBlaze V fwTPM bring-up. A 64 KiB
* buffer whose contents are lost across power cycles. The wolfTPM core owns the
Comment on lines +52 to +56
# 2. Add one master port to the MicroBlaze V AXI SmartConnect (19 -> 20) and
# wire it to the wizard's AXI4-Lite slave.
set_property CONFIG.NUM_MI {20} [get_bd_cells microblaze_riscv_0_axi_periph]
connect_bd_intf_net \
[get_bd_intf_pins microblaze_riscv_0_axi_periph/M19_AXI] \
Comment thread README.md
Comment on lines +47 to +49
minimal ECC-only build (`FWTPM_TINY_ECC`) fits the stock 192 KB of block RAM
(no DDR on this part): ~190 KB via wolfTPM's `FWTPM_MINIMAL` command gating and an
on-die SYSMONE4 fabric TRNG (added by `fpga/add_sysmon.tcl`) in place of MemUse
Comment on lines +114 to +122
3. Read the console (`axi_uartlite_0`) over the SCU35 FT4232H UART with `uart-monitor`.

## Address map (from the TRD, for the firmware `scu35_board.h`)

| Block | Base |
|-------|------|
| Local BRAM (reset vector) | `0x00000000` |
| AXI UARTLite 0 (console) | `0x40600000` |
| AXI UARTLite 1 | `0x40700000` |
…only fits 192KB via SYSMON TRNG + per-command-group gating)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants