diff --git a/litedram/common.py b/litedram/common.py index d353954..e5b600e 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -56,11 +56,12 @@ def cmd_layout(aw): ] -def data_layout(dw): +def data_layout(dw, bankbits): return [ ("wdata", dw, DIR_M_TO_S), ("wdata_we", dw//8, DIR_M_TO_S), - ("rdata", dw, DIR_S_TO_M) + ("rdata", dw, DIR_S_TO_M), + ("rbank", bankbits, DIR_S_TO_M) ] @@ -72,7 +73,7 @@ class LiteDRAMInterface(Record): self.settings = settings layout = [("bank"+str(i), cmd_layout(self.aw)) for i in range(self.nbanks)] - layout += data_layout(self.dw) + layout += data_layout(self.dw, settings.geom.bankbits) Record.__init__(self, layout) def cmd_description(aw): @@ -87,12 +88,12 @@ def wdata_description(dw): ("we", dw//8) ] -def rdata_description(dw): - return [("data", dw)] +def rdata_description(dw, nbanks): + return [("data", dw), ("bank", nbanks)] class LiteDRAMPort: - def __init__(self, mode, aw, dw, cd="sys", id=0): + def __init__(self, mode, aw, dw, bankbits, cd="sys", id=0): self.mode = mode self.aw = aw self.dw = dw @@ -103,7 +104,7 @@ class LiteDRAMPort: self.cmd = stream.Endpoint(cmd_description(aw)) self.wdata = stream.Endpoint(wdata_description(dw)) - self.rdata = stream.Endpoint(rdata_description(dw)) + self.rdata = stream.Endpoint(rdata_description(dw, bankbits)) self.flush = Signal() diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index c3f52f0..fb69230 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -33,12 +33,12 @@ class LiteDRAMCrossbar(Module): dw = self.dw # crossbar port - port = LiteDRAMPort(mode, self.rca_bits + self.bank_bits, self.dw, "sys", len(self.masters)) + port = LiteDRAMPort(mode, self.rca_bits + self.bank_bits, self.dw, self.bank_bits, "sys", len(self.masters)) self.masters.append(port) # clock domain crossing if cd != "sys": - new_port = LiteDRAMPort(mode, port.aw, port.dw, cd, port.id) + new_port = LiteDRAMPort(mode, port.aw, port.dw, self.bank_bits, cd, port.id) self.submodules += LiteDRAMPortCDC(new_port, port) port = new_port @@ -48,7 +48,7 @@ class LiteDRAMCrossbar(Module): adr_shift = -log2_int(dw//self.dw) else: adr_shift = log2_int(self.dw//dw) - new_port = LiteDRAMPort(mode, port.aw + adr_shift, dw, cd, port.id) + new_port = LiteDRAMPort(mode, port.aw + adr_shift, dw, self.bank_bits, cd, port.id) self.submodules += ClockDomainsRenamer(cd)(LiteDRAMPortConverter(new_port, port, reverse)) port = new_port @@ -68,6 +68,8 @@ class LiteDRAMCrossbar(Module): arbiters = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self.nbanks)] self.submodules += arbiters + + rbank = Signal(max=self.nbanks) for nb, arbiter in enumerate(arbiters): bank = getattr(controller, "bank"+str(nb)) @@ -89,6 +91,12 @@ class LiteDRAMCrossbar(Module): arbiter.ce.eq(~bank.valid & ~bank.lock) ] + # Get rdata source bank + self.sync += \ + If((arbiter.grant == nm) & bank.rdata_valid, + rbank.eq(nb) + ) + # route requests self.comb += [ bank.adr.eq(Array(m_rca)[arbiter.grant]), @@ -116,6 +124,12 @@ class LiteDRAMCrossbar(Module): master_rdata_valid = new_master_rdata_valid master_rdata_valids[nm] = master_rdata_valid + # Delay bank output to match rvalid + for i in range(self.read_latency-1): + new_master_rbank = Signal(max=self.nbanks) + self.sync += new_master_rbank.eq(rbank) + rbank = new_master_rbank + for master, master_ready in zip(self.masters, master_readys): self.comb += master.cmd.ready.eq(master_ready) for master, master_wdata_ready in zip(self.masters, master_wdata_readys): @@ -139,15 +153,18 @@ class LiteDRAMCrossbar(Module): # route data reads for master in self.masters: self.comb += master.rdata.data.eq(self.controller.rdata) + self.comb += master.rdata.bank.eq(rbank) def split_master_addresses(self, bank_bits, rca_bits, cba_shift): m_ba = [] # bank address m_rca = [] # row and column address + print("cba_shift: " + str(cba_shift)) for master in self.masters: cba = Signal(self.bank_bits) rca = Signal(self.rca_bits) cba_upper = cba_shift + bank_bits self.comb += cba.eq(master.cmd.adr[cba_shift:cba_upper]) + print("cba_shift: " + str(cba_shift) + " cba_upper: " + str(cba_upper)) if cba_shift < self.rca_bits: if cba_shift: self.comb += rca.eq(Cat(master.cmd.adr[:cba_shift], diff --git a/litedram/frontend/dma.py b/litedram/frontend/dma.py index db24afb..1c2e1fb 100644 --- a/litedram/frontend/dma.py +++ b/litedram/frontend/dma.py @@ -69,7 +69,7 @@ class LiteDRAMDMAReader(Module): self.submodules += fifo self.comb += [ - port.rdata.connect(fifo.sink), + port.rdata.connect(fifo.sink, omit=["bank"]), fifo.source.connect(source), data_dequeued.eq(source.valid & source.ready) ]