first attempt at 3) of
[soc.git] / src / soc / experiment / lsmem.py
1 from soc.minerva.units.loadstore import LoadStoreUnitInterface
2 from nmigen import Signal, Module, Elaboratable, Mux
3 from nmigen.utils import log2_int
4 from soc.experiment.testmem import TestMemory # TODO: replace with TMLSUI
5 from nmigen.cli import rtlil
6
7
8 class TestMemLoadStoreUnit(LoadStoreUnitInterface, Elaboratable):
9
10 def elaborate(self, platform):
11 m = Module()
12 regwid, addrwid, mask_wid = self.data_wid, self.addr_wid, self.mask_wid
13 adr_lsb = self.adr_lsbs
14
15 # limit TestMemory to 2^6 entries of regwid size
16 m.submodules.mem = mem = TestMemory(regwid, 6, granularity=8)
17
18 do_load = Signal() # set when load while valid and not stalled
19 do_store = Signal() # set when store while valid and not stalled
20
21 m.d.comb += [
22 do_load.eq(self.x_ld_i & (self.x_valid_i & ~self.x_stall_i)),
23 do_store.eq(self.x_st_i & (self.x_valid_i & ~self.x_stall_i)),
24 ]
25 # bit of a messy FSM that progresses from idle to in progress
26 # to done.
27 op_actioned = Signal(reset=0)
28 op_in_progress = Signal(reset=0)
29 with m.If(~op_actioned & (do_load | do_store)): # idle
30 m.d.sync += op_actioned.eq(1)
31 m.d.sync += op_in_progress.eq(1)
32 with m.Elif(op_in_progress): # in progress
33 m.d.sync += op_actioned.eq(0)
34 with m.If(~(do_load | do_store)): # done
35 m.d.sync += op_in_progress.eq(0)
36
37 m.d.comb += self.x_busy_o.eq(op_actioned & self.x_valid_i)
38
39 m.d.comb += [
40 # load
41 mem.rdport.addr.eq(self.x_addr_i[adr_lsb:]),
42 self.m_ld_data_o.eq(mem.rdport.data),
43
44 # store - only activates once
45 mem.wrport.addr.eq(self.x_addr_i[adr_lsb:]),
46 mem.wrport.en.eq(Mux(do_store & ~op_actioned,
47 self.x_mask_i, 0)),
48 mem.wrport.data.eq(self.x_st_data_i)
49 ]
50
51 return m
52
53
54 if __name__ == '__main__':
55 dut = TestMemLoadStoreUnit(regwid=32, addrwid=4)
56 vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
57 with open("test_lsmem.il", "w") as f:
58 f.write(vl)
59