rtl/l2_cache.sv — L2 Write-Back Cache (historical, single-master)
A 4-way set-associative, 16-set, 8-word-line (2 KiB) write-back cache with pseudo-LRU (round-robin) replacement. Not instantiated in the current design — superseded by duck_coherency_ctrl.sv, which adds the second (NPU DMA) master and the MOESI coherency protocol on top of an identical cache geometry. Kept in the tree as the historical single-master predecessor and as the simpler file to read first before duck_coherency_ctrl.sv's FSM.
Where it fits
Nowhere in the current build. Conceptually, this is what the CPU-only half of duck_coherency_ctrl.sv looks like with the NPU DMA master and MOESI states stripped out.
Parameters
| Name | Value | Meaning |
|---|---|---|
SETS |
16 | Number of sets |
WAYS |
4 | Associativity |
LINE_WORDS |
8 | Words per line (32 bytes) |
DRAM_FILL_CYCLES |
4 | Burst fill latency (documented, not separately enforced — actual fill is ack-paced) |
Ports
| Direction | Name | Width | Description |
|---|---|---|---|
| in | clk, rst_n |
1, 1 | Clock / reset |
| in | cpu_read/cpu_write |
1/1 | Load/store request |
| in | cpu_addr/cpu_wdata |
32/32 | Access address / write data |
| in | cpu_byte_en |
4 | Store byte enables |
| out | cpu_rdata |
32 | Combinational hit read data |
| out | cpu_stall |
1 | High while the miss FSM is busy or on a fresh miss |
| out | dram_read/dram_write |
1/1 | DRAM transaction request |
| out | dram_addr/dram_wdata |
32/32 | DRAM address / write data |
| out | dram_byte_en |
4 | Always 4'hF |
| in | dram_rdata |
32 | DRAM read data |
| in | dram_ack |
1 | DRAM transaction complete pulse |
Functionality
Address decomposition (word-addressed): [31:9] tag (23b), [8:5] set (4b), [4:2] word-in-line (3b). Hit detection is combinational across all 4 ways per set. Write policy is write-back + write-allocate: a store hit sets the line's dirty bit; a miss on a dirty victim triggers an 8-word writeback (ST_WB_START/ST_WB_WAIT) before the 8-word fill (ST_FILL) of the new line, then one ST_DONE gap cycle before the CPU re-issues and hits.
| State | Purpose |
|---|---|
ST_IDLE |
Serve hits; detect misses, pick LRU victim |
ST_WB_START/ST_WB_WAIT |
Writeback dirty victim, 8 words |
ST_FILL |
Burst-fill new line from DRAM, 8 words |
ST_FILL_WR |
(reserved encoding — folded into ST_FILL in the actual FSM) |
ST_DONE |
1-cycle gap before re-serving the CPU |
Example
A store that misses on a dirty line:
cpu_write=1, cpu_addr=X -> miss (way_hit all 0), victim=lru_counter[set]
victim valid && dirty -> ST_WB_START -> ST_WB_WAIT (8x dram_write, wait dram_ack each)
-> ST_FILL (8x dram_read, wait dram_ack each) -> tag/valid/dirty updated, lru++
-> ST_DONE -> ST_IDLE (CPU re-issues the same store, now hits)
Related
- duck_coherency_ctrl.md — the 2-master MOESI-aware cache that replaced this file, identical geometry
- duck_cache_pkg.md — geometry constants reference (docs-only)