read from instruction memory using FetchUnitInterface
[soc.git] / src / soc / experiment / imem.py
1 from soc.minerva.units.fetch import FetchUnitInterface
2 from nmigen import Signal, Module, Elaboratable, Mux
3 from soc.experiment.testmem import TestMemory
4 from nmigen.cli import rtlil
5
6
7 class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
8
9 def __init__(self, addr_wid=32, data_wid=32):
10 print ("testmemfetchunit", addr_wid, data_wid)
11 super().__init__(addr_wid=addr_wid, data_wid=data_wid)
12 # limit TestMemory to 2^6 entries of regwid size
13 self.mem = TestMemory(self.data_wid, 6, readonly=True)
14
15 def elaborate(self, platform):
16 m = Module()
17 regwid, addrwid = self.data_wid, self.addr_wid
18 adr_lsb = self.adr_lsbs
19
20 m.submodules.mem = mem = self.mem
21
22 do_fetch = Signal() # set when fetch while valid and not stalled
23 m.d.comb += do_fetch.eq(self.a_valid_i & ~self.a_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_fetch): # 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_fetch): # done
35 m.d.sync += op_in_progress.eq(0)
36
37 m.d.comb += self.a_busy_o.eq(op_actioned & self.a_valid_i)
38 # fetch
39 m.d.comb += mem.rdport.addr.eq(self.a_pc_i[adr_lsb:])
40 m.d.comb += self.f_instr_o.eq(mem.rdport.data)
41
42 return m
43
44 def __iter__(self): # TODO
45 yield self.a_pc_i
46 yield self.f_instr_o
47
48 def ports(self):
49 return list(self)
50
51 if __name__ == '__main__':
52 dut = TestMemFetchUnit(addr_wid=32, data_wid=32)
53 vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
54 with open("test_imem.il", "w") as f:
55 f.write(vl)
56