frontend/dma: Modify CSR interface to be similar to LiteX's DMA (start becomes a enable), also add offset CSR to keep track of current status.

This commit is contained in:
Florent Kermarrec 2021-03-04 11:58:33 +01:00
parent e9d5128811
commit 06411b2a72
1 changed files with 52 additions and 39 deletions

View File

@ -1,8 +1,8 @@
# #
# This file is part of LiteDRAM. # This file is part of LiteDRAM.
# #
# Copyright (c) 2016-2021 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk> # Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
# Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2018 John Sully <john@csquare.ca> # Copyright (c) 2018 John Sully <john@csquare.ca>
# Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com> # Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
# SPDX-License-Identifier: BSD-2-Clause # SPDX-License-Identifier: BSD-2-Clause
@ -51,7 +51,7 @@ class LiteDRAMDMAReader(Module, AutoCSR):
FIFO reservation level counter FIFO reservation level counter
""" """
def __init__(self, port, fifo_depth=16, fifo_buffered=False): def __init__(self, port, fifo_depth=16, fifo_buffered=False, with_csr=False):
assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort)) assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort))
self.port = port self.port = port
self.sink = sink = stream.Endpoint([("address", port.address_width)]) self.sink = sink = stream.Endpoint([("address", port.address_width)])
@ -108,46 +108,52 @@ class LiteDRAMDMAReader(Module, AutoCSR):
data_dequeued.eq(source.valid & source.ready) data_dequeued.eq(source.valid & source.ready)
] ]
def add_csr(self, default_base=0, default_length=0, default_start=0, default_loop=0): if with_csr:
self.add_csr()
def add_csr(self, default_base=0, default_length=0, default_enable=0, default_loop=0):
self._base = CSRStorage(32, reset=default_base) self._base = CSRStorage(32, reset=default_base)
self._length = CSRStorage(32, reset=default_length) self._length = CSRStorage(32, reset=default_length)
self._start = CSRStorage(reset=default_start) self._enable = CSRStorage(reset=default_enable)
self._done = CSRStatus() self._done = CSRStatus()
self._loop = CSRStorage(reset=default_loop) self._loop = CSRStorage(reset=default_loop)
self._offset = CSRStatus(32)
# # # # # #
shift = log2_int(self.port.data_width//8) shift = log2_int(self.port.data_width//8)
base = Signal(self.port.address_width) base = Signal(self.port.address_width)
offset = Signal(self.port.address_width) offset = Signal(self.port.address_width)
length = Signal(self.port.address_width) length = Signal(self.port.address_width)
self.comb += [ self.comb += base.eq(self._base.storage[shift:])
base.eq(self._base.storage[shift:]), self.comb += length.eq(self._length.storage[shift:])
length.eq(self._length.storage[shift:]),
]
self.submodules.fsm = fsm = FSM(reset_state="IDLE") self.comb += self._offset.status.eq(offset)
fsm = FSM(reset_state="IDLE")
fsm = ResetInserter()(fsm)
self.submodules.fsm = fsm
self.comb += fsm.reset.eq(~self._enable.storage)
fsm.act("IDLE", fsm.act("IDLE",
self._done.status.eq(1), NextValue(offset, 0),
If(self._start.storage & (default_start != 0 | self._start.re), NextState("RUN"),
NextValue(offset, 0),
NextState("RUN"),
)
) )
fsm.act("RUN", fsm.act("RUN",
self.sink.valid.eq(1), self.sink.valid.eq(1),
self.sink.last.eq(offset == (length - 1)),
self.sink.address.eq(base + offset), self.sink.address.eq(base + offset),
If(self.sink.ready, If(self.sink.ready,
NextValue(offset, offset + 1), NextValue(offset, offset + 1),
If(offset == (length - 1), If(self.sink.last,
If(self._loop.storage, If(self._loop.storage,
NextValue(offset, 0) NextValue(offset, 0)
).Else( ).Else(
NextState("IDLE") NextState("DONE")
) )
) )
) )
) )
fsm.act("DONE", self._done.status.eq(1))
# LiteDRAMDMAWriter -------------------------------------------------------------------------------- # LiteDRAMDMAWriter --------------------------------------------------------------------------------
@ -171,7 +177,7 @@ class LiteDRAMDMAWriter(Module, AutoCSR):
sink : Record("address", "data") sink : Record("address", "data")
Sink for DRAM addresses and DRAM data word to be written too. Sink for DRAM addresses and DRAM data word to be written too.
""" """
def __init__(self, port, fifo_depth=16, fifo_buffered=False): def __init__(self, port, fifo_depth=16, fifo_buffered=False, with_csr=False):
assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort)) assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort))
self.port = port self.port = port
self.sink = sink = stream.Endpoint([("address", port.address_width), self.sink = sink = stream.Endpoint([("address", port.address_width),
@ -215,43 +221,49 @@ class LiteDRAMDMAWriter(Module, AutoCSR):
wdata.data.eq(fifo.source.data) wdata.data.eq(fifo.source.data)
] ]
def add_csr(self, default_base=0, default_length=0, default_start=0, default_loop=0): if with_csr:
self.add_csr()
def add_csr(self, default_base=0, default_length=0, default_enable=0, default_loop=0):
self._sink = self.sink self._sink = self.sink
self.sink = stream.Endpoint([("data", self.port.data_width)]) self.sink = stream.Endpoint([("data", self.port.data_width)])
self._base = CSRStorage(32, reset=default_base) self._base = CSRStorage(32, reset=default_base)
self._length = CSRStorage(32, reset=default_length) self._length = CSRStorage(32, reset=default_length)
self._start = CSRStorage(reset=default_start) self._enable = CSRStorage(reset=default_enable)
self._done = CSRStatus() self._done = CSRStatus()
self._loop = CSRStorage(reset=default_loop) self._loop = CSRStorage(reset=default_loop)
self._offset = CSRStatus(32)
# # # # # #
shift = log2_int(self.port.data_width//8) shift = log2_int(self.port.data_width//8)
base = Signal(self.port.address_width) base = Signal(self.port.address_width)
offset = Signal(self.port.address_width) offset = Signal(self.port.address_width)
length = Signal(self.port.address_width) length = Signal(self.port.address_width)
self.comb += [ self.comb += base.eq(self._base.storage[shift:])
base.eq(self._base.storage[shift:]), self.comb += length.eq(self._length.storage[shift:])
length.eq(self._length.storage[shift:]),
]
self.submodules.fsm = fsm = FSM(reset_state="IDLE") self.comb += self._offset.status.eq(offset)
fsm = FSM(reset_state="IDLE")
fsm = ResetInserter()(fsm)
self.submodules.fsm = fsm
self.comb += fsm.reset.eq(~self._enable.storage)
fsm.act("IDLE", fsm.act("IDLE",
self._done.status.eq(1), self.sink.ready.eq(1),
If(self._start.storage & (default_start != 0 | self._start.re), NextValue(offset, 0),
NextValue(offset, 0), NextState("RUN"),
NextState("RUN"),
)
) )
fsm.act("RUN", fsm.act("RUN",
self._sink.valid.eq(self.sink.valid), self._sink.valid.eq(self.sink.valid),
self._sink.data.eq(self.sink.data), self._sink.last.eq(offset == (length - 1)),
self._sink.address.eq(base + offset), self._sink.address.eq(base + offset),
self._sink.data.eq(self.sink.data),
self.sink.ready.eq(self._sink.ready), self.sink.ready.eq(self._sink.ready),
If(self.sink.valid & self.sink.ready, If(self.sink.valid & self.sink.ready,
NextValue(offset, offset + 1), NextValue(offset, offset + 1),
If(offset == (length - 1), If(self._sink.last,
If(self._loop.storage, If(self._loop.storage,
NextValue(offset, 0) NextValue(offset, 0)
).Else( ).Else(
@ -260,3 +272,4 @@ class LiteDRAMDMAWriter(Module, AutoCSR):
) )
) )
) )
fsm.act("DONE", self._done.status.eq(1))