--- /dev/null
+from soc.minerva.units.fetch import FetchUnitInterface
+from nmigen import Signal, Module, Elaboratable, Mux
+from soc.experiment.testmem import TestMemory
+from nmigen.cli import rtlil
+
+
+class TestMemFetchUnit(FetchUnitInterface, Elaboratable):
+
+    def elaborate(self, platform):
+        m = Module()
+        regwid, addrwid = self.data_wid, self.addr_wid
+        adr_lsb = self.adr_lsbs
+
+        # limit TestMemory to 2^6 entries of regwid size
+        m.submodules.mem = mem = TestMemory(regwid, 6, readonly=True)
+
+        do_fetch = Signal()  # set when fetch while valid and not stalled
+        m.d.comb += do_fetch.eq(self.a_valid_i & ~self.a_stall_i)
+
+        # bit of a messy FSM that progresses from idle to in progress
+        # to done.
+        op_actioned = Signal(reset=0)
+        op_in_progress = Signal(reset=0)
+        with m.If(~op_actioned & do_fetch): # idle
+            m.d.sync += op_actioned.eq(1)
+            m.d.sync += op_in_progress.eq(1)
+        with m.Elif(op_in_progress):                    # in progress
+            m.d.sync += op_actioned.eq(0)
+        with m.If(~do_fetch):               # done
+            m.d.sync += op_in_progress.eq(0)
+
+        m.d.comb += self.a_busy_o.eq(op_actioned & self.a_valid_i)
+        # fetch
+        m.d.comb += mem.rdport.addr.eq(self.a_pc_i[adr_lsb:])
+        m.d.comb += self.f_instr_o.eq(mem.rdport.data)
+
+        return m
+
+
+if __name__ == '__main__':
+    dut = TestMemFetchUnit(addr_wid=32, data_wid=32)
+    vl = rtlil.convert(dut, ports=[]) # TODOdut.ports())
+    with open("test_imem.il", "w") as f:
+        f.write(vl)
+