97 lines
3.4 KiB
Markdown
97 lines
3.4 KiB
Markdown
# 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.
|