litex/misoclib/com/uart/__init__.py
Florent Kermarrec 8d1c555e36 misoclib/com/uart: remove irq condition parameters and use "non-full" for tx irq, "non-empty" for rx irq.
An optimal solution for both sync and async mode is not easy to implement, it would requires moving CDC out of UART module and handling in the PHY with AsyncFIFO or minimal depth.
For now use the solution that works for both cases. We'll try to optimize that if we have performance issues.
2015-07-25 00:25:09 +02:00

58 lines
1.8 KiB
Python

from migen.fhdl.std import *
from migen.bank.description import *
from migen.bank.eventmanager import *
from migen.genlib.record import Record
from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
if sink_cd != source_cd:
fifo = AsyncFIFO([("data", 8)], depth)
return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
else:
return SyncFIFO([("data", 8)], depth)
class UART(Module, AutoCSR):
def __init__(self, phy,
tx_fifo_depth=16,
rx_fifo_depth=16,
phy_cd="sys"):
self._rxtx = CSR(8)
self._txfull = CSRStatus()
self._rxempty = CSRStatus()
self.submodules.ev = EventManager()
self.ev.tx = EventSourceProcess()
self.ev.rx = EventSourceProcess()
self.ev.finalize()
# # #
# TX
tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
self.submodules += tx_fifo
self.comb += [
tx_fifo.sink.stb.eq(self._rxtx.re),
tx_fifo.sink.data.eq(self._rxtx.r),
self._txfull.status.eq(~tx_fifo.sink.ack),
Record.connect(tx_fifo.source, phy.sink),
# Generate TX IRQ when tx_fifo becomes non-full
self.ev.tx.trigger.eq(~tx_fifo.sink.ack)
]
# RX
rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
self.submodules += rx_fifo
self.comb += [
Record.connect(phy.source, rx_fifo.sink),
self._rxempty.status.eq(~rx_fifo.source.stb),
self._rxtx.w.eq(rx_fifo.source.data),
rx_fifo.source.ack.eq(self.ev.rx.clear),
# Generate RX IRQ when tx_fifo becomes non-empty
self.ev.rx.trigger.eq(~rx_fifo.source.stb)
]