frontend/wishbone: add efficient wishbone downconvert, improve DRAM access efficiency from CPU on boards with small native data_width.
This commit is contained in:
parent
34e6c24d72
commit
721c84bad0
|
@ -1,4 +1,4 @@
|
||||||
# This file is Copyright (c) 2016-2018 Florent Kermarrec <florent@enjoy-digital.fr>
|
# This file is Copyright (c) 2016-2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
"""Wishbone frontend for LiteDRAM"""
|
"""Wishbone frontend for LiteDRAM"""
|
||||||
|
@ -12,52 +12,69 @@ from litex.soc.interconnect import stream
|
||||||
|
|
||||||
class LiteDRAMWishbone2Native(Module):
|
class LiteDRAMWishbone2Native(Module):
|
||||||
def __init__(self, wishbone, port, base_address=0x00000000):
|
def __init__(self, wishbone, port, base_address=0x00000000):
|
||||||
assert len(wishbone.dat_w) == len(port.wdata.data)
|
wishbone_data_width = len(wishbone.dat_w)
|
||||||
|
port_data_width = len(port.wdata.data)
|
||||||
|
assert wishbone_data_width >= port_data_width
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
adr_offset = base_address >> log2_int(port.data_width//8)
|
adr_offset = base_address >> log2_int(port.data_width//8)
|
||||||
|
|
||||||
# Write data buffer-------------------------------------------------------------------------
|
# Write Datapath ---------------------------------------------------------------------------
|
||||||
wdata_buffer = stream.Buffer([("data", port.data_width), ("we", port.data_width//8)])
|
wdata_converter = stream.StrideConverter(
|
||||||
self.submodules += wdata_buffer
|
[("data", wishbone_data_width), ("we", wishbone_data_width//8)],
|
||||||
|
[("data", port_data_width), ("we", port_data_width//8)],
|
||||||
|
)
|
||||||
|
self.submodules += wdata_converter
|
||||||
|
self.comb += [
|
||||||
|
wdata_converter.sink.valid.eq(wishbone.cyc & wishbone.stb & wishbone.we),
|
||||||
|
wdata_converter.sink.data.eq(wishbone.dat_w),
|
||||||
|
wdata_converter.sink.we.eq(wishbone.sel),
|
||||||
|
wdata_converter.source.connect(port.wdata)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Read Datapath ----------------------------------------------------------------------------
|
||||||
|
rdata_converter = stream.StrideConverter(
|
||||||
|
[("data", port_data_width)],
|
||||||
|
[("data", wishbone_data_width)],
|
||||||
|
)
|
||||||
|
self.submodules += rdata_converter
|
||||||
|
self.comb += [
|
||||||
|
port.rdata.connect(rdata_converter.sink),
|
||||||
|
rdata_converter.source.ready.eq(1),
|
||||||
|
wishbone.dat_r.eq(rdata_converter.source.data),
|
||||||
|
]
|
||||||
|
|
||||||
# Control ----------------------------------------------------------------------------------
|
# Control ----------------------------------------------------------------------------------
|
||||||
|
ratio = wishbone_data_width//port_data_width
|
||||||
|
count = Signal(max=max(ratio, 2))
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="CMD")
|
self.submodules.fsm = fsm = FSM(reset_state="CMD")
|
||||||
fsm.act("CMD",
|
fsm.act("CMD",
|
||||||
port.cmd.valid.eq(wishbone.cyc & wishbone.stb),
|
port.cmd.valid.eq(wishbone.cyc & wishbone.stb),
|
||||||
port.cmd.we.eq(wishbone.we),
|
port.cmd.we.eq(wishbone.we),
|
||||||
|
port.cmd.addr.eq(wishbone.adr*ratio + count - adr_offset),
|
||||||
If(port.cmd.valid & port.cmd.ready,
|
If(port.cmd.valid & port.cmd.ready,
|
||||||
|
NextValue(count, count + 1),
|
||||||
|
If(count == (ratio - 1),
|
||||||
If(wishbone.we,
|
If(wishbone.we,
|
||||||
NextState("WRITE")
|
NextValue(count, 0),
|
||||||
|
NextState("WAIT-WRITE")
|
||||||
).Else(
|
).Else(
|
||||||
NextState("READ")
|
NextValue(count, 0),
|
||||||
|
NextState("WAIT-READ")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("WRITE",
|
)
|
||||||
wdata_buffer.sink.valid.eq(1),
|
fsm.act("WAIT-WRITE",
|
||||||
If(wdata_buffer.sink.ready,
|
If(wdata_converter.sink.ready,
|
||||||
wishbone.ack.eq(1),
|
wishbone.ack.eq(1),
|
||||||
NextState("CMD")
|
NextState("CMD")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("READ",
|
fsm.act("WAIT-READ",
|
||||||
port.rdata.ready.eq(1),
|
If(rdata_converter.source.valid,
|
||||||
If(port.rdata.valid,
|
|
||||||
wishbone.ack.eq(1),
|
wishbone.ack.eq(1),
|
||||||
NextState("CMD")
|
NextState("CMD")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Datapath ---------------------------------------------------------------------------------
|
|
||||||
self.comb += [
|
|
||||||
# Cmd
|
|
||||||
port.cmd.addr.eq(wishbone.adr - adr_offset),
|
|
||||||
# Write
|
|
||||||
wdata_buffer.sink.data.eq(wishbone.dat_w),
|
|
||||||
wdata_buffer.sink.we.eq(wishbone.sel),
|
|
||||||
wdata_buffer.source.connect(port.wdata),
|
|
||||||
# Read
|
|
||||||
wishbone.dat_r.eq(port.rdata.data),
|
|
||||||
]
|
|
||||||
|
|
Loading…
Reference in New Issue