Hardware CRC32 engine in matmul IP: 4-byte/cycle combinational, register at 0x010
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{"file": ".trellis/tasks/06-25-hardware-crc32-engine-in-matmul-ip/prd.md", "reason": "PRD with acceptance criteria for verification"}
|
||||
@@ -0,0 +1 @@
|
||||
{"file": ".trellis/tasks/06-25-hardware-crc32-engine-in-matmul-ip/prd.md", "reason": "PRD with CRC32 design and requirements"}
|
||||
@@ -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.
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "hardware-crc32-engine-in-matmul-ip",
|
||||
"name": "hardware-crc32-engine-in-matmul-ip",
|
||||
"title": "Hardware CRC32 engine in matmul IP",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "fallensigh",
|
||||
"assignee": "fallensigh",
|
||||
"createdAt": "2026-06-25",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "no-fft",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
@@ -154,6 +154,173 @@ module matmul_axi_slave (
|
||||
end
|
||||
endfunction
|
||||
|
||||
// ==========================================
|
||||
// CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320)
|
||||
// ==========================================
|
||||
localparam ADDR_CRC = 12'h010;
|
||||
|
||||
reg [31:0] crc32_table [0:255];
|
||||
reg [31:0] crc_reg;
|
||||
|
||||
// Stream CRC: triggered when AXI reads C results
|
||||
reg [31:0] crc_stream_data;
|
||||
reg crc_stream_valid;
|
||||
|
||||
wire [31:0] crc_t0, crc_c0, crc_t1, crc_c1, crc_t2, crc_c2, crc_t3, crc_next;
|
||||
assign crc_t0 = crc32_table[(crc_reg[7:0] ^ crc_stream_data[7:0])];
|
||||
assign crc_c0 = crc_t0 ^ {8'h00, crc_reg[31:8]};
|
||||
assign crc_t1 = crc32_table[(crc_c0[7:0] ^ crc_stream_data[15:8])];
|
||||
assign crc_c1 = crc_t1 ^ {8'h00, crc_c0[31:8]};
|
||||
assign crc_t2 = crc32_table[(crc_c1[7:0] ^ crc_stream_data[23:16])];
|
||||
assign crc_c2 = crc_t2 ^ {8'h00, crc_c1[31:8]};
|
||||
assign crc_t3 = crc32_table[(crc_c2[7:0] ^ crc_stream_data[31:24])];
|
||||
assign crc_next = crc_t3 ^ {8'h00, crc_c2[31:8]};
|
||||
|
||||
// CRC32 Table Initialization (IEEE 802.3 reflected)
|
||||
initial begin
|
||||
crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096;
|
||||
crc32_table[2 ] = 32'hEE0E612C; crc32_table[3 ] = 32'h990951BA;
|
||||
crc32_table[4 ] = 32'h076DC419; crc32_table[5 ] = 32'h706AF48F;
|
||||
crc32_table[6 ] = 32'hE963A535; crc32_table[7 ] = 32'h9E6495A3;
|
||||
crc32_table[8 ] = 32'h0EDB8832; crc32_table[9 ] = 32'h79DCB8A4;
|
||||
crc32_table[10 ] = 32'hE0D5E91E; crc32_table[11 ] = 32'h97D2D988;
|
||||
crc32_table[12 ] = 32'h09B64C2B; crc32_table[13 ] = 32'h7EB17CBD;
|
||||
crc32_table[14 ] = 32'hE7B82D07; crc32_table[15 ] = 32'h90BF1D91;
|
||||
crc32_table[16 ] = 32'h1DB71064; crc32_table[17 ] = 32'h6AB020F2;
|
||||
crc32_table[18 ] = 32'hF3B97148; crc32_table[19 ] = 32'h84BE41DE;
|
||||
crc32_table[20 ] = 32'h1ADAD47D; crc32_table[21 ] = 32'h6DDDE4EB;
|
||||
crc32_table[22 ] = 32'hF4D4B551; crc32_table[23 ] = 32'h83D385C7;
|
||||
crc32_table[24 ] = 32'h136C9856; crc32_table[25 ] = 32'h646BA8C0;
|
||||
crc32_table[26 ] = 32'hFD62F97A; crc32_table[27 ] = 32'h8A65C9EC;
|
||||
crc32_table[28 ] = 32'h14015C4F; crc32_table[29 ] = 32'h63066CD9;
|
||||
crc32_table[30 ] = 32'hFA0F3D63; crc32_table[31 ] = 32'h8D080DF5;
|
||||
crc32_table[32 ] = 32'h3B6E20C8; crc32_table[33 ] = 32'h4C69105E;
|
||||
crc32_table[34 ] = 32'hD56041E4; crc32_table[35 ] = 32'hA2677172;
|
||||
crc32_table[36 ] = 32'h3C03E4D1; crc32_table[37 ] = 32'h4B04D447;
|
||||
crc32_table[38 ] = 32'hD20D85FD; crc32_table[39 ] = 32'hA50AB56B;
|
||||
crc32_table[40 ] = 32'h35B5A8FA; crc32_table[41 ] = 32'h42B2986C;
|
||||
crc32_table[42 ] = 32'hDBBBC9D6; crc32_table[43 ] = 32'hACBCF940;
|
||||
crc32_table[44 ] = 32'h32D86CE3; crc32_table[45 ] = 32'h45DF5C75;
|
||||
crc32_table[46 ] = 32'hDCD60DCF; crc32_table[47 ] = 32'hABD13D59;
|
||||
crc32_table[48 ] = 32'h26D930AC; crc32_table[49 ] = 32'h51DE003A;
|
||||
crc32_table[50 ] = 32'hC8D75180; crc32_table[51 ] = 32'hBFD06116;
|
||||
crc32_table[52 ] = 32'h21B4F4B5; crc32_table[53 ] = 32'h56B3C423;
|
||||
crc32_table[54 ] = 32'hCFBA9599; crc32_table[55 ] = 32'hB8BDA50F;
|
||||
crc32_table[56 ] = 32'h2802B89E; crc32_table[57 ] = 32'h5F058808;
|
||||
crc32_table[58 ] = 32'hC60CD9B2; crc32_table[59 ] = 32'hB10BE924;
|
||||
crc32_table[60 ] = 32'h2F6F7C87; crc32_table[61 ] = 32'h58684C11;
|
||||
crc32_table[62 ] = 32'hC1611DAB; crc32_table[63 ] = 32'hB6662D3D;
|
||||
crc32_table[64 ] = 32'h76DC4190; crc32_table[65 ] = 32'h01DB7106;
|
||||
crc32_table[66 ] = 32'h98D220BC; crc32_table[67 ] = 32'hEFD5102A;
|
||||
crc32_table[68 ] = 32'h71B18589; crc32_table[69 ] = 32'h06B6B51F;
|
||||
crc32_table[70 ] = 32'h9FBFE4A5; crc32_table[71 ] = 32'hE8B8D433;
|
||||
crc32_table[72 ] = 32'h7807C9A2; crc32_table[73 ] = 32'h0F00F934;
|
||||
crc32_table[74 ] = 32'h9609A88E; crc32_table[75 ] = 32'hE10E9818;
|
||||
crc32_table[76 ] = 32'h7F6A0DBB; crc32_table[77 ] = 32'h086D3D2D;
|
||||
crc32_table[78 ] = 32'h91646C97; crc32_table[79 ] = 32'hE6635C01;
|
||||
crc32_table[80 ] = 32'h6B6B51F4; crc32_table[81 ] = 32'h1C6C6162;
|
||||
crc32_table[82 ] = 32'h856530D8; crc32_table[83 ] = 32'hF262004E;
|
||||
crc32_table[84 ] = 32'h6C0695ED; crc32_table[85 ] = 32'h1B01A57B;
|
||||
crc32_table[86 ] = 32'h8208F4C1; crc32_table[87 ] = 32'hF50FC457;
|
||||
crc32_table[88 ] = 32'h65B0D9C6; crc32_table[89 ] = 32'h12B7E950;
|
||||
crc32_table[90 ] = 32'h8BBEB8EA; crc32_table[91 ] = 32'hFCB9887C;
|
||||
crc32_table[92 ] = 32'h62DD1DDF; crc32_table[93 ] = 32'h15DA2D49;
|
||||
crc32_table[94 ] = 32'h8CD37CF3; crc32_table[95 ] = 32'hFBD44C65;
|
||||
crc32_table[96 ] = 32'h4DB26158; crc32_table[97 ] = 32'h3AB551CE;
|
||||
crc32_table[98 ] = 32'hA3BC0074; crc32_table[99 ] = 32'hD4BB30E2;
|
||||
crc32_table[100] = 32'h4ADFA541; crc32_table[101] = 32'h3DD895D7;
|
||||
crc32_table[102] = 32'hA4D1C46D; crc32_table[103] = 32'hD3D6F4FB;
|
||||
crc32_table[104] = 32'h4369E96A; crc32_table[105] = 32'h346ED9FC;
|
||||
crc32_table[106] = 32'hAD678846; crc32_table[107] = 32'hDA60B8D0;
|
||||
crc32_table[108] = 32'h44042D73; crc32_table[109] = 32'h33031DE5;
|
||||
crc32_table[110] = 32'hAA0A4C5F; crc32_table[111] = 32'hDD0D7CC9;
|
||||
crc32_table[112] = 32'h5005713C; crc32_table[113] = 32'h270241AA;
|
||||
crc32_table[114] = 32'hBE0B1010; crc32_table[115] = 32'hC90C2086;
|
||||
crc32_table[116] = 32'h5768B525; crc32_table[117] = 32'h206F85B3;
|
||||
crc32_table[118] = 32'hB966D409; crc32_table[119] = 32'hCE61E49F;
|
||||
crc32_table[120] = 32'h5EDEF90E; crc32_table[121] = 32'h29D9C998;
|
||||
crc32_table[122] = 32'hB0D09822; crc32_table[123] = 32'hC7D7A8B4;
|
||||
crc32_table[124] = 32'h59B33D17; crc32_table[125] = 32'h2EB40D81;
|
||||
crc32_table[126] = 32'hB7BD5C3B; crc32_table[127] = 32'hC0BA6CAD;
|
||||
crc32_table[128] = 32'hEDB88320; crc32_table[129] = 32'h9ABFB3B6;
|
||||
crc32_table[130] = 32'h03B6E20C; crc32_table[131] = 32'h74B1D29A;
|
||||
crc32_table[132] = 32'hEAD54739; crc32_table[133] = 32'h9DD277AF;
|
||||
crc32_table[134] = 32'h04DB2615; crc32_table[135] = 32'h73DC1683;
|
||||
crc32_table[136] = 32'hE3630B12; crc32_table[137] = 32'h94643B84;
|
||||
crc32_table[138] = 32'h0D6D6A3E; crc32_table[139] = 32'h7A6A5AA8;
|
||||
crc32_table[140] = 32'hE40ECF0B; crc32_table[141] = 32'h9309FF9D;
|
||||
crc32_table[142] = 32'h0A00AE27; crc32_table[143] = 32'h7D079EB1;
|
||||
crc32_table[144] = 32'hF00F9344; crc32_table[145] = 32'h8708A3D2;
|
||||
crc32_table[146] = 32'h1E01F268; crc32_table[147] = 32'h6906C2FE;
|
||||
crc32_table[148] = 32'hF762575D; crc32_table[149] = 32'h806567CB;
|
||||
crc32_table[150] = 32'h196C3671; crc32_table[151] = 32'h6E6B06E7;
|
||||
crc32_table[152] = 32'hFED41B76; crc32_table[153] = 32'h89D32BE0;
|
||||
crc32_table[154] = 32'h10DA7A5A; crc32_table[155] = 32'h67DD4ACC;
|
||||
crc32_table[156] = 32'hF9B9DF6F; crc32_table[157] = 32'h8EBEEFF9;
|
||||
crc32_table[158] = 32'h17B7BE43; crc32_table[159] = 32'h60B08ED5;
|
||||
crc32_table[160] = 32'hD6D6A3E8; crc32_table[161] = 32'hA1D1937E;
|
||||
crc32_table[162] = 32'h38D8C2C4; crc32_table[163] = 32'h4FDFF252;
|
||||
crc32_table[164] = 32'hD1BB67F1; crc32_table[165] = 32'hA6BC5767;
|
||||
crc32_table[166] = 32'h3FB506DD; crc32_table[167] = 32'h48B2364B;
|
||||
crc32_table[168] = 32'hD80D2BDA; crc32_table[169] = 32'hAF0A1B4C;
|
||||
crc32_table[170] = 32'h36034AF6; crc32_table[171] = 32'h41047A60;
|
||||
crc32_table[172] = 32'hDF60EFC3; crc32_table[173] = 32'hA867DF55;
|
||||
crc32_table[174] = 32'h316E8EEF; crc32_table[175] = 32'h4669BE79;
|
||||
crc32_table[176] = 32'hCB61B38C; crc32_table[177] = 32'hBC66831A;
|
||||
crc32_table[178] = 32'h256FD2A0; crc32_table[179] = 32'h5268E236;
|
||||
crc32_table[180] = 32'hCC0C7795; crc32_table[181] = 32'hBB0B4703;
|
||||
crc32_table[182] = 32'h220216B9; crc32_table[183] = 32'h5505262F;
|
||||
crc32_table[184] = 32'hC5BA3BBE; crc32_table[185] = 32'hB2BD0B28;
|
||||
crc32_table[186] = 32'h2BB45A92; crc32_table[187] = 32'h5CB36A04;
|
||||
crc32_table[188] = 32'hC2D7FFA7; crc32_table[189] = 32'hB5D0CF31;
|
||||
crc32_table[190] = 32'h2CD99E8B; crc32_table[191] = 32'h5BDEAE1D;
|
||||
crc32_table[192] = 32'h9B64C2B0; crc32_table[193] = 32'hEC63F226;
|
||||
crc32_table[194] = 32'h756AA39C; crc32_table[195] = 32'h026D930A;
|
||||
crc32_table[196] = 32'h9C0906A9; crc32_table[197] = 32'hEB0E363F;
|
||||
crc32_table[198] = 32'h72076785; crc32_table[199] = 32'h05005713;
|
||||
crc32_table[200] = 32'h95BF4A82; crc32_table[201] = 32'hE2B87A14;
|
||||
crc32_table[202] = 32'h7BB12BAE; crc32_table[203] = 32'h0CB61B38;
|
||||
crc32_table[204] = 32'h92D28E9B; crc32_table[205] = 32'hE5D5BE0D;
|
||||
crc32_table[206] = 32'h7CDCEFB7; crc32_table[207] = 32'h0BDBDF21;
|
||||
crc32_table[208] = 32'h86D3D2D4; crc32_table[209] = 32'hF1D4E242;
|
||||
crc32_table[210] = 32'h68DDB3F8; crc32_table[211] = 32'h1FDA836E;
|
||||
crc32_table[212] = 32'h81BE16CD; crc32_table[213] = 32'hF6B9265B;
|
||||
crc32_table[214] = 32'h6FB077E1; crc32_table[215] = 32'h18B74777;
|
||||
crc32_table[216] = 32'h88085AE6; crc32_table[217] = 32'hFF0F6A70;
|
||||
crc32_table[218] = 32'h66063BCA; crc32_table[219] = 32'h11010B5C;
|
||||
crc32_table[220] = 32'h8F659EFF; crc32_table[221] = 32'hF862AE69;
|
||||
crc32_table[222] = 32'h616BFFD3; crc32_table[223] = 32'h166CCF45;
|
||||
crc32_table[224] = 32'hA00AE278; crc32_table[225] = 32'hD70DD2EE;
|
||||
crc32_table[226] = 32'h4E048354; crc32_table[227] = 32'h3903B3C2;
|
||||
crc32_table[228] = 32'hA7672661; crc32_table[229] = 32'hD06016F7;
|
||||
crc32_table[230] = 32'h4969474D; crc32_table[231] = 32'h3E6E77DB;
|
||||
crc32_table[232] = 32'hAED16A4A; crc32_table[233] = 32'hD9D65ADC;
|
||||
crc32_table[234] = 32'h40DF0B66; crc32_table[235] = 32'h37D83BF0;
|
||||
crc32_table[236] = 32'hA9BCAE53; crc32_table[237] = 32'hDEBB9EC5;
|
||||
crc32_table[238] = 32'h47B2CF7F; crc32_table[239] = 32'h30B5FFE9;
|
||||
crc32_table[240] = 32'hBDBDF21C; crc32_table[241] = 32'hCABAC28A;
|
||||
crc32_table[242] = 32'h53B39330; crc32_table[243] = 32'h24B4A3A6;
|
||||
crc32_table[244] = 32'hBAD03605; crc32_table[245] = 32'hCDD70693;
|
||||
crc32_table[246] = 32'h54DE5729; crc32_table[247] = 32'h23D967BF;
|
||||
crc32_table[248] = 32'hB3667A2E; crc32_table[249] = 32'hC4614AB8;
|
||||
crc32_table[250] = 32'h5D681B02; crc32_table[251] = 32'h2A6F2B94;
|
||||
crc32_table[252] = 32'hB40BBE37; crc32_table[253] = 32'hC30C8EA1;
|
||||
crc32_table[254] = 32'h5A05DF1B; crc32_table[255] = 32'h2D02EF8D;
|
||||
end
|
||||
|
||||
// CRC register update: stream when reading C data, reset on write
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
crc_reg <= 32'hFFFFFFFF;
|
||||
crc_stream_valid <= 1'b0;
|
||||
end else begin
|
||||
if (crc_stream_valid)
|
||||
crc_reg <= crc_next;
|
||||
else
|
||||
crc_stream_valid <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// ==========================================
|
||||
// AXI Write 通道逻辑 (支持 INCR Burst)
|
||||
// ==========================================
|
||||
@@ -220,8 +387,11 @@ module matmul_axi_slave (
|
||||
if (s_axi_wdata[1]) req_1 <= 1'b1; // 启动 Bank 1
|
||||
end
|
||||
else if (w_offset == ADDR_STATUS) begin
|
||||
if (s_axi_wdata[1]) done <= 1'b0; // 写 1 清零 Done (兼容旧版TB)
|
||||
if (s_axi_wdata[2]) error <= 1'b0; // 写 1 清零 Error
|
||||
if (s_axi_wdata[1]) done <= 1'b0;
|
||||
if (s_axi_wdata[2]) error <= 1'b0;
|
||||
end
|
||||
else if (w_offset == ADDR_CRC) begin
|
||||
crc_reg <= 32'hFFFFFFFF; // 写任意值复位 CRC
|
||||
end
|
||||
else if (w_offset >= ADDR_B0_A && w_offset < ADDR_B0_B)
|
||||
b0_a[(w_offset - ADDR_B0_A) >> 2] <= apply_wstrb(b0_a[(w_offset - ADDR_B0_A) >> 2], s_axi_wdata, s_axi_wstrb);
|
||||
@@ -308,6 +478,11 @@ module matmul_axi_slave (
|
||||
end
|
||||
R_DATA: begin
|
||||
if (s_axi_rvalid && s_axi_rready) begin
|
||||
// CRC32 stream: feed read data when in C result range
|
||||
if (crc_read_en) begin
|
||||
crc_stream_data <= s_axi_rdata;
|
||||
crc_stream_valid <= 1'b1;
|
||||
end
|
||||
if (r_cnt == r_len) begin
|
||||
s_axi_rvalid <= 1'b0;
|
||||
s_axi_rlast <= 1'b0;
|
||||
@@ -328,12 +503,18 @@ module matmul_axi_slave (
|
||||
// 修复:将 wire 声明提取到 always 块外部
|
||||
wire [11:0] current_r_offset = (r_state == R_DATA) ? r_offset : s_axi_araddr[11:0];
|
||||
|
||||
// CRC stream trigger: valid when reading C result data
|
||||
wire crc_read_en = (r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) ||
|
||||
(r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_C + 12'h0C0));
|
||||
|
||||
// 组合逻辑准备 Read 数据
|
||||
always @(*) begin
|
||||
s_axi_rdata = 32'b0;
|
||||
if (r_state == R_DATA || (r_state == R_IDLE && s_axi_arvalid)) begin
|
||||
if (current_r_offset == ADDR_CTRL)
|
||||
s_axi_rdata = {30'b0, req_1, req_0};
|
||||
else if (current_r_offset == ADDR_CRC)
|
||||
s_axi_rdata = crc_reg ^ 32'hFFFFFFFF;
|
||||
else if (current_r_offset == ADDR_STATUS)
|
||||
s_axi_rdata = {29'b0, error, done, busy};
|
||||
else if (current_r_offset >= ADDR_B0_A && current_r_offset < ADDR_B0_B)
|
||||
|
||||
1162
sdk/axi_ram.mif
1162
sdk/axi_ram.mif
File diff suppressed because it is too large
Load Diff
@@ -59,46 +59,13 @@ unsigned long CORE_CLOCKS_PER_SEC = 33000000L;
|
||||
#define STATUS_DONE 0x2
|
||||
#define STATUS_ERROR 0x4
|
||||
|
||||
// Hardware CRC register (offset 0x010 in matmul IP)
|
||||
#define MATMUL_CRC (MATMUL_BASE_UNCACHED + 0x010)
|
||||
|
||||
/* ─── Convenience macros ──────────────────────────────────────────── */
|
||||
#define REG_WR(addr, val) (*(volatile uint32_t *)(addr) = (uint32_t)(val))
|
||||
#define REG_RD(addr) (*(volatile uint32_t *)(addr))
|
||||
|
||||
/* ─── CRC32 table (IEEE 802.3, polynomial 0xEDB88320) ─────────────── */
|
||||
static const uint32_t crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||
};
|
||||
|
||||
static volatile int matmul_done_flag = 0;
|
||||
static volatile int dma0_done_flag = 0;
|
||||
static volatile int dma1_done_flag = 0;
|
||||
@@ -138,29 +105,13 @@ static void wait_dma_done_intr(int ch)
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── CRC32 over ExtRAM result region ─────────────────────────────── */
|
||||
static uint32_t compute_crc32(volatile uint32_t *extram)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
uint32_t i, w;
|
||||
|
||||
for (i = 0; i < RESULT_WORDS; i++) {
|
||||
w = extram[DST_BASE_WORDS + i];
|
||||
crc = crc32_table[(crc ^ (w & 0xFF)) & 0xFF] ^ (crc >> 8);
|
||||
crc = crc32_table[(crc ^ ((w >> 8) & 0xFF)) & 0xFF] ^ (crc >> 8);
|
||||
crc = crc32_table[(crc ^ ((w >> 16) & 0xFF)) & 0xFF] ^ (crc >> 8);
|
||||
crc = crc32_table[(crc ^ (w >> 24) ) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════ */
|
||||
int main(void)
|
||||
{
|
||||
if (MATMUL_GROUP_NUM <= 0) return 0;
|
||||
|
||||
volatile uint32_t *extram = (volatile uint32_t *)EXTRAM_BASE_UNCACHED;
|
||||
uint32_t crc, t_prologue, t_mainloop, t_epilogue, t_crc32;
|
||||
uint32_t crc, t_prologue, t_mainloop, t_epilogue;
|
||||
int g;
|
||||
|
||||
// Ping-Pong Register Address Arrays (Physical for DMA)
|
||||
@@ -175,6 +126,7 @@ int main(void)
|
||||
|
||||
// 清理寄存器状态
|
||||
REG_WR(MATMUL_STATUS, STATUS_DONE | STATUS_ERROR);
|
||||
REG_WR(MATMUL_CRC, 0); // 复位硬件 CRC32 为 0xFFFFFFFF
|
||||
|
||||
/* ── Prologue: 第0组数据初始化 ────────────────────────── */
|
||||
t_prologue = get_ns();
|
||||
@@ -228,10 +180,8 @@ int main(void)
|
||||
wait_dma_done_intr(1);
|
||||
t_epilogue = get_ns() - t_epilogue;
|
||||
|
||||
/* ── CRC32 over result region ─────────────────────────────── */
|
||||
t_crc32 = get_ns();
|
||||
crc = compute_crc32(extram);
|
||||
t_crc32 = get_ns() - t_crc32;
|
||||
/* ── Read hardware CRC32 result ──────────────────────────── */
|
||||
crc = REG_RD(MATMUL_CRC);
|
||||
|
||||
/* ── Final markers ────────────────────────────────────────── */
|
||||
printf("MATMUL_CRC32=%08lx\n", (unsigned long)crc);
|
||||
@@ -239,8 +189,7 @@ int main(void)
|
||||
printf("TIME_LOOP=%lu\n", (unsigned long)t_mainloop);
|
||||
printf("TIME_LOOP_PER=%lu\n", (unsigned long)(t_mainloop / MATMUL_GROUP_NUM));
|
||||
printf("TIME_EPILOGUE=%lu\n", (unsigned long)t_epilogue);
|
||||
printf("TIME_CRC32=%lu\n", (unsigned long)t_crc32);
|
||||
printf("TIME_TOTAL=%lu\n", (unsigned long)(t_prologue + t_mainloop + t_epilogue + t_crc32));
|
||||
printf("TIME_TOTAL=%lu\n", (unsigned long)(t_prologue + t_mainloop + t_epilogue));
|
||||
printf("MATMUL_DONE\n");
|
||||
|
||||
return 0;
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user