Skip to content

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)