07. FPGA / Zynq Overview
This page covers the general flow of taking a graph that's been
validated on cpu_ref / npu_sim and putting it onto real FPGA
silicon. The pattern established here is what 08. kws_silicon
executes concretely.
Why FPGA / Zynq
What FPGA buys you over CPU/GPU:
- Deterministic latency — almost no branch/cache misses, suits real-time/safety-critical
- Low power — ~1/10 W of GPU at equivalent throughput
- Online reconfiguration — accelerators can be re-synthesised at operator granularity
- Small-chip entry — meaningful acceleration on a small board (XC7Z020, Zynq-7000 family)
eulernpu's primary target board is QMTECH XC7Z020 CLG484-1 (Zynq-7000):
| Resource | Value | Implication |
|---|---|---|
| LUT | 53 K | Small IPs fit comfortably |
| DSP slices | 220 | ~50 float MAC units possible |
| BRAM 36k | 280 (~140 KB usable) | Small model weights cache on-chip |
| DDR3 | 512 MB | Bigger weights need DDR streaming |
| ARM Cortex-A9 | 666 MHz × 2 (PS) | Embedding/sample/non-PL work |
| EMIO UART | MIO 48/49 | Bare-metal printf channel |
| PL Fmax | ~90–115 MHz measured | Bound by float MAC placement |
Zynq Architecture at a Glance
┌─────────────────────────────────────────┐
│ PS (Processing System) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ ARM A9 #0 │ │ ARM A9 #1 │ │
│ │ 666 MHz │ │ 666 MHz │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ L1 32K + L2 512K │
│ │ DDR3 controller │
└─────────┼─────────────────────────────────┘
│ GP0 (32-bit AXI, control)
│ HP0–3 (64-bit AXI, data)
│ EMIO (GPIO/UART routing)
┌─────────┼─────────────────────────────────┐
│ PL (Programmable Logic) │
│ ┌──────▼───────────────────────────┐ │
│ │ NPU IP │ │
│ │ s_axilite (control reg) │ │
│ │ m_axi (data via HP slave) │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
- GP0 (General Purpose) — 32-bit AXI-Lite, IP control registers
- HP0 (High Performance) — 64-bit AXI-Full, IP reads/writes DDR
- EMIO — routes PL pins to PS UART (printf channel)
Standard Flow — 7 Stages
1. Train + INT8 quantize → weights.npz / weights.h
2. Host CPU smoke → compile same C with host gcc, verify accuracy
3. HLS C-synth → C++ → RTL IP, Fmax / DSP / BRAM report
4. Vivado BD + impl → IP + PS + AXI wiring → bitstream
5. Vitis platform + ELF → SDT platform + BSP + bare-metal C ELF
6. xsdb silicon run → JTAG bitstream load + ELF download + UART capture
7. Measure + regression → cycle count / accuracy / reproducibility auto-checked
All 7 stages should live in automated scripts — silicon reproducibility should not be a cliff edge every time.
PL Offload Candidates (Spec → Hardware)
Which ops are worth putting on PL fabric?
- Compute-heavy + regular: linear, matmul, batched_matmul
- Conv family: conv2d, conv1d, depthwise_conv2d, patch_embed
- Attention family: attention_core, flash_attention, cross_attention, multi_query_attention
- SSM: selective_scan (Mamba)
Which ops are NOT worth offloading:
- Small control flow (
argmax,sample) — microseconds on ARM - KV cache management — variable length, fits ARM
- LayerNorm, GELU — small enough that IP overhead dominates (confirmed by P08 measurement)
The equivalent analysis is now automatic via
eulernpu profile --roofline.
Board Bring-up Checklist
If you have a fresh XC7Z020 board:
- Power + USB-JTAG connected (QMTECH does both via a single USB-C)
- Check
/dev/ttyUSBn— typically two ports (JTAG + UART) - Vivado 2025.1 + Vitis 2025.1 installed
- USB Blaster cable driver —
lsusbto confirm Xilinx is recognised - 115200-8N1 UART terminal —
picocom,tio,pyserial, etc.
The shortest board bring-up walkthrough is the P05 sanity check: the FPGA sanity-check demo tutorial (shipped with the internal bring-up repo). Once that passes you can move to P06.
Per-Board Resource Limits (capability matrix)
eulernpu profile --all-boards /tmp/sim.profile.json
A single table tells you which board the graph fits on:
| Board | LUT | DSP | BRAM 36k | DDR | Note |
|---|---|---|---|---|---|
| XC7Z020 | 53 K | 220 | 280 | DDR3 512 MB | P06/07/08 silicon-validated |
| XC7Z045 | 218 K | 900 | 545 | DDR3 1 GB | Midrange |
| XCZU7EV | 230 K | 1728 | 312 | DDR4 4 GB | ZU+ entry |
| XCZU9EG | 274 K | 2520 | 912 | DDR4 4 GB | Larger models |
| XCK26 | (Kria) | 1248 | varies | 4 GB | Module form factor |
Next
The full silicon flow on the actual P06 KWS demo → 08. kws_silicon.