add test instruction memory
[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 elaborate(self, platform):
10 m = Module()
11 regwid, addrwid = self.data_wid, self.addr_wid
12 adr_lsb = self.adr_lsbs
13
14 # limit TestMemory to 2^6 entries of regwid size
15 m.submodules.mem = mem = TestMemory(regwid, 6, readonly=True)
16
17 do_fetch = Signal() # set when fetch while valid and not stalled
18 m.d.comb += do_fetch.eq(self.a_valid_i & ~self.a_stall_i)
19
20 # bit of a messy FSM that progresses from idle to in progress
21 # to done.
22 op_actioned = Signal(reset=0)
23 op_in_progress = Signal(reset=0)
24 with m.If(~op_actioned & do_fetch): # idle
25 m.d.sync += op_actioned.eq(1)
26 m.d.sync += op_in_progress.eq(1)
27 with m.Elif(op_in_progress): # in progress
28 m.d.sync += op_actioned.eq(0)
29 with m.If(~do_fetch): # done
30 m.d.sync += op_in_progress.eq(0)
31
32 m.d.comb += self.a_busy_o.eq(op_actioned & self.a_valid_i)
33 # fetch
34 m.d.comb += mem.rdport.addr.eq(self.a_pc_i[adr_lsb:])
35 m.d.comb += self.f_instr_o.eq(mem.rdport.data)
36
37 return m
38
39
40 if __name__ == '__main__':
41 dut = TestMemFetchUnit(addr_wid=32, data_wid=32)
42 vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
43 with open("test_imem.il", "w") as f:
44 f.write(vl)
45