a79b68723a566e8bfcc88c97033949c8453ad3ec
[soc.git] / src / soc / experiment / cache_ram.py
1 # TODO: replace with Memory at some point
2 from nmigen import Elaboratable, Signal, Array, Module, Memory
3 from nmutil.util import Display
4
5
6 class CacheRam(Elaboratable):
7
8 def __init__(self, ROW_BITS=16, WIDTH = 64, TRACE=True, ADD_BUF=False,
9 ram_num=0):
10 self.ram_num = ram_num # for debug reporting
11 self.ROW_BITS = ROW_BITS
12 self.WIDTH = WIDTH
13 self.TRACE = TRACE
14 self.ADD_BUF = ADD_BUF
15 self.rd_en = Signal()
16 self.rd_addr = Signal(ROW_BITS)
17 self.rd_data_o = Signal(WIDTH)
18 self.wr_sel = Signal(WIDTH//8)
19 self.wr_addr = Signal(ROW_BITS)
20 self.wr_data = Signal(WIDTH)
21
22 def elaborate(self, platform):
23 m = Module()
24 comb, sync = m.d.comb, m.d.sync
25
26 ROW_BITS = self.ROW_BITS
27 WIDTH = self.WIDTH
28 TRACE = self.TRACE
29 ADD_BUF = self.ADD_BUF
30 SIZE = 2**ROW_BITS
31
32 # set up the Cache RAM Memory and create one read and one write port
33 # the read port is *not* transparent (does not pass write-thru-read)
34 #attribute ram_style of ram : signal is "block";
35 ram = Memory(depth=SIZE, width=WIDTH)
36 m.submodules.rdport = rdport = ram.read_port(transparent=False)
37 m.submodules.wrport = wrport = ram.write_port(granularity=8)
38
39 with m.If(TRACE):
40 with m.If(self.wr_sel.bool()):
41 sync += Display( "write ramno %d a: %%x "
42 "sel: %%x dat: %%x" % self.ram_num,
43 self.wr_addr,
44 self.wr_sel, self.wr_data)
45
46 # read data output and a latched copy. behaves like microwatt cacheram
47 rd_data0 = Signal(WIDTH)
48 rd_data0l = Signal(WIDTH)
49
50 # delay on read address/en
51 rd_delay = Signal()
52 rd_delay_addr = Signal.like(self.rd_addr)
53 sync += rd_delay_addr.eq(self.rd_addr)
54 sync += rd_delay.eq(self.rd_en)
55
56 # write port
57 comb += wrport.addr.eq(self.wr_addr)
58 comb += wrport.en.eq(self.wr_sel)
59 comb += wrport.data.eq(self.wr_data)
60
61 # read port (include a latch on the output, for microwatt compatibility)
62 comb += rdport.addr.eq(self.rd_addr)
63 comb += rdport.en.eq(self.rd_en)
64 with m.If(rd_delay):
65 comb += rd_data0.eq(rdport.data)
66 sync += rd_data0l.eq(rd_data0) # preserve latched data
67 with m.Else():
68 comb += rd_data0.eq(rd_data0l) # output latched (last-read)
69
70 if TRACE:
71 with m.If(rd_delay):
72 sync += Display("read ramno %d a: %%x dat: %%x" % self.ram_num,
73 rd_delay_addr, rd_data0)
74 pass
75
76 # extra delay requested?
77 if ADD_BUF:
78 sync += self.rd_data_o.eq(rd_data0)
79 else:
80 comb += self.rd_data_o.eq(rd_data0)
81
82 return m