@@ -0,0 +1,96 @@
# Hardware CRC32 Engine in Matmul IP
## Goal
Replace software CRC32 (80.8% of total time, ~396ms for 5000 groups) with a hardware CRC32 engine embedded in the matmul IP. The CRC32 streams through during DMA reads of C result data, near-zero overhead.
**Expected ** : total time drops from 490ms → ~94ms, score from 51.66 → ~69.
## Requirements
1. **CRC32 table ** : 256× 32 LUTRAM, IEEE 802.3 polynomial 0xEDB88320, identical to software table
2. **Engine ** : 4-byte/cycle combinational CRC32, triggered only when AXI R_CH reads C memory (B0_C/B1_C)
3. **Register ** at offset `0x010` :
- Read: returns `crc_reg ^ 0xFFFFFFFF` (final CRC32)
- Write any value: resets CRC to `0xFFFFFFFF`
4. **Software ** : remove `crc32_table[]` , `compute_crc32()` , and `CRC32 printf` call
- Replace with `REG_RD(MATMUL_CRC)` after all groups complete
5. **No regressions ** : existing AXI read/write, compute engine, DMA, interrupts unchanged
6. **Lint clean ** , Vivado synthesis passes at 33MHz
## Acceptance Criteria
- [ ] **CRC match ** : hardware CRC32 matches software CRC32 for 10-group and 5000-group tests
- [ ] **Correct output ** : `MATMUL_CRC32=d53cd879` (5000 groups, unchanged since matmul compute is identical)
- [ ] **Timing improvement ** : CRC32 component drops from ~396ms to <1ms
- [ ] **No timing violations ** in Vivado (WNS passes)
- [ ] **No DSP ** used (DSP utilization = 0)
- [ ] **Lint clean **
## Definition of Done
- [ ] `matmul_axi_slave.v` : CRC engine added, register at 0x010
- [ ] `user-sample.c` : software CRC removed, hardware CRC read
- [ ] Simulation verifies CRC match (10 groups)
- [ ] Lint + compile pass
- [ ] Synced to regional-submit
## Technical Approach
### Hardware
**CRC32 engine ** in `matmul_axi_slave.v` :
- LUTRAM table: 256 entries × 32 bits, initialized via `initial` block
- 4-byte combinational datapath: `t0→c0→t1→c1→t2→c2→t3→crc_next`
- Triggered when AXI read address hits B0_C or B1_C ranges
- Registered on `posedge clk` when `s_axi_rvalid && s_axi_rready`
- Reset on write to 0x010 (CRC register)
``` verilog
// Simplified combinational chain:
t0 = TABLE [ ( crc_reg [ 7 : 0 ] ^ rdata [ 7 : 0 ] ) ] ;
c0 = t0 ^ { 8 'h00 , crc_reg [ 31 : 8 ] } ;
t1 = TABLE [ ( c0 [ 7 : 0 ] ^ rdata [ 15 : 8 ] ) ] ;
c1 = t1 ^ { 8 'h00 , c0 [ 31 : 8 ] } ;
t2 = TABLE [ ( c1 [ 7 : 0 ] ^ rdata [ 23 : 16 ] ) ] ;
c2 = t2 ^ { 8 'h00 , c1 [ 31 : 8 ] } ;
t3 = TABLE [ ( c2 [ 7 : 0 ] ^ rdata [ 31 : 24 ] ) ] ;
crc_next = t3 ^ { 8 'h00 , c2 [ 31 : 8 ] } ;
```
**Register map ** :
- `0x010` : CRC_VAL (RO returns final CRC; WO resets CRC to 0xFFFFFFFF)
### Software
``` c
// Before main loop: reset CRC
REG_WR ( MATMUL_CRC_CTRL , 1 ) ; // 0xbf500010
// After all DMA + compute:
crc = REG_RD ( MATMUL_CRC_CTRL ) ;
printf ( " MATMUL_CRC32=%08lx \n " , ( unsigned long ) crc ) ;
```
Delete: `crc32_table[256]` , `compute_crc32()` , `t_crc32` timing variables.
## Out of Scope
- Pipelined CRC (combinational at 33MHz is sufficient; pipeline only if timing fails)
- CRC32 for FFT data
- Other polynomial CRC variants
## Technical Notes
### Files to modify
- `rtl/ip/matmul/matmul_axi_slave.v` — add CRC engine + register
- `sdk/software/examples/asm/user-sample.c` — remove software CRC, add hardware CRC read
### Timing expectations
- CRC datapath: 4 LUTRAM reads + 4 XORs in combinational chain
- At 33MHz (30ns cycle), critical path ~15-20ns on LS FPGA → should meet timing
- If Vivado reports WNS violation, fall back to 2-stage pipeline (2 bytes per stage)
### CRC32 byte order verification
The software processes: byte0 (LSB), byte1, byte2, byte3 (MSB). The hardware must match this order.