add debugging and buffering to CacheRam
[soc.git] / src / soc / experiment / cache_ram.py
1 # TODO: replace with Memory at some point
2 from nmigen import Elaboratable, Signal, Array, Module
3 from nmutil.util import Display
4
5 class CacheRam(Elaboratable):
6
7 def __init__(self, ROW_BITS=16, WIDTH = 64, TRACE=True, ADD_BUF=False):
8 self.ROW_BITS = ROW_BITS
9 self.WIDTH = WIDTH
10 self.TRACE = TRACE
11 self.ADD_BUF = ADD_BUF
12 self.rd_en = Signal()
13 self.rd_addr = Signal(ROW_BITS)
14 self.rd_data_o = Signal(WIDTH)
15 self.wr_sel = Signal(WIDTH//8)
16 self.wr_addr = Signal(ROW_BITS)
17 self.wr_data = Signal(WIDTH)
18
19 def elaborate(self, platform):
20 m = Module()
21 comb, sync = m.d.comb, m.d.sync
22
23 ROW_BITS = self.ROW_BITS
24 WIDTH = self.WIDTH
25 TRACE = self.TRACE
26 ADD_BUF = self.ADD_BUF
27 SIZE = 2**ROW_BITS
28
29 ram = Array(Signal(WIDTH) for i in range(SIZE))
30 #attribute ram_style of ram : signal is "block";
31
32 rd_data0 = Signal(WIDTH)
33
34 sel0 = Signal(WIDTH//8) # defaults to zero
35
36 with m.If(TRACE):
37 with m.If(self.wr_sel != sel0):
38 sync += Display( "write a: %x sel: %x dat: %x",
39 self.wr_addr, self.wr_sel, self.wr_data)
40 for i in range(WIDTH//8):
41 lbit = i * 8;
42 mbit = lbit + 8;
43 with m.If(self.wr_sel[i]):
44 sync += ram[self.wr_addr][lbit:mbit].eq(self.wr_data[lbit:mbit])
45 with m.If(self.rd_en):
46 sync += rd_data0.eq(ram[self.rd_addr])
47 if TRACE:
48 sync += Display("read a: %x dat: %x",
49 self.rd_addr, ram[self.rd_addr])
50 pass
51
52
53 if ADD_BUF:
54 sync += self.rd_data_o.eq(rd_data0)
55 else:
56 comb += self.rd_data_o.eq(rd_data0)
57
58 return m