frontend/avalon: First review pass to make codestyle more similar to other LiteX/LiteDRAM modules.

This commit is contained in:
Florent Kermarrec 2023-05-31 08:54:44 +02:00 committed by Hans Baier
parent e9adaebf0d
commit 17527092db

View file

@ -10,21 +10,25 @@ from math import log2
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
# DownConverter (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)
@ -40,67 +44,78 @@ class LiteDRAMAvalonMM2Native(Module):
# # #
offset = base_address >> log2_int(port.data_width//8)
# Internal Signals.
offset = (base_address >> log2_int(port.data_width//8))
burstcounter = Signal(9)
start_burst = Signal()
active_burst = Signal()
address = Signal.like(port.cmd.addr)
byteenable = Signal.like(avalon.byteenable)
burst_count = Signal(9)
burst_start = Signal()
burst_active = Signal()
address = Signal(port.address_width)
byteenable = Signal(avalon_data_width//8)
writedata = Signal(avalon_data_width)
start_transaction = Signal()
start_condition = Signal()
cmd_ready_seen = Signal()
cmd_ready_counter = Signal.like(burstcounter)
cmd_ready_count = Signal(9)
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)
burst_start .eq(avalon.burstcount >= 2),
burst_active.eq(burst_count >= 1),
]
self.sync += [
If(start_transaction,
byteenable.eq(avalon.byteenable),
burstcounter.eq(avalon.burstcount),
address.eq(avalon.address - offset))
burst_count.eq(avalon.burstcount),
address.eq(avalon.address - offset),
)
]
start_condition = start_transaction if downconvert else (start_transaction & (start_burst | port.cmd.ready))
# FSM.
self.submodules.fsm = fsm = FSM(reset_state="START")
fsm.act("START",
avalon.waitrequest.eq(1),
If (~start_burst,
If(~burst_start,
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(downconvert,
start_condition.eq(start_transaction)
).Else(
start_condition.eq(start_transaction & (burst_start | port.cmd.ready))
),
If(start_condition,
[] if downconvert else [If (~start_burst, avalon.waitrequest.eq(0))],
If (avalon.write,
If (start_burst,
If(downconvert,
avalon.waitrequest.eq(1)
).Else(
If(~burst_start, avalon.waitrequest.eq(0))
),
If(avalon.write,
If(burst_start,
NextState("BURST_WRITE")
).Else(
[
If(downconvert,
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(burst_start,
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),
@ -114,28 +129,36 @@ class LiteDRAMAvalonMM2Native(Module):
avalon.waitrequest.eq(1),
port.rdata.ready.eq(0),
[
If(downconvert,
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(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),
If(downconvert,
avalon.waitrequest.eq(0)
),
NextValue(writedata, avalon.writedata),
port.flush.eq(1),
NextValue(cmd_ready_seen, 0) if downconvert else NextValue(port.cmd.last, 1),
If(downconvert,
NextValue(cmd_ready_seen, 0)
).Else(
NextValue(port.cmd.last, 1)
),
NextValue(byteenable, 0),
NextState("START")
)
@ -145,33 +168,36 @@ class LiteDRAMAvalonMM2Native(Module):
avalon.waitrequest.eq(1),
port.rdata.ready.eq(1),
[
If(downconvert,
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(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),
[
If(downconvert,
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 +209,15 @@ class LiteDRAMAvalonMM2Native(Module):
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_active,
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 +244,19 @@ class LiteDRAMAvalonMM2Native(Module):
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,
If(port.rdata.valid,
If(burst_count == 1,
NextValue(cmd_ready_seen, 0),
NextState("START")),
NextValue(burstcounter, burstcounter - 1)
NextState("START")
),
NextValue(burst_count, burst_count - 1)
)
)