From 721c84bad0a14e16c7fd7b6ebe01ad43bff3bcf8 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 13 Jan 2020 12:58:15 +0100 Subject: [PATCH] frontend/wishbone: add efficient wishbone downconvert, improve DRAM access efficiency from CPU on boards with small native data_width. --- litedram/frontend/wishbone.py | 75 +++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/litedram/frontend/wishbone.py b/litedram/frontend/wishbone.py index 36ff0cc..bfe9ab9 100644 --- a/litedram/frontend/wishbone.py +++ b/litedram/frontend/wishbone.py @@ -1,4 +1,4 @@ -# This file is Copyright (c) 2016-2018 Florent Kermarrec +# This file is Copyright (c) 2016-2020 Florent Kermarrec # License: BSD """Wishbone frontend for LiteDRAM""" @@ -12,52 +12,69 @@ from litex.soc.interconnect import stream 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), - ]