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),
]
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;
+ }
}
}