Skip to content

Commit

Permalink
frontend/wishbone: add efficient wishbone downconvert, improve DRAM a…
Browse files Browse the repository at this point in the history
…ccess efficiency from CPU on boards with small native data_width.
  • Loading branch information
enjoy-digital committed Jan 13, 2020
1 parent 34e6c24 commit 721c84b
Showing 1 changed file with 46 additions and 29 deletions.
75 changes: 46 additions & 29 deletions litedram/frontend/wishbone.py
Original file line number Diff line number Diff line change
@@ -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

"""Wishbone frontend for LiteDRAM"""
Expand All @@ -12,52 +12,69 @@

class LiteDRAMWishbone2Native(Module):
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)

# Write data buffer-------------------------------------------------------------------------
wdata_buffer = stream.Buffer([("data", port.data_width), ("we", port.data_width//8)])
self.submodules += wdata_buffer
# Write Datapath ---------------------------------------------------------------------------
wdata_converter = stream.StrideConverter(
[("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 ----------------------------------------------------------------------------------
ratio = wishbone_data_width//port_data_width
count = Signal(max=max(ratio, 2))
self.submodules.fsm = fsm = FSM(reset_state="CMD")
fsm.act("CMD",
port.cmd.valid.eq(wishbone.cyc & wishbone.stb),
port.cmd.we.eq(wishbone.we),
port.cmd.addr.eq(wishbone.adr*ratio + count - adr_offset),
If(port.cmd.valid & port.cmd.ready,
If(wishbone.we,
NextState("WRITE")
).Else(
NextState("READ")
NextValue(count, count + 1),
If(count == (ratio - 1),
If(wishbone.we,
NextValue(count, 0),
NextState("WAIT-WRITE")
).Else(
NextValue(count, 0),
NextState("WAIT-READ")
)
)
)
)
fsm.act("WRITE",
wdata_buffer.sink.valid.eq(1),
If(wdata_buffer.sink.ready,
fsm.act("WAIT-WRITE",
If(wdata_converter.sink.ready,
wishbone.ack.eq(1),
NextState("CMD")
)
)
fsm.act("READ",
port.rdata.ready.eq(1),
If(port.rdata.valid,
wishbone.ack.eq(1),
NextState("CMD")
fsm.act("WAIT-READ",
If(rdata_converter.source.valid,
wishbone.ack.eq(1),
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),
]

0 comments on commit 721c84b

Please sign in to comment.