From: Florent Kermarrec Date: Fri, 1 May 2015 13:58:10 +0000 (+0200) Subject: com/uart: add tx and rx fifos. X-Git-Tag: 24jan2021_ls180~2284 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8aa3fb3eb707e6a3c72979d870f393398f022479;p=litex.git com/uart: add tx and rx fifos. Since ressource usage is low with default depth of 16 (implemented in RAM LUTs) we don't keep old behaviour. Tested successfully with BIOS and flterm. --- diff --git a/misoclib/com/uart/__init__.py b/misoclib/com/uart/__init__.py index bc5c6cd4..16160ebb 100644 --- a/misoclib/com/uart/__init__.py +++ b/misoclib/com/uart/__init__.py @@ -3,30 +3,45 @@ from migen.bank.description import * from migen.bank.eventmanager import * from migen.genlib.record import Record from migen.flow.actor import Sink, Source +from migen.actorlib.fifo import SyncFIFO class UART(Module, AutoCSR): - def __init__(self, phy): + def __init__(self, phy, + tx_fifo_depth=16, + rx_fifo_depth=16): self._rxtx = CSR(8) + self._txfull = CSRStatus() + self._rxempty = CSRStatus() self.submodules.ev = EventManager() - self.ev.tx = EventSourcePulse() - self.ev.rx = EventSourcePulse() + self.ev.tx = EventSourceProcess() + self.ev.rx = EventSourceProcess() self.ev.finalize() - ### - self.sync += [ - If(self._rxtx.re, - phy.sink.stb.eq(1), - phy.sink.data.eq(self._rxtx.r), - ).Elif(phy.sink.ack, - phy.sink.stb.eq(0) - ), - If(phy.source.stb, - self._rxtx.w.eq(phy.source.data) - ) + + # # # + + tx_fifo = SyncFIFO([("data", 8)], tx_fifo_depth) + 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) ] + + rx_fifo = SyncFIFO([("data", 8)], rx_fifo_depth) + 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) + ] + self.comb += [ - self.ev.tx.trigger.eq(phy.sink.stb & phy.sink.ack), - self.ev.rx.trigger.eq(phy.source.stb & phy.source.ack), - phy.source.ack.eq(~self.ev.rx.pending) + # Generate TX IRQ when tx_fifo becomes empty + self.ev.tx.trigger.eq(tx_fifo.source.stb), + # Generate RX IRQ when rx_fifo becomes non-empty + self.ev.rx.trigger.eq(~rx_fifo.source.stb), ] diff --git a/software/libbase/uart.c b/software/libbase/uart.c index 13dfe3b1..30ea5ef3 100644 --- a/software/libbase/uart.c +++ b/software/libbase/uart.c @@ -31,19 +31,22 @@ void uart_isr(void) stat = uart_ev_pending_read(); if(stat & UART_EV_RX) { - rx_buf[rx_produce] = uart_rxtx_read(); - rx_produce = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX; - uart_ev_pending_write(UART_EV_RX); + while(!uart_rxempty_read()) { + rx_buf[rx_produce] = uart_rxtx_read(); + rx_produce = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX; + uart_ev_pending_write(UART_EV_RX); + } } if(stat & UART_EV_TX) { uart_ev_pending_write(UART_EV_TX); - if(tx_level > 0) { + if(tx_level == 0) + tx_cts = 1; + while(tx_level > 0 && !uart_txfull_read()) { uart_rxtx_write(tx_buf[tx_consume]); tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; tx_level--; - } else - tx_cts = 1; + } } }