diff --git a/litedram/frontend/adapter.py b/litedram/frontend/adapter.py index 5c1461e9..8530279e 100644 --- a/litedram/frontend/adapter.py +++ b/litedram/frontend/adapter.py @@ -81,23 +81,28 @@ def __init__(self, port_from, port_to, reverse=False): ratio = port_from.data_width//port_to.data_width mode = port_from.mode - count = Signal(max=ratio) + + cmd_count = Signal(max=ratio) + cmd_addr = Signal(len(port_from.cmd.addr)) + cmd_we = Signal() self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", - NextValue(count, 0), + port_from.cmd.ready.eq(1), If(port_from.cmd.valid, + NextValue(cmd_count, 0), + NextValue(cmd_addr, port_from.cmd.addr), + NextValue(cmd_we, port_from.cmd.we), NextState("CONVERT") ) ) fsm.act("CONVERT", port_to.cmd.valid.eq(1), - port_to.cmd.we.eq(port_from.cmd.we), - port_to.cmd.addr.eq(port_from.cmd.addr*ratio + count), + port_to.cmd.we.eq(cmd_we), + port_to.cmd.addr.eq(cmd_addr*ratio + cmd_count), If(port_to.cmd.ready, - NextValue(count, count + 1), - If(count == (ratio - 1), - port_from.cmd.ready.eq(1), + NextValue(cmd_count, cmd_count + 1), + If(cmd_count == (ratio - 1), NextState("IDLE") ) ) diff --git a/litedram/frontend/avalon.py b/litedram/frontend/avalon.py index 6878ffe3..fc3f8865 100644 --- a/litedram/frontend/avalon.py +++ b/litedram/frontend/avalon.py @@ -10,21 +10,25 @@ from migen import * +from litex.gen import * + from litex.soc.interconnect import stream + from litedram.common import LiteDRAMNativePort from litedram.frontend.adapter import LiteDRAMNativePortConverter - # LiteDRAMAvalonMM2Native -------------------------------------------------------------------------- -class LiteDRAMAvalonMM2Native(Module): +class LiteDRAMAvalonMM2Native(LiteXModule): def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000, burst_increment=1): + # Parameters. avalon_data_width = len(avalon.writedata) - port_data_width = 2**int(log2(len(port.wdata.data))) # Round to lowest power 2 - ratio = avalon_data_width/port_data_width - downconvert = ratio > 1 - upconvert = ratio < 1 + port_data_width = 2**int(log2(len(port.wdata.data))) # Round to lowest power 2 + ratio = avalon_data_width/port_data_width + downconvert = ratio > 1 + upconvert = ratio < 1 + # Data-Width Converter (Optional). if avalon_data_width != port_data_width: if avalon_data_width > port_data_width: addr_shift = -log2_int(avalon_data_width//port_data_width) @@ -35,76 +39,70 @@ def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000 address_width = port.address_width + addr_shift, data_width = avalon_data_width ) - self.submodules += LiteDRAMNativePortConverter(new_port, port) + self.converter = LiteDRAMNativePortConverter(new_port, port) port = new_port # # # - offset = base_address >> log2_int(port.data_width//8) + # Internal Signals. + burst_count = Signal(9) + address = Signal(port.address_width) + address_offset = Signal(port.address_width) + byteenable = Signal(avalon_data_width//8) + writedata = Signal(avalon_data_width) + latch = Signal() + cmd_ready_seen = Signal() + cmd_ready_count = Signal(9) - burstcounter = Signal(9) - start_burst = Signal() - active_burst = Signal() - address = Signal.like(port.cmd.addr) - byteenable = Signal.like(avalon.byteenable) - writedata = Signal(avalon_data_width) - start_transaction = Signal() - cmd_ready_seen = Signal() - cmd_ready_counter = Signal.like(burstcounter) + self.comb += address_offset.eq(base_address >> log2_int(port.data_width//8)) - cmd_layout = [("address", len(address))] + # Layouts. + cmd_layout = [("address", len(address))] wdata_layout = [ - ("data", avalon_data_width), - ("byteenable", len(avalon.byteenable)) + ("data", avalon_data_width), + ("byteenable", avalon_data_width//8), ] - self.comb += [ - start_burst .eq(2 <= avalon.burstcount), - active_burst.eq(1 <= burstcounter) - ] self.sync += [ - If(start_transaction, + If(latch, byteenable.eq(avalon.byteenable), - burstcounter.eq(avalon.burstcount), - address.eq(avalon.address - offset)) + writedata.eq(avalon.writedata), + burst_count.eq(avalon.burstcount), + address.eq(avalon.address - address_offset), + ) ] - start_condition = start_transaction if downconvert else (start_transaction & (start_burst | port.cmd.ready)) - - self.submodules.fsm = fsm = FSM(reset_state="START") + # FSM. + self.fsm = fsm = FSM(reset_state="START") fsm.act("START", avalon.waitrequest.eq(1), - If (~start_burst, - port.cmd.addr.eq(avalon.address - offset), - port.cmd.we.eq(avalon.write), - port.cmd.valid.eq(avalon.read | avalon.write) - ), - - start_transaction.eq(avalon.read | avalon.write), - - If(start_condition, - [] if downconvert else [If (~start_burst, avalon.waitrequest.eq(0))], - If (avalon.write, - If (start_burst, + NextValue(cmd_ready_seen, 0), + # Start of Access. + If(avalon.read | avalon.write, + latch.eq(1), + # Burst Access. + If(avalon.burstcount > 1, + If(avalon.write, NextState("BURST_WRITE") - ).Else( - [ - port.wdata.data.eq(avalon.writedata), - port.wdata.valid.eq(1), - port.wdata.we.eq(avalon.byteenable), - ] if downconvert else [], - NextValue(writedata, avalon.writedata), - port.cmd.last.eq(1), - NextState("SINGLE_WRITE") - ) - ).Elif(avalon.read, - If (start_burst, + ), + If(avalon.read, avalon.waitrequest.eq(0), - NextValue(cmd_ready_counter, avalon.burstcount), + NextValue(cmd_ready_count, avalon.burstcount), NextState("BURST_READ") - ).Else( - port.cmd.last.eq(1), - NextState("SINGLE_READ") + ) + # Single Access. + ).Else( + port.cmd.addr.eq(avalon.address - address_offset), + port.cmd.we.eq(avalon.write), + port.cmd.valid.eq(1), + port.cmd.last.eq(1), + If(port.cmd.ready, + avalon.waitrequest.eq(0), + If(port.cmd.we, + NextState("SINGLE_WRITE") + ).Else( + NextState("SINGLE_READ") + ) ) ) ) @@ -114,29 +112,11 @@ def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000 avalon.waitrequest.eq(1), port.rdata.ready.eq(0), - [ - port.cmd.addr.eq(address), - port.cmd.we.eq(1), - port.cmd.valid.eq(1), - - If(port.cmd.ready, NextValue(cmd_ready_seen, 1)), - If(cmd_ready_seen, - port.cmd.valid.eq(0), - port.cmd.we.eq(0) - ), - ] if downconvert else [], - port.wdata.data.eq(writedata), port.wdata.valid.eq(1), port.wdata.we.eq(byteenable), If(port.wdata.ready, - avalon.waitrequest.eq(0 if downconvert else 1), - NextValue(writedata, avalon.writedata), - - port.flush.eq(1), - NextValue(cmd_ready_seen, 0) if downconvert else NextValue(port.cmd.last, 1), - NextValue(byteenable, 0), NextState("START") ) ) @@ -145,33 +125,16 @@ def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000 avalon.waitrequest.eq(1), port.rdata.ready.eq(1), - [ - port.cmd.addr.eq(address), - port.cmd.we.eq(0), - port.cmd.valid.eq(1), - - If(port.cmd.ready, NextValue(cmd_ready_seen, 1)), - If(cmd_ready_seen, - port.cmd.valid.eq(0), - port.cmd.we.eq(0) - ), - ] if downconvert else [], - If(port.rdata.valid, avalon.readdata.eq(port.rdata.data), avalon.readdatavalid.eq(1), - [ - port.cmd.valid.eq(0), - avalon.waitrequest.eq(0), - NextValue(cmd_ready_seen, 0), - ] if downconvert else [], NextState("START") ) ) - self.submodules.cmd_fifo = cmd_fifo = stream.SyncFIFO(cmd_layout, max_burst_length) - self.submodules.wdata_fifo = wdata_fifo = stream.SyncFIFO(wdata_layout, max_burst_length) + self.cmd_fifo = cmd_fifo = stream.SyncFIFO(cmd_layout, max_burst_length) + self.wdata_fifo = wdata_fifo = stream.SyncFIFO(wdata_layout, max_burst_length) fsm.act("BURST_WRITE", # FIFO producer @@ -183,15 +146,15 @@ def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000 wdata_fifo.sink.payload.byteenable.eq(avalon.byteenable), wdata_fifo.sink.valid.eq(avalon.write & ~avalon.waitrequest), - If (avalon.write & active_burst, - If (cmd_fifo.sink.ready & cmd_fifo.sink.valid, - NextValue(burstcounter, burstcounter - 1), - NextValue(address, address + burst_increment)) + If(avalon.write & (burst_count > 0), + If(cmd_fifo.sink.ready & cmd_fifo.sink.valid, + NextValue(burst_count, burst_count - 1), + NextValue(address, address + burst_increment) + ) ).Else( avalon.waitrequest.eq(1), - # wait for the FIFO to be empty - If ((cmd_fifo .level == 0) & - (wdata_fifo.level == 1) & port.wdata.ready, + # Wait for the FIFO to be empty + If((cmd_fifo.level == 0) & (wdata_fifo.level == 1) & port.wdata.ready, NextState("START") ) ), @@ -218,16 +181,18 @@ def __init__(self, avalon, port, *, max_burst_length=16, base_address=0x00000000 avalon.readdata.eq(port.rdata.data), avalon.readdatavalid.eq(port.rdata.valid), - If (port.cmd.ready, - If (cmd_ready_counter == 1, NextValue(cmd_ready_seen, 1)), - NextValue(cmd_ready_counter, cmd_ready_counter - 1), + If(port.cmd.ready, + If(cmd_ready_count == 1, + NextValue(cmd_ready_seen, 1) + ), + NextValue(cmd_ready_count, cmd_ready_count - 1), NextValue(address, address + burst_increment) ), - If (port.rdata.valid, - If (burstcounter == 1, - NextValue(cmd_ready_seen, 0), - NextState("START")), - NextValue(burstcounter, burstcounter - 1) + If(port.rdata.valid, + If(burst_count == 1, + NextState("START") + ), + NextValue(burst_count, burst_count - 1) ) )