I built Edge AI RTL Lab as a small, reproducible hardware-design project that connects quantized AI inference arithmetic with an RTL verification workflow. The core computes a signed int8 vector dot product using one multiply-accumulate lane, then clamps the exact internal sum to a signed output width.
I kept the scope deliberately small: parameterized SystemVerilog, ready/valid control, a bit-exact Python reference model, deterministic regression, and CI. This is not a trained AI model or a complete neural-network accelerator.
The figure is generated from the checked-in CI matrix. It counts verification transactions; it is not a throughput, timing, area, power, FPGA, or silicon benchmark.
- Synthesizable SystemVerilog with configurable vector length
- Signed int8 multiplication and wide internal accumulation
- Signed saturation at the output (16 bits by default)
- Input and output ready/valid handshakes with output backpressure
- Python golden model and deterministic corner/random vectors
- Self-checking testbench for Icarus Verilog or Verilator
- GitHub Actions simulation and Yosys structural checks
flowchart LR
A["int8 vector A"] --> L["Input latch"]
B["int8 vector B"] --> L
L --> M["One signed 8 x 8 multiplier"]
M --> C["Wide accumulator"]
C --> S["Signed output saturation"]
S --> O["ready/valid result"]
Python 3.10+ and either Icarus Verilog (iverilog + vvp) or Verilator are
required for the full RTL regression.
python -m unittest discover -s tests -v
python tools/run_regression.py --sim auto --vec-len 8 --random-cases 200The harness always includes named corner cases, then adds pseudo-random cases
from a fixed seed. It writes generated artifacts under build/ and prints the
exact compile and simulation commands.
To exercise parameterization:
python tools/run_regression.py --vec-len 1 --random-cases 40
python tools/run_regression.py --vec-len 17 --random-cases 100For vectors a and b, each lane is a two's-complement signed int8 value:
exact_sum = sum(a[i] * b[i] for i in 0 .. VEC_LEN-1)
result = clamp(exact_sum, -2^(OUT_W-1), 2^(OUT_W-1)-1)
I generate this boundary plot from the same named vectors and bit-exact Python model used by the self-checking RTL regression. It shows the wide accumulator value before clamping and the emitted 16-bit result, including exact limits, one-step overflow cases, and both signed extremes. It is arithmetic evidence, not a timing, area, or power result.
Lane 0 occupies bits [7:0] of each packed input bus. Accumulation does not
wrap with the default parameters; saturation happens once, after the final
lane. See Architecture for timing and width details.
| Path | Purpose |
|---|---|
rtl/int8_dot_product.sv |
Synthesizable accelerator core |
model/dot_product_model.py |
Bit-exact reference arithmetic and packing |
tb/tb_int8_dot_product.sv |
Self-checking ready/valid testbench |
tools/run_regression.py |
Vector generation, compile, and simulation harness |
tools/render_readme_assets.py |
Rebuilds and checks both README evidence figures |
tests/ |
Python unit tests for the arithmetic contract |
docs/ |
Architecture and verification notes |
The automated evidence in this repository is RTL simulation plus a Yosys structural synthesis check. No FPGA or ASIC implementation, timing closure, power measurement, silicon validation, or performance benchmark is claimed. Any area, frequency, or energy statement would require a named target, constraints, tool flow, and reproducible reports.
- Add a streaming lane interface so vectors need not arrive on wide buses
- Compare one-MAC and multi-lane architectures after synthesis to a named FPGA
- Add quantization scales and bias/ReLU stages around the integer datapath
- Add formal properties for handshake stability and saturation boundaries
Released under the MIT License.