Lab 2: AXI4 Burst Reads for a SIMD#
Introduction#
In Lab 1, we deisgn an accelerator that fetches one 32-bit word per custom instruction. In this lab, one software command must start an AXI4 INCR read burst and retain multiple beats in accelerator-local storage. You will reuse those burst-loaded operands in a self-designed compute datapath and accelerate the int8 convolution used by KWS model in Lab 1.
The compute instruction encoding and internal microarchitecture are your choice while the external visible behavior is fixed.
Learning goals#
implement an AXI4 read burst using the VALID/READY protocol
interpret
ARLENandRLASTcorrectly and tolerate bus stallsbuffer and reuse data instead of issuing repeated single-word reads
define a stable hardware/software interface for custom instructions
compare latency and FPGA resource cost under a reproducible flow
Grading#
Component |
Weight |
|---|---|
AXI4 burst engine and dot-product service |
30% |
TFLM convolution and model correctness |
30% |
Latency and accelerator-resource efficiency |
20% |
Demo and questions |
20% |
Prerequisites and setup#
Vivado 2024.1
RISC-V toolchain
Python 3 with
pyserialVerilator and a host C++11 compiler
Model file
ds_cnn_stream_fe.tflitefrom lab1
Download everything in
lab2/from AAML-Labs-2026.Replace
Platform/sw/projectwith the version you downloaded.Move everything in
model/toPlatform/sw/model.Add
APP_EXTRA_SRCS += $(wildcard models/label/label*_board.cc)toproject.mk, or define it when runningmake.From the repository root, run the following preflight check before editing the RTL:
vivado -version
verilator --version
c++ --version
riscv64-unknown-elf-g++ --version
python3 -c "import serial"
make -C Platform/sw validate
make -C Platform/sw check-env \
MODEL_FILE=ds_cnn_stream_fe.tflite MODEL_PROFILE=ds_cnn_stream_fe
Files and submission boundary#
You may modify:
Platform/hw/srcs/NPU.vPlatform/sw/project/lab2_api.ccPlatform/sw/models/ds_cnn_stream_fe_profile.ccPlatform/sw/tflm_patches/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h
You may add helper Verilog modules under Platform/hw/srcs/ and helper C/C++ files under Platform/sw/project/. Do not replace or rename the NPU module. Preserve its complete port list, active-low rst_n behavior, and CPU/AXI signal directions so the existing block design still elaborates.
NPU.v is starter code, not a golden implementation. Write your own accelerator after all the environmental check passed.
Important
Your submitted project must build and run without source edits. Keep the required API signatures below even if you change every underlying funct3/funct7 value.
Required software contract#
The public and grading software calls the following function declared in Platform/sw/project/lab2_api.h:
int32_t hw_simd_mac(int8_t* ptr1, int8_t* ptr2, int8_t input_offset, uint32_t N);
Keep this signature and its C linkage unchanged, and implement it in Platform/sw/project/lab2_api.cc. The buffers are read-only from the accelerator’s point of view.
For every valid call, return the exact signed 32-bit result:
result = sum((ptr1[i] + input_offset)*ptr2[i] for i in range(N))
You can check function ConvPerChannel in file tflite-micro/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h for more detail.
The CUSTOM-0 encoding behind hw_simd_mac is your design. You may choose the funct3 and funct7 values, command sequence, local-buffer organization, state machine, and SIMD width.
You can use register or bram as local data buffer.
Use the helpers in Platform/sw/app/cfu.h.
The multiplication and main accumulation must be performed by custom hardware using operand data read through AXI4 bursts. A CPU loop that calculates the dot product, including one hidden inside hw_simd_mac, does not satisfy the assignment.
Software may prepare the arguments of custom instructions, clean cache lines and issue custom instructions.
Part 1: AXI4 read burst engine and dot service (30%)#
Implement the read-burst engine and SIMD multiply-accumulate datapath in Platform/hw/srcs/NPU.v, then implement hw_simd_mac in Platform/sw/project/lab2_api.cc using your custom instructions. The NPU must fetch both operand vectors through its AXI master and use the fetched bytes in the returned dot product. AXI writes are not required for Lab 2.
Required transfer domain#
N in the software ABI is an element count measured in bytes, not an AXI word count. Use B below for the number of 32-bit AXI beats in one load. Every burst issued for Lab 2 must satisfy:
Property |
Requirement |
|---|---|
Direction |
Read only |
AXI data width |
32 bits |
Burst type |
INCR ( |
Beat size |
4 bytes ( |
AXI start address |
4-byte aligned address in |
Outstanding requests |
One is sufficient |
4-KiB boundary |
An individual burst must not cross it |
AXI encodes a burst of B beats as ARLEN = B - 1. Each AXI burst issues one address handshake with:
ARADDR = legal aligned source or staging address
ARLEN = B - 1
ARSIZE = 3'b010
ARBURST = 2'b01
A legal request satisfies:
address[1:0] == 0
address[11:0] + 4 * B <= 4096
0x6000_0000 <= address
address + 4 * B <= 0x6800_0000
Note
Your hardware design must handle independently unaligned pointers, arbitrary N and the final partial word. Replacing a multi-beat burst with repeated single-beat requests does not satisfy this lab.
Important
Unaligned addresses should be passed directly to the hardware for processing. If we find that your code uses any software staging method to handle unaligned pointers, you will receive zero points for both Part 1 and Part 2.
AXI protocol requirements#
Your burst engine must satisfy all of the following:
Assert
ARVALIDwith a legal address and the required control values, and keep them stable untilARVALID && ARREADY.Accept a read beat only when
RVALID && RREADY.Accept exactly
Bbeats in address order and interpret each 32-bit beat in little-endian byte order.Do not assume that
ARREADYorRVALIDremains high continuously.Complete a successful load only after accepting beat
BwithRLAST; an earlyRLAST, a missingRLASTon beatB, an incorrect beat count, or a non-OKAYRRESPis an error.An early
RLASTmay finish the command immediately withNPU_doneasserted. If beatBarrives withoutRLAST, stop writing local operand storage, accept and discard later beats untilRLAST, then finish withNPU_doneasserted.Pulse
NPU_doneexactly once for each completed custom command and do not leave it asserted while idle.Be prepared to accept back-to-back commands.
Software verification#
After changing RTL, program the FPGA and upload the model-free firmware from the repository root:
make -C Platform prog
make -C Platform run
Press CPU RESET after the upload, press 2 to enter the Lab 2 submenu, and run both entries:
Main menu -> Lab menu (key l) -> Lab2 set tests (key t)
Main menu -> Lab menu (key l) -> Lab2 random tests (key r)
The test code writes the input arrays and then calls hw_simd_mac; it does not clean them first, so cache cleaning is part of the service implementation.
Testcase Input Limits#
1 <= N <= 256
ptr1,ptr2: any valid address for AXI read requestselements of
ptr1,ptr2: any value ofint8_tinput_offset: any value ofint8_t
There are hidden testcases. Make sure that your design can handle all edge cases correctly.
Part 2: TFLM convolution integration (30%)#
Modify the int8 ConvPerChannel implementation in:
Platform/sw/tflm_patches/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h
Include lab2_api.h and replace existing software implementations that can be accelerated with calls to hw_simd_mac.
CPU code may still perform loop control, address calculation, padding checks, bias addition, requantization, output offset, and clamping, but the input/filter channel products must contribute through hw_simd_mac.
Your accelerated kernel must preserve the reference behavior for:
signed int8 input and filter values
grouped-convolution input-channel offsets
input_offsetwithin the published int8 service domain and arbitrary input-channel countsstride, dilation, and omitted out-of-image padding positions
bias addition
per-channel multiplier and shift
output offset and activation clamping
output indexing and all tensor shapes
Software verification#
First upload the model-free firmware and run the existing golden convolution cases:
make run
After pressing CPU RESET, select:
Main menu -> Lab menu (key l) -> Basic convolution tests (key c)
All three cases must report [PASS].
Run the KWS model#
After the test passed, recompile the software with following command:
make run -C Platform/sw MODEL_FILE=ds_cnn_stream_fe.tflite MODEL_PROFILE=ds_cnn_stream_fe
It usually takes 3 min to inference. You can print out model output by yourself to check the correctness of model.
Important
If the result of any testcase inside label/ is different from golden answer, Parts 2 and the efficiency section receive zero.
Latency and accelerator-resource efficiency (20%)#
Only submissions that complete every preceding requirement are eligible for ranking. An eligible submission must:
receives
20/20in Part 1receives
20/20in Part 2compliance with the mandatory accelerator-command, AXI-trace, and convolution-coverage requirements in Part 2
successful post-route implementation for
Arty-A7 100Twith exactly one recursiveNPUinstance identified in the utilization reportnon-negative overall setup
WNS (ns)in the final Design Timing Summary
Available hardware and maximum usage#
Resource counts are taken from the recursive NPU-only final post-route utilization report; the fixed CPU, caches, DDR controller, and interconnect are excluded. Each RAMB18 counts as one-half of a BRAM36 equivalent.
Resource |
Available on FPGA |
Maximum NPU usage |
|---|---|---|
Slice LUT |
56,981 |
20,000 |
Flip-flop |
121,572 |
5,000 |
DSP48E1 |
230 |
30 |
RAMB18E1 |
270 |
270 |
RAMB36E1 |
135 |
135 |
Latency efficiency#
Let \(\mathcal{T}\) be the official test set and let \(C_{i,t}\) be the interpreter.Invoke() cycle count for student \(i\) on test \(t\). Every test has equal weight, and the latency used for ranking is the average:
Lower \(\overline{C}_i\) is better. Cached final outputs are not allowed.
Ranking#
Eligible submissions are ordered from the lowest to the highest average cycle count and divided into five groups as evenly as possible.
Level |
Nominal position among eligible submissions |
Efficiency points |
|---|---|---|
1 |
Top 20% |
20 |
2 |
20%-40% |
15 |
3 |
40%-60% |
10 |
4 |
60%-80% |
5 |
5 |
Bottom 20% |
0 |
Demo and questions (20%)#
Prepare a short explanation of your implementation, including how you use aligned staging when a source address is not directly legal for the burst interface. Be ready to reproduce your results and answer questions about the following areas:
AXI4 handshakes, burst state machine, stalls,
RLAST, and error handlingTFLM convolution mapping, aligned staging, and cache coherence
Submission#
Submit your hardware RTL, custom op design according to the following format. Do not include Platform/build/, a generated Vivado project, or other reproducible build output.
aaml-lab2-[id].zip
└── aaml-lab2-[id]/
├── hw/
│ └── src/
│ ├── NPU.v
│ └── {any other modules}
└── sw/
├── conv.h
└── lab2_api.cc
Important
Notice: An incorrect submission structure will result in a 10-point deduction from your total lab score!
Important
If the project cannot be compiled or run using the documented commands, Parts 1 and 2 and the efficiency section receive zero; only the 20-point demo can be assessed. Follow the course collaboration policy; plagiarism is not allowed.