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)
]