turn CompALU/CompLDST latches synchronous
[soc.git] / src / soc / experiment / lsmem.py
index e926017646bca872e940e584b37337c766f991f8..11a1ba81a14c020d15f9b3268604a7102b54b3e4 100644 (file)
@@ -6,35 +6,45 @@ from nmigen.cli import rtlil
 
 
 class TestMemLoadStoreUnit(LoadStoreUnitInterface, Elaboratable):
-    def __init__(self, addr_wid=32, mask_wid=4, data_wid=32):
-        super().__init__()
-        self.regwid = data_wid
-        self.addrwid = addr_wid
-        self.mask_wid = mask_wid
 
     def elaborate(self, platform):
         m = Module()
-        regwid, addrwid, mask_wid = self.regwid, self.addrwid, self.mask_wid
+        regwid, addrwid, mask_wid = self.data_wid, self.addr_wid, self.mask_wid
         adr_lsb = self.adr_lsbs
 
         # limit TestMemory to 2^6 entries of regwid size
         m.submodules.mem = mem = TestMemory(regwid, 6, granularity=8)
 
-        do_load = Signal()  # set when doing a load while valid and not stalled
-        do_store = Signal() # set when doing a store while valid and not stalled
+        do_load = Signal()  # set when load while valid and not stalled
+        do_store = Signal() # set when store while valid and not stalled
 
         m.d.comb += [
-            do_load.eq(self.x_ld_i & (self.x_valid_i & ~self.x_stall_i)),
-            do_store.eq(self.x_st_i & (self.x_valid_i & ~self.x_stall_i)),
+            do_load.eq(self.x_ld_i & (self.x_i_valid & ~self.x_stall_i)),
+            do_store.eq(self.x_st_i & (self.x_i_valid & ~self.x_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_load | do_store)): # 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_load | do_store)):               # done
+            m.d.sync += op_in_progress.eq(0)
+
+        m.d.comb += self.x_busy_o.eq(op_actioned & self.x_i_valid)
+
         m.d.comb += [
             # load
             mem.rdport.addr.eq(self.x_addr_i[adr_lsb:]),
             self.m_ld_data_o.eq(mem.rdport.data),
 
-            # store
+            # store - only activates once
             mem.wrport.addr.eq(self.x_addr_i[adr_lsb:]),
-            mem.wrport.en.eq(Mux(do_store, self.x_mask_i, 0)),
+            mem.wrport.en.eq(Mux(do_store & ~op_actioned,
+                                 self.x_mask_i, 0)),
             mem.wrport.data.eq(self.x_st_data_i)
             ]