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),
|
("ready", 1, DIR_S_TO_M),
|
||||||
("we", 1, DIR_M_TO_S),
|
("we", 1, DIR_M_TO_S),
|
||||||
("adr", aw, 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),
|
("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):
|
class LiteDRAMPort(Record):
|
||||||
def __init__(self, aw, dw):
|
def __init__(self, aw, dw, cd):
|
||||||
self.aw = aw
|
self.aw = aw
|
||||||
self.dw = dw
|
self.dw = dw
|
||||||
|
self.cd = cd
|
||||||
|
|
||||||
layout = cmd_layout(aw) + data_layout(dw)
|
layout = cmd_layout(aw) + data_layout(dw)
|
||||||
Record.__init__(self, layout)
|
Record.__init__(self, layout)
|
||||||
|
|
|
@ -46,7 +46,9 @@ class BankMachine(Module):
|
||||||
settings.cmd_buffer_depth)
|
settings.cmd_buffer_depth)
|
||||||
self.submodules += cmd_buffer
|
self.submodules += cmd_buffer
|
||||||
self.comb += [
|
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),
|
cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid),
|
||||||
req.lock.eq(cmd_buffer.source.valid),
|
req.lock.eq(cmd_buffer.source.valid),
|
||||||
]
|
]
|
||||||
|
|
|
@ -25,12 +25,14 @@ class LiteDRAMWishboneBridge(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("WRITE_DATA",
|
fsm.act("WRITE_DATA",
|
||||||
|
port.wdata_valid.eq(1),
|
||||||
If(port.wdata_ready,
|
If(port.wdata_ready,
|
||||||
wishbone.ack.eq(1),
|
wishbone.ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("READ_DATA",
|
fsm.act("READ_DATA",
|
||||||
|
port.rdata_ready.eq(1),
|
||||||
If(port.rdata_valid,
|
If(port.rdata_valid,
|
||||||
wishbone.ack.eq(1),
|
wishbone.ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
|
|
|
@ -4,8 +4,62 @@ from operator import or_
|
||||||
from litex.gen import *
|
from litex.gen import *
|
||||||
from litex.gen.genlib import roundrobin
|
from litex.gen.genlib import roundrobin
|
||||||
|
|
||||||
|
from litex.soc.interconnect import stream
|
||||||
|
|
||||||
from litedram.common import *
|
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):
|
class LiteDRAMCrossbar(Module):
|
||||||
def __init__(self, controller, cba_shift):
|
def __init__(self, controller, cba_shift):
|
||||||
|
@ -23,13 +77,17 @@ class LiteDRAMCrossbar(Module):
|
||||||
|
|
||||||
self.masters = []
|
self.masters = []
|
||||||
|
|
||||||
def get_port(self):
|
def get_port(self, cd="sys"):
|
||||||
if self.finalized:
|
if self.finalized:
|
||||||
raise FinalizeError
|
raise FinalizeError
|
||||||
port = LiteDRAMPort(self.rca_bits + self.bank_bits,
|
port_to = LiteDRAMPort(self.rca_bits + self.bank_bits, self.dw, "sys")
|
||||||
self.dw)
|
self.masters.append(port_to)
|
||||||
self.masters.append(port)
|
if cd != "sys":
|
||||||
return port
|
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):
|
def do_finalize(self):
|
||||||
nmasters = len(self.masters)
|
nmasters = len(self.masters)
|
||||||
|
|
|
@ -43,6 +43,7 @@ class LiteDRAMDMAReader(Module):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
fifo.sink.data.eq(port.rdata),
|
fifo.sink.data.eq(port.rdata),
|
||||||
fifo.sink.valid.eq(port.rdata_valid),
|
fifo.sink.valid.eq(port.rdata_valid),
|
||||||
|
port.rdata_ready.eq(fifo.sink.ready),
|
||||||
|
|
||||||
fifo.source.connect(source),
|
fifo.source.connect(source),
|
||||||
data_dequeued.eq(source.valid & source.ready)
|
data_dequeued.eq(source.valid & source.ready)
|
||||||
|
@ -69,6 +70,7 @@ class LiteDRAMDMAWriter(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
port.wdata_valid.eq(fifo.source.valid),
|
||||||
fifo.source.ready.eq(port.wdata_ready),
|
fifo.source.ready.eq(port.wdata_ready),
|
||||||
port.wdata_we.eq(2**(port.dw//8)-1),
|
port.wdata_we.eq(2**(port.dw//8)-1),
|
||||||
port.wdata.eq(fifo.source.data)
|
port.wdata.eq(fifo.source.data)
|
||||||
|
|
|
@ -8,8 +8,8 @@ from litedram.frontend.bist import LiteDRAMBISTChecker
|
||||||
|
|
||||||
class TB(Module):
|
class TB(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.write_port = LiteDRAMPort(aw=32, dw=32)
|
self.write_port = LiteDRAMPort(aw=32, dw=32, cd="sys")
|
||||||
self.read_port = LiteDRAMPort(aw=32, dw=32)
|
self.read_port = LiteDRAMPort(aw=32, dw=32, cd="sys")
|
||||||
self.submodules.generator = LiteDRAMBISTGenerator(self.write_port)
|
self.submodules.generator = LiteDRAMBISTGenerator(self.write_port)
|
||||||
self.submodules.checker = LiteDRAMBISTChecker(self.read_port)
|
self.submodules.checker = LiteDRAMBISTChecker(self.read_port)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue