common: use cmd/wdata/rdata stream on LiteDRAMPort
This commit is contained in:
parent
30bacfeb1b
commit
8d066caea9
|
@ -1,4 +1,5 @@
|
||||||
from litex.gen import *
|
from litex.gen import *
|
||||||
|
from litex.soc.interconnect import stream
|
||||||
|
|
||||||
class PhySettings:
|
class PhySettings:
|
||||||
def __init__(self, memtype, dfi_databits,
|
def __init__(self, memtype, dfi_databits,
|
||||||
|
@ -47,10 +48,8 @@ def cmd_layout(aw):
|
||||||
("adr", aw, DIR_M_TO_S),
|
("adr", aw, DIR_M_TO_S),
|
||||||
("lock", 1, DIR_S_TO_M), # only used internally
|
("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,15 +72,33 @@ class LiteDRAMInterface(Record):
|
||||||
layout += data_layout(self.dw)
|
layout += data_layout(self.dw)
|
||||||
Record.__init__(self, layout)
|
Record.__init__(self, layout)
|
||||||
|
|
||||||
|
def cmd_description(aw):
|
||||||
|
return [
|
||||||
|
("we", 1),
|
||||||
|
("adr", aw)
|
||||||
|
]
|
||||||
|
|
||||||
class LiteDRAMPort(Record):
|
def wdata_description(dw):
|
||||||
|
return [
|
||||||
|
("data", dw),
|
||||||
|
("we", dw//8)
|
||||||
|
]
|
||||||
|
|
||||||
|
def rdata_description(dw):
|
||||||
|
return [("data", dw)]
|
||||||
|
|
||||||
|
|
||||||
|
class LiteDRAMPort:
|
||||||
def __init__(self, aw, dw, cd):
|
def __init__(self, aw, dw, cd):
|
||||||
self.aw = aw
|
self.aw = aw
|
||||||
self.dw = dw
|
self.dw = dw
|
||||||
self.cd = cd
|
self.cd = cd
|
||||||
|
|
||||||
layout = cmd_layout(aw) + data_layout(dw)
|
self.lock = Signal()
|
||||||
Record.__init__(self, layout)
|
|
||||||
|
self.cmd = stream.Endpoint(cmd_description(aw))
|
||||||
|
self.wdata = stream.Endpoint(wdata_description(dw))
|
||||||
|
self.rdata = stream.Endpoint(rdata_description(dw))
|
||||||
|
|
||||||
|
|
||||||
def cmd_request_layout(a, ba):
|
def cmd_request_layout(a, ba):
|
||||||
|
|
|
@ -14,9 +14,9 @@ class LiteDRAMWishboneBridge(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("REQUEST",
|
fsm.act("REQUEST",
|
||||||
port.valid.eq(1),
|
port.cmd.valid.eq(1),
|
||||||
port.we.eq(wishbone.we),
|
port.cmd.we.eq(wishbone.we),
|
||||||
If(port.ready,
|
If(port.cmd.ready,
|
||||||
If(wishbone.we,
|
If(wishbone.we,
|
||||||
NextState("WRITE_DATA")
|
NextState("WRITE_DATA")
|
||||||
).Else(
|
).Else(
|
||||||
|
@ -25,15 +25,15 @@ class LiteDRAMWishboneBridge(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("WRITE_DATA",
|
fsm.act("WRITE_DATA",
|
||||||
port.wdata_valid.eq(1),
|
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),
|
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")
|
||||||
)
|
)
|
||||||
|
@ -41,8 +41,8 @@ class LiteDRAMWishboneBridge(Module):
|
||||||
|
|
||||||
# Address / Datapath
|
# Address / Datapath
|
||||||
self.comb += [
|
self.comb += [
|
||||||
port.adr.eq(wishbone.adr),
|
port.cmd.adr.eq(wishbone.adr),
|
||||||
port.wdata_we.eq(wishbone.sel),
|
port.wdata.we.eq(wishbone.sel),
|
||||||
port.wdata.eq(wishbone.dat_w),
|
port.wdata.data.eq(wishbone.dat_w),
|
||||||
wishbone.dat_r.eq(port.rdata)
|
wishbone.dat_r.eq(port.rdata.data)
|
||||||
]
|
]
|
||||||
|
|
|
@ -21,43 +21,24 @@ class LiteDRAMAsyncAdapter(Module):
|
||||||
cmd_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(cmd_fifo)
|
cmd_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(cmd_fifo)
|
||||||
self.submodules += cmd_fifo
|
self.submodules += cmd_fifo
|
||||||
self.comb += [
|
self.comb += [
|
||||||
cmd_fifo.sink.valid.eq(port_from.valid),
|
port_from.cmd.connect(cmd_fifo.sink),
|
||||||
cmd_fifo.sink.we.eq(port_from.we),
|
cmd_fifo.source.connect(port_to.cmd)
|
||||||
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 = stream.AsyncFIFO([("data", dw), ("we", dw//8)], 4)
|
||||||
wdata_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(wdata_fifo)
|
wdata_fifo = ClockDomainsRenamer({"write": cd_from, "read": cd_to})(wdata_fifo)
|
||||||
self.submodules += wdata_fifo
|
self.submodules += wdata_fifo
|
||||||
self.comb += [
|
self.comb += [
|
||||||
wdata_fifo.sink.valid.eq(port_from.wdata_valid),
|
port_from.wdata.connect(wdata_fifo.sink),
|
||||||
wdata_fifo.sink.data.eq(port_from.wdata),
|
wdata_fifo.source.connect(port_to.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 = stream.AsyncFIFO([("data", dw)], 4)
|
||||||
rdata_fifo = ClockDomainsRenamer({"write": cd_to, "read": cd_from})(rdata_fifo)
|
rdata_fifo = ClockDomainsRenamer({"write": cd_to, "read": cd_from})(rdata_fifo)
|
||||||
self.submodules += rdata_fifo
|
self.submodules += rdata_fifo
|
||||||
self.comb += [
|
self.comb += [
|
||||||
rdata_fifo.sink.valid.eq(port_to.rdata_valid),
|
port_to.rdata.connect(rddata_fifo.sink),
|
||||||
rdata_fifo.sink.data.eq(port_to.rdata),
|
rddata_fifo.source.connect(port_from.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)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,7 +99,7 @@ class LiteDRAMCrossbar(Module):
|
||||||
|
|
||||||
# arbitrate
|
# arbitrate
|
||||||
bank_selected = [(ba == nb) & ~locked for ba, locked in zip(m_ba, master_locked)]
|
bank_selected = [(ba == nb) & ~locked for ba, locked in zip(m_ba, master_locked)]
|
||||||
bank_requested = [bs & master.valid for bs, master in zip(bank_selected, self.masters)]
|
bank_requested = [bs & master.cmd.valid for bs, master in zip(bank_selected, self.masters)]
|
||||||
self.comb += [
|
self.comb += [
|
||||||
arbiter.request.eq(Cat(*bank_requested)),
|
arbiter.request.eq(Cat(*bank_requested)),
|
||||||
arbiter.ce.eq(~bank.valid & ~bank.lock)
|
arbiter.ce.eq(~bank.valid & ~bank.lock)
|
||||||
|
@ -127,7 +108,7 @@ class LiteDRAMCrossbar(Module):
|
||||||
# route requests
|
# route requests
|
||||||
self.comb += [
|
self.comb += [
|
||||||
bank.adr.eq(Array(m_rca)[arbiter.grant]),
|
bank.adr.eq(Array(m_rca)[arbiter.grant]),
|
||||||
bank.we.eq(Array(self.masters)[arbiter.grant].we),
|
bank.we.eq(Array(self.masters)[arbiter.grant].cmd.we),
|
||||||
bank.valid.eq(Array(bank_requested)[arbiter.grant])
|
bank.valid.eq(Array(bank_requested)[arbiter.grant])
|
||||||
]
|
]
|
||||||
master_readys = [master_ready | ((arbiter.grant == nm) & bank_selected[nm] & bank.ready)
|
master_readys = [master_ready | ((arbiter.grant == nm) & bank_selected[nm] & bank.ready)
|
||||||
|
@ -152,18 +133,18 @@ class LiteDRAMCrossbar(Module):
|
||||||
master_rdata_valids[nm] = master_rdata_valid
|
master_rdata_valids[nm] = master_rdata_valid
|
||||||
|
|
||||||
for master, master_ready in zip(self.masters, master_readys):
|
for master, master_ready in zip(self.masters, master_readys):
|
||||||
self.comb += master.ready.eq(master_ready)
|
self.comb += master.cmd.ready.eq(master_ready)
|
||||||
for master, master_wdata_ready in zip(self.masters, master_wdata_readys):
|
for master, master_wdata_ready in zip(self.masters, master_wdata_readys):
|
||||||
self.comb += master.wdata_ready.eq(master_wdata_ready)
|
self.comb += master.wdata.ready.eq(master_wdata_ready)
|
||||||
for master, master_rdata_valid in zip(self.masters, master_rdata_valids):
|
for master, master_rdata_valid in zip(self.masters, master_rdata_valids):
|
||||||
self.comb += master.rdata_valid.eq(master_rdata_valid)
|
self.comb += master.rdata.valid.eq(master_rdata_valid)
|
||||||
|
|
||||||
# route data writes
|
# route data writes
|
||||||
wdata_cases = {}
|
wdata_cases = {}
|
||||||
for nm, master in enumerate(self.masters):
|
for nm, master in enumerate(self.masters):
|
||||||
wdata_cases[2**nm] = [
|
wdata_cases[2**nm] = [
|
||||||
controller.wdata.eq(master.wdata),
|
controller.wdata.eq(master.wdata.data),
|
||||||
controller.wdata_we.eq(master.wdata_we)
|
controller.wdata_we.eq(master.wdata.we)
|
||||||
]
|
]
|
||||||
wdata_cases["default"] = [
|
wdata_cases["default"] = [
|
||||||
controller.wdata.eq(0),
|
controller.wdata.eq(0),
|
||||||
|
@ -173,7 +154,7 @@ class LiteDRAMCrossbar(Module):
|
||||||
|
|
||||||
# route data reads
|
# route data reads
|
||||||
for master in self.masters:
|
for master in self.masters:
|
||||||
self.comb += master.rdata.eq(self.controller.rdata)
|
self.comb += master.rdata.data.eq(self.controller.rdata)
|
||||||
|
|
||||||
def split_master_addresses(self, bank_bits, rca_bits, cba_shift):
|
def split_master_addresses(self, bank_bits, rca_bits, cba_shift):
|
||||||
m_ba = [] # bank address
|
m_ba = [] # bank address
|
||||||
|
@ -182,15 +163,15 @@ class LiteDRAMCrossbar(Module):
|
||||||
cba = Signal(self.bank_bits)
|
cba = Signal(self.bank_bits)
|
||||||
rca = Signal(self.rca_bits)
|
rca = Signal(self.rca_bits)
|
||||||
cba_upper = cba_shift + bank_bits
|
cba_upper = cba_shift + bank_bits
|
||||||
self.comb += cba.eq(master.adr[cba_shift:cba_upper])
|
self.comb += cba.eq(master.cmd.adr[cba_shift:cba_upper])
|
||||||
if cba_shift < self.rca_bits:
|
if cba_shift < self.rca_bits:
|
||||||
if cba_shift:
|
if cba_shift:
|
||||||
self.comb += rca.eq(Cat(master.adr[:cba_shift],
|
self.comb += rca.eq(Cat(master.cmd.adr[:cba_shift],
|
||||||
master.adr[cba_upper:]))
|
master.cmd.adr[cba_upper:]))
|
||||||
else:
|
else:
|
||||||
self.comb += rca.eq(master.adr[cba_upper:])
|
self.comb += rca.eq(master.cmd.adr[cba_upper:])
|
||||||
else:
|
else:
|
||||||
self.comb += rca.eq(master.adr[:cba_shift])
|
self.comb += rca.eq(master.cmd.adr[:cba_shift])
|
||||||
|
|
||||||
ba = cba
|
ba = cba
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@ class LiteDRAMDMAReader(Module):
|
||||||
request_issued = Signal()
|
request_issued = Signal()
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
port.we.eq(0),
|
port.cmd.we.eq(0),
|
||||||
port.valid.eq(sink.valid & request_enable),
|
port.cmd.valid.eq(sink.valid & request_enable),
|
||||||
port.adr.eq(sink.address),
|
port.cmd.adr.eq(sink.address),
|
||||||
sink.ready.eq(port.ready & request_enable),
|
sink.ready.eq(port.cmd.ready & request_enable),
|
||||||
request_issued.eq(port.valid & port.ready)
|
request_issued.eq(port.cmd.valid & port.cmd.ready)
|
||||||
]
|
]
|
||||||
|
|
||||||
# FIFO reservation level counter
|
# FIFO reservation level counter
|
||||||
|
@ -41,10 +41,7 @@ class LiteDRAMDMAReader(Module):
|
||||||
self.submodules += fifo
|
self.submodules += fifo
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
fifo.sink.data.eq(port.rdata),
|
port.rdata.connect(fifo.sink),
|
||||||
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)
|
||||||
]
|
]
|
||||||
|
@ -61,17 +58,17 @@ class LiteDRAMDMAWriter(Module):
|
||||||
self.submodules += fifo
|
self.submodules += fifo
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
port.we.eq(1),
|
port.cmd.we.eq(1),
|
||||||
port.valid.eq(fifo.sink.ready & sink.valid),
|
port.cmd.valid.eq(fifo.sink.ready & sink.valid),
|
||||||
port.adr.eq(sink.address),
|
port.cmd.adr.eq(sink.address),
|
||||||
sink.ready.eq(fifo.sink.ready & port.ready),
|
sink.ready.eq(fifo.sink.ready & port.cmd.ready),
|
||||||
fifo.sink.valid.eq(sink.valid & port.ready),
|
fifo.sink.valid.eq(sink.valid & port.cmd.ready),
|
||||||
fifo.sink.data.eq(sink.data)
|
fifo.sink.data.eq(sink.data)
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
port.wdata_valid.eq(fifo.source.valid),
|
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.data.eq(fifo.source.data)
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue