diff --git a/litex/soc/cores/uart.py b/litex/soc/cores/uart.py index f4e0fec28..a00710f8d 100644 --- a/litex/soc/cores/uart.py +++ b/litex/soc/cores/uart.py @@ -474,12 +474,53 @@ class UARTCrossover(UART): 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. + + If a pad_phy is provided, a debug_en register is created that enables a + mux to interpose the pads. When debug_en is 0, then the internal UART + is routed to the pads (and the crossover UART is unused); when debug_en + is 1, then the pad_phy is passed through to its original destination, + and the crossover is also passed through as usual (i.e., the behavior as + if no pad_phy were provided). """ - def __init__(self, **kwargs): + def __init__(self, pad_phy=None, **kwargs): assert kwargs.get("phy", None) == None UART.__init__(self, **kwargs) self.xover = UART(tx_fifo_depth=1, rx_fifo_depth=16, rx_fifo_rx_we=True) - self.comb += [ - self.source.connect(self.xover.sink), - self.xover.source.connect(self.sink) - ] + + if pad_phy is not None: + # Steal the pads from the pad_phy. + replaced_source = stream.Endpoint([("data", 8)]) + replaced_sink = stream.Endpoint([("data", 8)]) + + self.debug_en = CSRStorage(1, reset=1) + # debug_en = 0: + # pad_phy <-> self + # xover dangles, uartbone_phy dangles + # debug_en = 1: + # xover <-> self + # pad_phy <-> uartbone_phy + + self.comb += If(self.debug_en.storage == 0, + pad_phy.source.connect(self.sink), + self.source.connect(pad_phy.sink), + self.xover.source.ready.eq(0), + self.xover.sink.valid.eq(0), + replaced_source.valid.eq(0), + replaced_sink.ready.eq(0), + ).Else( + replaced_source.valid.eq(pad_phy.source.valid), + replaced_source.data.eq(pad_phy.source.data), + pad_phy.source.ready.eq(replaced_source.ready), + pad_phy.sink.valid.eq(replaced_sink.valid), + pad_phy.sink.data.eq(replaced_sink.data), + replaced_sink.ready.eq(pad_phy.sink.ready), + self.source.connect(self.xover.sink), + self.xover.source.connect(self.sink), + ) + pad_phy.source = replaced_source + pad_phy.sink = replaced_sink + else: + self.comb += [ + self.source.connect(self.xover.sink), + self.xover.source.connect(self.sink) + ] diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index dc3a4e49b..ff528b252 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1512,8 +1512,7 @@ class LiteXSoC(SoC): # Crossover + UARTBone. elif uart_name in ["crossover+uartbone"]: - self.add_uartbone(baudrate=baudrate) - uart = UARTCrossover(**uart_kwargs) + uart = self.add_uartbone(baudrate=baudrate, with_crossover=True, **uart_kwargs) # JTAG UART. elif uart_name in ["jtag_uart"]: @@ -1566,16 +1565,21 @@ class LiteXSoC(SoC): self.add_constant("UART_POLLING") # Add UARTbone --------------------------------------------------------------------------------- - def add_uartbone(self, name="uartbone", uart_name="serial", clk_freq=None, baudrate=115200, cd="sys"): + def add_uartbone(self, name="uartbone", uart_name="serial", clk_freq=None, baudrate=115200, cd="sys", with_crossover=False, **uart_kwargs): # Imports. from litex.soc.cores import uart # Core. if clk_freq is None: clk_freq = self.sys_clk_freq + self.check_if_exists(name) uartbone_phy = uart.UARTPHY(self.platform.request(uart_name), clk_freq, baudrate) - uartbone = uart.UARTBone( + + if with_crossover: + crossover = uart.UARTCrossover(pad_phy=uartbone_phy, **uart_kwargs) + + uartbone = uart.UARTBone( phy = uartbone_phy, clk_freq = clk_freq, cd = cd, @@ -1584,6 +1588,9 @@ class LiteXSoC(SoC): self.add_module(name=name, module=uartbone) self.bus.add_master(name=name, master=uartbone.wishbone) + if with_crossover: + return crossover + # Add JTAGbone --------------------------------------------------------------------------------- def add_jtagbone(self, name="jtagbone", chain=1): # Imports. diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 34a430bfc..981606c88 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -187,14 +187,14 @@ class SoCCore(LiteXSoC): if with_uart: # crossover+uartbone is kept as backward compatibility - if uart_name == "crossover+uartbone": - self.logger.warning("{} UART: is deprecated {}".format( - colorer(uart_name, color="yellow"), - colorer("please use --uart-name=\"crossover\" --with-uartbone", color="red"))) - time.sleep(2) - # Already configured. - self._uartbone = True - uart_name = "crossover" + #if uart_name == "crossover+uartbone": + # self.logger.warning("{} UART: is deprecated {}".format( + # colorer(uart_name, color="yellow"), + # colorer("please use --uart-name=\"crossover\" --with-uartbone", color="red"))) + # time.sleep(2) + # # Already configured. + # self._uartbone = True + # uart_name = "crossover" # JTAGBone and jtag_uart can't be used at the same time. assert not (with_jtagbone and uart_name == "jtag_uart")