mirror of
https://github.com/enjoy-digital/litedram.git
synced 2025-01-04 09:52:25 -05:00
frontend/avalon: First review pass to make codestyle more similar to other LiteX/LiteDRAM modules.
This commit is contained in:
parent
e9adaebf0d
commit
17527092db
1 changed files with 86 additions and 57 deletions
|
@ -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)
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue