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