frontend: add LiteDRAMAsyncAdapter for asynchronous ports (need more tests)
This commit is contained in:
parent
19a0bd59d2
commit
30bacfeb1b
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue