https://github.com/celpha2svx/matrix-riscv
Custom RISC-V core with Matrix MAC instruction
https://github.com/celpha2svx/matrix-riscv
Last synced: 9 days ago
JSON representation
Custom RISC-V core with Matrix MAC instruction
- Host: GitHub
- URL: https://github.com/celpha2svx/matrix-riscv
- Owner: celpha2svx
- Created: 2026-05-13T11:38:30.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-05T23:08:12.000Z (about 1 month ago)
- Last Synced: 2026-06-06T00:12:00.577Z (about 1 month ago)
- Language: Verilog
- Size: 878 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# β‘ Matrix-RISCV
### A Custom MAC Instruction for Memory-Efficient Machine Learning
[](https://opensource.org/licenses/MIT)
[](https://github.com/celpha2svx/matrix-riscv)
[](https://riscv.org/)
[](http://iverilog.icarus.com/)
*A single-cycle RV32I RISC-V processor extended with a custom Multiply-Accumulate instruction β built for ML workloads on memory-constrained hardware.*
---
## π§ The Problem
Training ML models requires **millions of matrix multiply-accumulate operations**. On a standard RISC-V core, every single MAC costs two instructions:
```asm
mul t0, a0, a1 # Multiply β 1 instruction, 1 cycle, 1 register write
add a2, a2, t0 # Accumulate β 1 instruction, 1 cycle, 1 register write
```
That's **2 cycles, 2 register writes, 8 bytes of instruction memory** per MAC. On a 4 GB RAM machine, your instruction stream competes directly with your training data for memory bandwidth. At 1 million MACs, you're burning **8 MB just on instruction fetches** β before a single weight is touched.
---
## β
The Solution
```asm
mac a2, a0, a1 # a2 = a2 + (a0 * a1) β ONE instruction, ONE cycle
```
A single custom instruction that does the full multiply-accumulate in **one cycle**. Half the instructions. Half the memory traffic. Same result.

---
## π Why This Matters Beyond the Numbers
Most researchers building AI on constrained hardware β students, independent
researchers, developers in low-resource environments β don't have the luxury
of throwing more RAM at the problem.
This project asks a different question: what if the instruction set itself
was part of the solution?
A 50% reduction in instruction fetch overhead is not just a benchmark number.
On a 4GB RAM machine running a real ML workload, it means the difference
between training completing and training stalling. This is hardware designed
for the constraints that actually exist β not the constraints that are
convenient to assume away.
---
## π Instruction Encoding
```
31 25 24 20 19 15 14 12 11 7 6 0
ββββββββββββ¬ββββββββ¬ββββββββ¬ββββββββ¬ββββββββ¬ββββββββββ
β funct7 β rs2 β rs1 βfunct3 β rd β opcode β
β 0000001 β rs2 β rs1 β 000 β rd β 0001011 β
ββββββββββββ΄ββββββββ΄ββββββββ΄ββββββββ΄ββββββββ΄ββββββββββ
custom-0
```
`mac rd, rs1, rs2` β R-type, opcode `0001011` (RISC-V custom-0 space)
---
## βοΈ Hardware Architecture
The datapath below shows how `MatrixALU` plugs into the writeback stage. The Register File gains a third read port (`rd / h4`) so the old accumulator value is available every cycle. A 3-input MUX selects between ALU, Data Memory, and MAC result via a 2-bit `ResultSrc`.

### Modified Modules
| Module | Modification |
|---|---|
| `MatrixALU.v` | New 32-bit signed Multiply-Accumulate unit |
| `Register_File.v` | Third read port (A4/RD4) to read `rd` for accumulation |
| `Mux.v` | Extended 2β3 input (ALU / Memory / MAC) with 2-bit select |
| `Main_Decoder.v` | Detects custom-0 opcode and asserts `MAC_Enable` |
| `Control_Unit_Top.v` | Routes `MAC_Enable` through the control path |
| `Single_Cycle_Top.v` | Integrates `MatrixALU` into the writeback stage |
---
## π Results
### Simulation Waveform β 16-MAC Benchmark
The waveform below shows all control signals across 16 consecutive MAC cycles. `MAC_Enable` and `RegWrite` stay high for every MAC instruction and drop exactly at the store β confirming the decoder and datapath are working correctly with no stray cycles.

### 4Γ4 Matrix MAC Benchmark β Real Simulation Numbers
Both versions were compiled and simulated on the same processor using Icarus Verilog. The standard version uses `mul`+`add` pairs. The MAC version uses the custom `mac` instruction. Results captured directly from simulation output:

| Metric | Standard (`mul`+`add`) | Matrix-RISCV (`mac`) | Reduction |
|---|---|---|---|
| Total instructions | 33 | 17 | **~48.5%** |
| Register writes | 32 | 16 | **50%** |
| Instruction memory traffic | 132 bytes | 68 bytes | **~48.5%** |
| MAC instructions | 0 | 16 | β |
> These are real numbers from simulation, not theoretical estimates. Full logs in `result_mac.txt` and `result_standard.txt`.
### Original 4-MAC Functional Verification
Real terminal output confirming correct chained accumulation:

```
Cycle 1: Instr=0262828b MAC=1 RegWrite=1 MACResult=000002d6 β 726
Cycle 2: Instr=0262828b MAC=1 RegWrite=1 MACResult=00001f32 β 7,986
Cycle 3: Instr=0262828b MAC=1 RegWrite=1 MACResult=00015726 β 87,846
Cycle 4: Instr=0262828b MAC=1 RegWrite=1 MACResult=000ebea2 β 966,306
Simulation finished.
```
---
## π Quick Start
**Prerequisites**
- [Icarus Verilog](http://iverilog.icarus.com/) (`iverilog`)
**Clone & Simulate**
```bash
git clone https://github.com/celpha2svx/matrix-riscv.git
cd matrix-riscv
iverilog -o simv Single_Cycle_Top.v Single_Cycle_Top_Tb.v
./simv
```
**Run the 4Γ4 Benchmark**
```bash
# MAC version
cp matmul_mac.hex memfile.hex
iverilog -o bench_mac Single_Cycle_Top.v Benchmark_Tb.v && ./bench_mac
# Standard version
cp matmul_standard.hex memfile.hex
iverilog -o bench_std Single_Cycle_Top.v Benchmark_Tb.v && ./bench_std
```
**Expected Output (MAC version)**
```
Cycle 1: Instr=0262828b MAC=1 RegWrite=1 MACResult=00000042
...
Cycle 16: Instr=0262828b MAC=1 RegWrite=1 MACResult=1442a086
========================================
BENCHMARK RESULTS
========================================
Total instructions executed : 17
MAC instructions : 16
Register writes : 16
Instruction memory traffic : 68 bytes
========================================
```
---
## π File Reference
| File | Description |
|---|---|
| `MatrixALU.v` | Custom 32-bit signed MAC hardware unit |
| `Register_File.v` | Extended register file with third read port |
| `Mux.v` | 3-input multiplexer for writeback `ResultSrc` |
| `Main_Decoder.v` | Control decoder with custom-0 opcode support |
| `Control_Unit_Top.v` | Top-level control unit routing `MAC_Enable` |
| `Single_Cycle_Top.v` | Full processor with MAC datapath integrated |
| `Single_Cycle_Top_Tb.v` | Original testbench (4-MAC verification) |
| `Benchmark_Tb.v` | Extended testbench for 4Γ4 benchmark with counters |
| `mac_bench.hex` | Original test program: 4 MACs + store |
| `matmul_mac.hex` | 4Γ4 benchmark: 16 MAC instructions |
| `matmul_standard.hex` | 4Γ4 benchmark: 32 standard mul+add instructions |
| `result_mac.txt` | Full simulation log β MAC version |
| `result_standard.txt` | Full simulation log β standard version |
| `benchmark_chart.png` | Bar chart comparing both approaches |
| `waveform.png` | Signal waveform across 16-MAC benchmark |
| `plot_benchmark.py` | Python script that generated the benchmark chart |
| `plot_waveform.py` | Python script that generated the waveform figure |
---
## πΊοΈ Roadmap
- [ ] FPGA synthesis (Tang Nano / ICE40 target)
- [ ] Vector MAC for SIMD-style parallelism
- [ ] Integration with TinyML inference
- [ ] Memory bandwidth measurement on physical hardware
- [ ] Paper submission β RISC-V Summit / CARRV workshop
---
## π€ Author
**Ademuyiwa Afeez** β Building efficient hardware for resource-constrained machine learning.
> *"We don't need bigger machines. We need smarter architectures."*
---
## π License
[MIT](LICENSE) β Build on it. Improve it. Share it.