Skip to content

Commit

Permalink
Merge pull request #354 from hansfbaier/downconvert-cleanup
Browse files Browse the repository at this point in the history
stable avalon frontend
  • Loading branch information
enjoy-digital authored Mar 25, 2024
2 parents e9adaeb + d7344c0 commit d6bf987
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 117 deletions.
19 changes: 12 additions & 7 deletions litedram/frontend/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
)
)
Expand Down
185 changes: 75 additions & 110 deletions litedram/frontend/avalon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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")
)
)
)
)
Expand All @@ -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")
)
)
Expand All @@ -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
Expand All @@ -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")
)
),
Expand All @@ -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)
)
)

0 comments on commit d6bf987

Please sign in to comment.