cores/uart/UART: add stream interface (phy=None), add connect method and use this for UART Stub/Crossover.

A bridged/crossover UART can now just be created by:
- passing uart_name="stream" to SoCCore/SoCSDRAM.
- adding a crossover UART core to the design:

# UART Crossover (over Wishbone Bridge
from litex.soc.cores.uart import UART
self.submodules.uart_xover = UART(tx_fifo_depth=2, rx_fifo_depth=2)
self.add_csr("uart_xover")
self.comb += self.uart.connect(self.uart_xover)
This commit is contained in:
Florent Kermarrec 2020-01-13 09:20:40 +01:00
parent d92bd8ffaa
commit 2f03d3234e
2 changed files with 30 additions and 54 deletions

View File

@ -13,11 +13,22 @@ from litex.soc.interconnect.csr_eventmanager import *
from litex.soc.interconnect import stream from litex.soc.interconnect import stream
from litex.soc.interconnect.wishbonebridge import WishboneStreamingBridge from litex.soc.interconnect.wishbonebridge import WishboneStreamingBridge
# Common -------------------------------------------------------------------------------------------
def UARTPads():
return Record([("tx", 1), ("rx", 1)])
class UARTInterface: class UARTInterface:
def __init__(self): def __init__(self):
self.sink = stream.Endpoint([("data", 8)]) self.sink = stream.Endpoint([("data", 8)])
self.source = stream.Endpoint([("data", 8)]) self.source = stream.Endpoint([("data", 8)])
def connect(self, other):
return [
other.source.connect(self.sink),
self.source.connect(other.sink)
]
# RS232 PHY ---------------------------------------------------------------------------------------- # RS232 PHY ----------------------------------------------------------------------------------------
class RS232PHYInterface(UARTInterface): class RS232PHYInterface(UARTInterface):
@ -182,8 +193,8 @@ def UARTPHY(pads, clk_freq, baudrate):
else: else:
return RS232PHY(pads, clk_freq, baudrate) return RS232PHY(pads, clk_freq, baudrate)
class UART(Module, AutoCSR): class UART(Module, AutoCSR, UARTInterface):
def __init__(self, phy, def __init__(self, phy=None,
tx_fifo_depth=16, tx_fifo_depth=16,
rx_fifo_depth=16, rx_fifo_depth=16,
phy_cd="sys"): phy_cd="sys"):
@ -198,6 +209,15 @@ class UART(Module, AutoCSR):
# # # # # #
UARTInterface.__init__(self)
# PHY
if phy is not None:
self.comb += [
phy.source.connect(self.sink),
self.source.connect(phy.sink)
]
# TX # TX
tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd) tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
self.submodules += tx_fifo self.submodules += tx_fifo
@ -206,7 +226,7 @@ class UART(Module, AutoCSR):
tx_fifo.sink.valid.eq(self._rxtx.re), tx_fifo.sink.valid.eq(self._rxtx.re),
tx_fifo.sink.data.eq(self._rxtx.r), tx_fifo.sink.data.eq(self._rxtx.r),
self._txfull.status.eq(~tx_fifo.sink.ready), self._txfull.status.eq(~tx_fifo.sink.ready),
tx_fifo.source.connect(phy.sink), tx_fifo.source.connect(self.source),
# Generate TX IRQ when tx_fifo becomes non-full # Generate TX IRQ when tx_fifo becomes non-full
self.ev.tx.trigger.eq(~tx_fifo.sink.ready) self.ev.tx.trigger.eq(~tx_fifo.sink.ready)
] ]
@ -216,7 +236,7 @@ class UART(Module, AutoCSR):
self.submodules += rx_fifo self.submodules += rx_fifo
self.comb += [ self.comb += [
phy.source.connect(rx_fifo.sink), self.sink.connect(rx_fifo.sink),
self._rxempty.status.eq(~rx_fifo.source.valid), self._rxempty.status.eq(~rx_fifo.source.valid),
self._rxtx.w.eq(rx_fifo.source.data), self._rxtx.w.eq(rx_fifo.source.data),
rx_fifo.source.ready.eq(self.ev.rx.clear), rx_fifo.source.ready.eq(self.ev.rx.clear),
@ -224,37 +244,12 @@ class UART(Module, AutoCSR):
self.ev.rx.trigger.eq(~rx_fifo.source.valid) self.ev.rx.trigger.eq(~rx_fifo.source.valid)
] ]
class UARTStub(Module, AutoCSR):
def __init__(self):
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()
# # #
self.comb += [
self._txfull.status.eq(0),
self.ev.tx.trigger.eq(~(self._rxtx.re & self._rxtx.r)),
self._rxempty.status.eq(1)
]
class UARTWishboneBridge(WishboneStreamingBridge): class UARTWishboneBridge(WishboneStreamingBridge):
def __init__(self, pads, clk_freq, baudrate=115200): def __init__(self, pads, clk_freq, baudrate=115200):
self.submodules.phy = RS232PHY(pads, clk_freq, baudrate) self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
WishboneStreamingBridge.__init__(self, self.phy, clk_freq) WishboneStreamingBridge.__init__(self, self.phy, clk_freq)
# UART Mutltiplexer -------------------------------------------------------------------------------- # UART Multiplexer ---------------------------------------------------------------------------------
def UARTPads():
return Record([("tx", 1), ("rx", 1)])
class UARTMultiplexer(Module): class UARTMultiplexer(Module):
def __init__(self, uarts, uart): def __init__(self, uarts, uart):
@ -269,22 +264,3 @@ class UARTMultiplexer(Module):
uarts[n].rx.eq(uart.rx) uarts[n].rx.eq(uart.rx)
] ]
self.comb += Case(self.sel, cases) self.comb += Case(self.sel, cases)
# UART Emulator ------------------------------------------------------------------------------------
class UARTEmulator(UART):
"""
UART emulation over Wishbone bridge.
Creates a fully compatible UART that can be used by the CPU as a regular UART and adds a second
UART, cross-connected to the main one to allow terminal emulation over a Wishbone bridge.
"""
def __init__(self, **kwargs):
uart_phy = UARTInterface()
emul_phy = UARTInterface()
UART.__init__(self, uart_phy, **kwargs)
self.submodules.emul = UART(emul_phy)
self.comb += [
uart_phy.source.connect(emul_phy.sink),
emul_phy.source.connect(uart_phy.sink)
]

View File

@ -95,7 +95,7 @@ class SoCCore(Module):
# Identifier parameters # Identifier parameters
ident="", ident_version=False, ident="", ident_version=False,
# UART parameters # UART parameters
with_uart=True, uart_name="serial", uart_baudrate=115200, uart_stub=False, with_uart=True, uart_name="serial", uart_baudrate=115200,
# Timer parameters # Timer parameters
with_timer=True, with_timer=True,
# Controller parameters # Controller parameters
@ -239,10 +239,10 @@ class SoCCore(Module):
# Add UART # Add UART
if with_uart: if with_uart:
if uart_stub: if uart_name in ["stub", "stream"]:
self.submodules.uart = uart.UARTStub() self.submodules.uart = uart.UART()
elif uart_name == "emulator": if uart_name == "stub":
self.submodules.uart = uart.UARTEmulator() self.comb += uart.sink.ready.eq(1)
else: else:
if uart_name == "jtag_atlantic": if uart_name == "jtag_atlantic":
from litex.soc.cores.jtag import JTAGAtlantic from litex.soc.cores.jtag import JTAGAtlantic