For the Conv2D inner loop (K×K×C_in MACs per output, C_out output channels, 4-wide MAC array):
Bytes read from DMEM per spatial position:
Effective AI (per spatial position, all C_out output channels computed):
Compare to software (no local buffer, weights re-fetched each time):
The local BRAM buffer increases AI by C_out× (e.g., 64× if C_out=64). The MAC array is now compute-bound (operating near the compute roof), not memory-bound.
| Design point | AI (MACs/byte) | Performance | Bound by |
|---|---|---|---|
| Software baseline | 0.5 | 0.5 × bus_BW | Memory |
| 4-wide SIMD, no buffer | 0.5 | 0.5 × bus_BW | Memory |
| 4-wide SIMD + BRAM | 64 | min(4, 64 × BW) = 4 | Compute |
| 8-wide SIMD + BRAM | 64 | min(8, 64 × BW) = 8 | Compute |
| 16-wide + double-buffer | 128 | min(16, 128 × BW) = 16 | Compute |
The key insight: adding more MAC units without a local buffer would have given zero speedup. The BRAM buffer was the architectural decision that mattered most.
The classic roofline model has two regions: memory-bound (left of the knee) and compute-bound (right). In practice, a third region exists:
Latency-bound: the accelerator is neither saturating memory bandwidth nor compute units — it is stalled waiting for a fixed-latency operation (e.g., a single BRAM read that takes 2 cycles, a bus round-trip that takes 4 cycles) even though neither bandwidth nor FLOP rate is the bottleneck.
Performance (MACs/cycle)
│
4 │ ───────────────────────────── ← compute roof
│ /
│ latency-bound zone / ← accelerator stalls on bus round-trip
1 │ ── ── ── ── ● / even though bandwidth is not saturated
│ ↑ /
│ "should be here" /
│ /
└──────────────────────────────→ AI (MACs/byte)
How to identify it: if your measured performance is below both the memory bandwidth line AND the compute roof, but increasing data reuse (buffering) doesn't help, the bottleneck is latency, not bandwidth.
In the course reference implementation (docs/stage9-writeup.md): the first accelerator version was latency-bound because each MAC required a bus round-trip (write rs1, write rs2, read result). Adding a local BRAM buffer moved it to the compute-bound region.
Mitigation: pipeline the bus interface, add a request queue, or redesign the memory interface to amortize latency over a burst of operations.
Accelerating Conv2D to 4× gives ~3.1× system speedup (assuming Conv2D is 90% of runtime):
System = Accelerated part + Non-accelerated part
= 90% at 4× + 10% unchanged
Speedup = 1 / (0.10 + 0.90/4) = 1 / 0.325 ≈ 3.1×
The fixed 10% (FC layer, bus overhead, requantization) sets an asymptotic ceiling of 10× regardless of how fast Conv2D gets. With actual measured percentages from your profiling, substitute the real numbers.
This is the honest engineering answer: 4× layer speedup, ~3× system speedup. More MAC units would help only if the layer stays compute-bound (which depends on the weight buffer being large enough).
| Your design | Ethos-U55 (32 MAC config) | |
|---|---|---|
| MAC units | 4 int8 | 32 int8 |
| Clock | 27 MHz | 500 MHz |
| Peak throughput | 108M MACs/s | 16,000M MACs/s |
| Memory bandwidth | 32-bit bus @ 27 MHz | 64-bit AXI @ 500 MHz |
| Weight buffer | 512 bytes BRAM | 32 KB SRAM |
| Supported ops | Conv2D inner loop | Full tiny_conv graph |
| Programming model | Register + poll | Command stream (DMA) |
| Area | ~400 LUT + 4 DSP | ~0.06 mm² in 5nm |
| Power | ~10 mW (estimate) | ~0.5 mW (measured) |
The Ethos-U55 is 148× faster with 20× less power. But it required a full design team, a silicon process, and years of engineering. Your design was built in one semester from first principles.
RVV integrates SIMD into the CPU pipeline — no separate peripheral:
| Memory-mapped accelerator | RVV vector unit | |
|---|---|---|
| Interface | Bus registers + polling | New instructions |
| Programming model | C driver with volatile pointers | Intrinsics or auto-vectorization |
| Overhead | 2–4 bus transactions per call | Zero (inline) |
| Datapath | Fixed function | General (any element-wise op) |
| Flexibility | Only PW conv | Any SIMD-friendly loop |
| Design complexity | Medium (separate module) | High (pipeline change) |
For this course, the memory-mapped approach was the right pedagogical choice — it teaches the full stack (hardware interface design, software drivers, bus integration) in a way that RVV shortcuts. In production, RVV wins on almost every metric.
Honest retrospective on the design choices:
The slides that follow cover security, energy, and reproducibility. Security corners are required reading. Energy and reproducibility corners are optional enrichment.
Your accelerator sits on the memory-mapped bus and, from the CPU's perspective, is just another peripheral. But what if the accelerator had DMA (Direct Memory Access) capability?
A DMA-capable accelerator can read and write any memory address independently of the CPU:
An IOMMU (I/O Memory Management Unit) does for peripherals what PMP/MMU does for the CPU:
Your Project 3 accelerator does not have DMA — the CPU moves all data via load/store. But production accelerators (GPU, NPU, network cards) always need an IOMMU.
Your 4-wide MAC array consumes different amounts of power depending on the input data and weights:
127 × 127 toggles more transistor gates than 0 × 0.| Technique | Cost | Effect |
|---|---|---|
| Constant-activity masking | ~2× area | XOR weights with random mask; unmask after MAC |
| Noise injection | Minimal | Random dummy operations between real MACs |
| Voltage regulation | Board-level | On-chip LDO smooths power signature |
| Algorithmic | Free | Process inputs in random order each inference |
These are not theoretical — power side-channel extraction of neural network weights has been demonstrated on FPGAs in published research (Batina et al., CHES 2019).
Project 3 security question: "Your accelerator has direct access to the bus. Describe a scenario where this could be exploited if DMA were added, and one hardware mechanism that would restrict it."
Just as the performance roofline plots throughput vs arithmetic intensity, an energy roofline plots energy efficiency (inferences/J) vs arithmetic intensity:
Your accelerator's BRAM buffer moves the design from "fetching weights from DMEM every cycle" (memory-bound) to "reading weights from local BRAM" (compute-bound):
| Configuration | Energy per MAC | Bottleneck |
|---|---|---|
| CPU SW (DMEM fetch) | ~50 pJ | Memory access dominates |
| Accelerator (BRAM buffer) | ~5 pJ | Compute dominates |
| ASIC NPU (local SRAM + 8nm) | ~0.1 pJ | Leakage becomes significant |
Recall
Combined with the 10× process advantage (55 nm → 8 nm), this explains why production NPUs achieve ~1000× better energy efficiency than your FPGA design — and why your FPGA design still beats cloud inference by ~400×.
Putting it all together for one KWS inference at 27 MHz:
| Component | Power | Time | Energy |
|---|---|---|---|
| FPGA static power | 20 mW | 360 ms | 7.2 mJ |
| CPU dynamic (clock tree) | 15 mW | 360 ms | 5.4 mJ |
| CPU logic switching | 10 mW | 360 ms | 3.6 mJ |
| BRAM access | 5 mW | 360 ms | 1.8 mJ |
| Accelerator (when active) | 5 mW | 100 ms | 0.5 mJ |
| Total (baseline) | 18.5 mJ | ||
| (with accelerator, ~103 ms) | 6.3 mJ |
Static power is 39% of total — and you cannot reduce it without a different FPGA or voltage scaling. This is a fundamental limit of the platform.
Your Project 3 repository should allow the instructor to reproduce your results from a single make command:
├── rtl/ # all SystemVerilog source
│ ├── cpu/ # Project 1 core
│ ├── bus/ # Project 2 bus + peripherals
│ └── accel/ # Project 3 accelerator
├── tb/ # all Verilator testbenches
│ ├── Makefile # `make test` runs all tests
│ └── test_*.cpp
├── sw/ # C programs
│ ├── bootloader/
│ ├── kws/
│ └── Makefile # `make` cross-compiles all
├── constraints/ # pin constraints (.cst)
├── Makefile # top-level: `make synth`, `make load`
├── results/ # synthesis reports, cycle counts
│ ├── utilization.txt
│ ├── timing.txt
│ └── speedup.csv
└── README.md # memory map, tool versions, how to reproduce
make test passes all Verilator tests on a clean clonemake synth produces a bitstream with no timing violationsmake load programs the Tang Nano 9Kresults/speedup.csv matches the numbers in your presentation.gitignore)Module 6 — Closing: off-the-shelf alternatives in depth, final presentations, and the full retrospective — from gates to AI inference in one semester.