diff --git a/litedram/common.py b/litedram/common.py index 4a88511..8f7c98c 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -45,10 +45,12 @@ def cmd_layout(aw): ("ready", 1, DIR_S_TO_M), ("we", 1, DIR_M_TO_S), ("adr", aw, DIR_M_TO_S), - ("lock", 1, DIR_S_TO_M), + ("lock", 1, DIR_S_TO_M), # only used internally + ("wdata_valid", 1, DIR_M_TO_S), ("wdata_ready", 1, DIR_S_TO_M), - ("rdata_valid", 1, DIR_S_TO_M) + ("rdata_valid", 1, DIR_S_TO_M), + ("rdata_ready", 1, DIR_M_TO_S) ] @@ -73,9 +75,10 @@ class LiteDRAMInterface(Record): class LiteDRAMPort(Record): - def __init__(self, aw, dw): + def __init__(self, aw, dw, cd): self.aw = aw self.dw = dw + self.cd = cd layout = cmd_layout(aw) + data_layout(dw) Record.__init__(self, layout) diff --git a/litedram/core/bankmachine.py b/litedram/core/bankmachine.py index c86b016..d099b38 100644 --- a/litedram/core/bankmachine.py +++ b/litedram/core/bankmachine.py @@ -46,7 +46,9 @@ class BankMachine(Module): settings.cmd_buffer_depth) self.submodules += cmd_buffer self.comb += [ - req.connect(cmd_buffer.sink, omit=["wdata_ready", "rdata_valid", "lock"]), + req.connect(cmd_buffer.sink, omit=["wdata_valid", "wdata_ready", + "rdata_valid", "rdata_ready", + "lock"]), cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid), req.lock.eq(cmd_buffer.source.valid), ] diff --git a/litedram/frontend/bridge.py b/litedram/frontend/bridge.py index 2981a11..0f02924 100644 --- a/litedram/frontend/bridge.py +++ b/litedram/frontend/bridge.py @@ -25,12 +25,14 @@ class LiteDRAMWishboneBridge(Module): ) ) fsm.act("WRITE_DATA", + port.wdata_valid.eq(1), If(port.wdata_ready, wishbone.ack.eq(1), NextState("IDLE") ) ) fsm.act("READ_DATA", + port.rdata_ready.eq(1), If(port.rdata_valid, wishbone.ack.eq(1), NextState("IDLE") diff --git a/litedram/frontend/crossbar.py b/litedram/frontend/crossbar.py index 8f9f98c..0786bb7 100644 --- a/litedram/frontend/crossbar.py +++ b/litedram/frontend/crossbar.py @@ -4,8 +4,62 @@ from operator import or_ from litex.gen import * from litex.gen.genlib import roundrobin +from litex.soc.interconnect import stream + from litedram.common import * +class LiteDRAMAsyncAdapter(Module): + def __init__(self, port_from, port_to): + aw = port_from.aw + dw = port_from.dw + cd_from = port_from.cd + cd_to = port_from.cd + + # # # + + cmd_fifo = stream.AsyncFIFO([("we", 1), ("adr", aw)], 4) + cmd_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(cmd_fifo) + self.submodules += cmd_fifo + self.comb += [ + cmd_fifo.sink.valid.eq(port_from.valid), + cmd_fifo.sink.we.eq(port_from.we), + cmd_fifo.sink.adr.eq(port_from.adr), + port_from.ready.eq(cmd_fifo.sink.ready), + + port_to.valid.eq(cmd_fifo.source.valid), + port_to.we.eq(cmd_fifo.source.we), + port_to.adr.eq(cmd_fifo.source.adr), + cmd_fifo.source.ready.eq(port_to.ready) + ] + + wdata_fifo = stream.AsyncFIFO([("data", dw), ("we", dw//8)], 4) + wdata_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(wdata_fifo) + self.submodules += wdata_fifo + self.comb += [ + wdata_fifo.sink.valid.eq(port_from.wdata_valid), + wdata_fifo.sink.data.eq(port_from.wdata), + wdata_fifo.sink.we.eq(port_from.wdata_we), + port_from.wdata_ready.eq(wdata_fifo.sink.ready), + + port_to.wdata_valid.eq(wdata_fifo.source.valid), + port_to.wdata.eq(wdata_fifo.source.data), + port_to.wdata_we.eq(wdata_fifo.source.we), + wdata_fifo.source.ready.eq(port_to.wdata_ready) + ] + + rdata_fifo = stream.AsyncFIFO([("data", dw)], 4) + rdata_fifo = ClockDomainsRenamer({"write": cd_to, "read": cd_from})(rdata_fifo) + self.submodules += rdata_fifo + self.comb += [ + rdata_fifo.sink.valid.eq(port_to.rdata_valid), + rdata_fifo.sink.data.eq(port_to.rdata), + port_to.rdata_ready.eq(rdata_fifo.sink.ready), + + port_from.rdata_valid.eq(rdata_fifo.source.valid), + port_from.rdata.eq(rdata_fifo.source.data), + rdata_fifo.source.ready.eq(port_from.rdata_ready) + ] + class LiteDRAMCrossbar(Module): def __init__(self, controller, cba_shift): @@ -23,13 +77,17 @@ class LiteDRAMCrossbar(Module): self.masters = [] - def get_port(self): + def get_port(self, cd="sys"): if self.finalized: raise FinalizeError - port = LiteDRAMPort(self.rca_bits + self.bank_bits, - self.dw) - self.masters.append(port) - return port + port_to = LiteDRAMPort(self.rca_bits + self.bank_bits, self.dw, "sys") + self.masters.append(port_to) + if cd != "sys": + port_from = LiteDRAMPort(self.rca_bits + self.bank_bits, self.dw, cd) + self.submodules += LiteDRAMAsyncAdapter(port_from, port_to) + return port_from + else: + return port_to def do_finalize(self): nmasters = len(self.masters) diff --git a/litedram/frontend/dma.py b/litedram/frontend/dma.py index e279ee4..278567d 100644 --- a/litedram/frontend/dma.py +++ b/litedram/frontend/dma.py @@ -43,6 +43,7 @@ class LiteDRAMDMAReader(Module): self.comb += [ fifo.sink.data.eq(port.rdata), fifo.sink.valid.eq(port.rdata_valid), + port.rdata_ready.eq(fifo.sink.ready), fifo.source.connect(source), data_dequeued.eq(source.valid & source.ready) @@ -69,6 +70,7 @@ class LiteDRAMDMAWriter(Module): ] self.comb += [ + port.wdata_valid.eq(fifo.source.valid), fifo.source.ready.eq(port.wdata_ready), port.wdata_we.eq(2**(port.dw//8)-1), port.wdata.eq(fifo.source.data) diff --git a/test/bist_tb.py b/test/bist_tb.py index f49eb32..8386c0d 100644 --- a/test/bist_tb.py +++ b/test/bist_tb.py @@ -8,8 +8,8 @@ from litedram.frontend.bist import LiteDRAMBISTChecker class TB(Module): def __init__(self): - self.write_port = LiteDRAMPort(aw=32, dw=32) - self.read_port = LiteDRAMPort(aw=32, dw=32) + self.write_port = LiteDRAMPort(aw=32, dw=32, cd="sys") + self.read_port = LiteDRAMPort(aw=32, dw=32, cd="sys") self.submodules.generator = LiteDRAMBISTGenerator(self.write_port) self.submodules.checker = LiteDRAMBISTChecker(self.read_port)