diff --git a/software/glasgow/applet/interface/uart/__init__.py b/software/glasgow/applet/interface/uart/__init__.py index c7f81bfc9..e0e961172 100644 --- a/software/glasgow/applet/interface/uart/__init__.py +++ b/software/glasgow/applet/interface/uart/__init__.py @@ -10,7 +10,7 @@ from glasgow.support.arepl import AsyncInteractiveConsole from glasgow.support.logging import dump_hex from glasgow.support.endpoint import ServerEndpoint -from glasgow.gateware.uart import UART +from glasgow.gateware.uart import ExternalUART from glasgow.abstract import AbstractAssembly, GlasgowPin from glasgow.applet import GlasgowAppletV2 @@ -117,7 +117,8 @@ def elaborate(self, platform): # TODO: `uart.bit_cyc` is only used to set the width of the register; the actual initial # value is zero (same as `self.bit_cyc`); this is a footgun and should be fixed by rewriting # the UART to use lib.wiring - m.submodules.uart = uart = UART(self.ports, + m.submodules.uart = uart = ExternalUART( + self.ports, bit_cyc=(1 << len(self.manual_cyc)) - 1, parity=self.parity) m.submodules.auto_baud = auto_baud = UARTAutoBaud() diff --git a/software/glasgow/applet/interface/uart_analyzer/__init__.py b/software/glasgow/applet/interface/uart_analyzer/__init__.py index b4c6d1859..2044adaeb 100644 --- a/software/glasgow/applet/interface/uart_analyzer/__init__.py +++ b/software/glasgow/applet/interface/uart_analyzer/__init__.py @@ -11,7 +11,7 @@ from amaranth.lib.wiring import In, Out from glasgow.gateware.ports import PortGroup -from glasgow.gateware.uart import UART +from glasgow.gateware.uart import ExternalUART from glasgow.gateware.stream import Queue from glasgow.abstract import AbstractAssembly, GlasgowPin, ClockDivisor from glasgow.applet import GlasgowAppletV2, GlasgowAppletError @@ -51,8 +51,10 @@ def elaborate(self, platform): channels = [] for index, pin in enumerate(self._port): - m.submodules[f"ch{index}"] = uart = UART(PortGroup(rx=pin), - bit_cyc=(1 << len(self.periods[index])) - 1, parity=self._parity) + m.submodules[f"ch{index}"] = uart = ExternalUART( + PortGroup(rx=pin), + bit_cyc=(1 << len(self.periods[index])) - 1, + parity=self._parity) m.d.comb += uart.bit_cyc.eq(self.periods[index] + 1) channels.append(uart) diff --git a/software/glasgow/applet/program/m16c/__init__.py b/software/glasgow/applet/program/m16c/__init__.py index e24b07be0..828f99220 100644 --- a/software/glasgow/applet/program/m16c/__init__.py +++ b/software/glasgow/applet/program/m16c/__init__.py @@ -80,7 +80,7 @@ def __init__(self, ports, out_fifo, in_fifo, bit_cyc, reset, mode, max_bit_cyc): self.reset = reset self.mode = mode - self.uart = UART(ports, bit_cyc=max_bit_cyc) + self.uart = ExternalUART(ports, bit_cyc=max_bit_cyc) def elaborate(self, platform): m = Module() diff --git a/software/glasgow/applet/sensor/pmsx003/__init__.py b/software/glasgow/applet/sensor/pmsx003/__init__.py index 4727cab1f..53702de56 100644 --- a/software/glasgow/applet/sensor/pmsx003/__init__.py +++ b/software/glasgow/applet/sensor/pmsx003/__init__.py @@ -27,7 +27,8 @@ def __init__(self, ports, in_fifo, out_fifo): def elaborate(self, platform): m = Module() - m.submodules.uart = uart = UART(self.ports, + m.submodules.uart = uart = ExternalUART( + self.ports, bit_cyc=int(platform.default_clk_frequency // 9600)) m.d.comb += [ self.in_fifo.w_data.eq(uart.rx_data), diff --git a/software/glasgow/gateware/uart.py b/software/glasgow/gateware/uart.py index e6b35e373..aaaa18911 100644 --- a/software/glasgow/gateware/uart.py +++ b/software/glasgow/gateware/uart.py @@ -3,7 +3,7 @@ from amaranth.lib.cdc import FFSynchronizer -__all__ = ["UART"] +__all__ = ["UART", "ExternalUART"] class UARTBus(Elaboratable): @@ -12,6 +12,7 @@ class UARTBus(Elaboratable): Provides synchronization. """ + def __init__(self, ports): self.ports = ports @@ -90,7 +91,8 @@ class UART(Elaboratable): Transmit acknowledgement. If active when ``tx_rdy`` is active, ``tx_rdy`` is reset, ``tx_data`` is sampled, and the transmit state machine starts transmitting a frame. """ - def __init__(self, ports, bit_cyc, data_bits=8, parity="none", max_bit_cyc=None): + + def __init__(self, bus, bit_cyc, data_bits=8, parity="none", max_bit_cyc=None): if max_bit_cyc is not None: self.max_bit_cyc = max_bit_cyc else: @@ -102,18 +104,18 @@ def __init__(self, ports, bit_cyc, data_bits=8, parity="none", max_bit_cyc=None) self.bit_cyc = Signal(range(self.max_bit_cyc + 1), init=bit_cyc) self.rx_data = Signal(data_bits) - self.rx_rdy = Signal() - self.rx_ack = Signal() + self.rx_rdy = Signal() + self.rx_ack = Signal() self.rx_ferr = Signal() self.rx_perr = Signal() - self.rx_ovf = Signal() - self.rx_err = Signal() + self.rx_ovf = Signal() + self.rx_err = Signal() self.tx_data = Signal(data_bits) - self.tx_rdy = Signal() - self.tx_ack = Signal() + self.tx_rdy = Signal() + self.tx_ack = Signal() - self.bus = UARTBus(ports) + self.bus = bus def elaborate(self, platform): m = Module() @@ -139,7 +141,7 @@ def calc_parity(sig, kind): if self.bus.has_rx: rx_start = Signal() rx_timer = Signal(range(self.max_bit_cyc)) - rx_stb = Signal() + rx_stb = Signal() rx_shreg = Signal(self.data_bits) rx_bitno = Signal(range(len(rx_shreg))) @@ -199,11 +201,11 @@ def calc_parity(sig, kind): ### if self.bus.has_tx: - tx_start = Signal() - tx_timer = Signal(range(self.max_bit_cyc)) - tx_stb = Signal() - tx_shreg = Signal(self.data_bits) - tx_bitno = Signal(range(len(tx_shreg))) + tx_start = Signal() + tx_timer = Signal(range(self.max_bit_cyc)) + tx_stb = Signal() + tx_shreg = Signal(self.data_bits) + tx_bitno = Signal(range(len(tx_shreg))) tx_parity = Signal() with m.If(tx_start | (tx_timer == 0)): @@ -222,7 +224,9 @@ def calc_parity(sig, kind): self.bus.tx_o.eq(0), ] if self.parity != "none": - m.d.sync += tx_parity.eq(calc_parity(self.tx_data, self.parity)) + m.d.sync += tx_parity.eq( + calc_parity(self.tx_data, self.parity) + ) m.next = "START" with m.Else(): m.d.sync += self.bus.tx_o.eq(1) @@ -230,7 +234,7 @@ def calc_parity(sig, kind): with m.If(tx_stb): m.d.sync += [ self.bus.tx_o.eq(tx_shreg[0]), - tx_shreg.eq(Cat(tx_shreg[1:], C(0,1))), + tx_shreg.eq(Cat(tx_shreg[1:], C(0, 1))), ] m.next = "DATA" with m.State("DATA"): @@ -239,7 +243,7 @@ def calc_parity(sig, kind): with m.If(tx_bitno != len(tx_shreg) - 1): m.d.sync += [ self.bus.tx_o.eq(tx_shreg[0]), - tx_shreg.eq(Cat(tx_shreg[1:], C(0,1))), + tx_shreg.eq(Cat(tx_shreg[1:], C(0, 1))), ] with m.Else(): if self.parity == "none": @@ -250,10 +254,16 @@ def calc_parity(sig, kind): m.next = "PARITY" with m.State("PARITY"): with m.If(tx_stb): - m.d.sync += self.bus.tx_o.eq(1), + m.d.sync += (self.bus.tx_o.eq(1),) m.next = "STOP" with m.State("STOP"): with m.If(tx_stb): m.next = "IDLE" return m + + +class ExternalUART(UART): + def __init__(self, ports, *args, **kwargs): + bus = UARTBus(ports) + super().__init__(bus, *args, **kwargs)