2 from nmigen
.lib
.fifo
import SyncFIFOBuffered
4 from nmigen_stdio
.serial
import AsyncSerial
6 from . import Peripheral
9 __all__
= ["AsyncSerialPeripheral"]
12 class AsyncSerialPeripheral(Peripheral
, Elaboratable
):
13 """Asynchronous serial transceiver peripheral.
15 See :class:`nmigen_stdio.serial.AsyncSerial` for details.
20 * If this peripheral is used with the LambdaSoC BIOS, `rx_depth * data_bits` should be at least
21 256 bytes in order to buffer a complete SFL frame. Otherwise, a race condition may occur during
22 a serialboot at high baudrates.
31 Receiver ready. The receiver FIFO is non-empty.
33 Receiver error flags. See :class:`nmigen_stdio.serial.AsyncSerialRX` for layout.
37 Transmitter ready. The transmitter FIFO is non-full.
41 rx_rdy : level-triggered
42 Receiver ready. The receiver FIFO is non-empty.
43 rx_err : edge-triggered (rising)
44 Receiver error. Error cause is available in the ``rx_err`` register.
45 tx_mty : edge-triggered (rising)
46 Transmitter empty. The transmitter FIFO is empty.
51 Depth of the receiver FIFO.
53 Depth of the transmitter FIFO.
55 Clock divisor reset value. Should be set to ``int(clk_frequency // baudrate)``.
57 Optional. Clock divisor width. If omitted, ``bits_for(divisor)`` is used instead.
60 parity : ``"none"``, ``"mark"``, ``"space"``, ``"even"``, ``"odd"``
62 pins : :class:`Record`
63 Optional. UART pins. See :class:`nmigen_boards.resources.UARTResource`.
67 bus : :class:`nmigen_soc.wishbone.Interface`
68 Wishbone bus interface.
69 irq : :class:`IRQLine`
70 Interrupt request line.
72 def __init__(self
, *, rx_depth
=256, tx_depth
=16, data_bits
=8, **kwargs
):
75 self
._phy
= AsyncSerial(data_bits
=data_bits
, **kwargs
)
76 self
._rx
_fifo
= SyncFIFOBuffered(width
=self
._phy
.rx
.data
.width
, depth
=rx_depth
)
77 self
._tx
_fifo
= SyncFIFOBuffered(width
=self
._phy
.tx
.data
.width
, depth
=tx_depth
)
79 bank
= self
.csr_bank()
80 self
._divisor
= bank
.csr(self
._phy
.divisor
.width
, "rw")
81 self
._rx
_data
= bank
.csr(self
._phy
.rx
.data
.width
, "r")
82 self
._rx
_rdy
= bank
.csr(1, "r")
83 self
._rx
_err
= bank
.csr(len(self
._phy
.rx
.err
), "r")
84 self
._tx
_data
= bank
.csr(self
._phy
.tx
.data
.width
, "w")
85 self
._tx
_rdy
= bank
.csr(1, "r")
87 self
._rx
_rdy
_ev
= self
.event(mode
="level")
88 self
._rx
_err
_ev
= self
.event(mode
="rise")
89 self
._tx
_mty
_ev
= self
.event(mode
="rise")
91 self
._bridge
= self
.bridge(data_width
=32, granularity
=8, alignment
=2)
92 self
.bus
= self
._bridge
.bus
93 self
.irq
= self
._bridge
.irq
95 def elaborate(self
, platform
):
97 m
.submodules
.bridge
= self
._bridge
99 m
.submodules
.phy
= self
._phy
100 m
.submodules
.rx_fifo
= self
._rx
_fifo
101 m
.submodules
.tx_fifo
= self
._tx
_fifo
103 m
.d
.comb
+= self
._divisor
.r_data
.eq(self
._phy
.divisor
)
104 with m
.If(self
._divisor
.w_stb
):
105 m
.d
.sync
+= self
._phy
.divisor
.eq(self
._divisor
.w_data
)
108 self
._rx
_data
.r_data
.eq(self
._rx
_fifo
.r_data
),
109 self
._rx
_fifo
.r_en
.eq(self
._rx
_data
.r_stb
),
110 self
._rx
_rdy
.r_data
.eq(self
._rx
_fifo
.r_rdy
),
112 self
._rx
_fifo
.w_data
.eq(self
._phy
.rx
.data
),
113 self
._rx
_fifo
.w_en
.eq(self
._phy
.rx
.rdy
),
114 self
._phy
.rx
.ack
.eq(self
._rx
_fifo
.w_rdy
),
115 self
._rx
_err
.r_data
.eq(self
._phy
.rx
.err
),
117 self
._tx
_fifo
.w_en
.eq(self
._tx
_data
.w_stb
),
118 self
._tx
_fifo
.w_data
.eq(self
._tx
_data
.w_data
),
119 self
._tx
_rdy
.r_data
.eq(self
._tx
_fifo
.w_rdy
),
121 self
._phy
.tx
.data
.eq(self
._tx
_fifo
.r_data
),
122 self
._phy
.tx
.ack
.eq(self
._tx
_fifo
.r_rdy
),
123 self
._tx
_fifo
.r_en
.eq(self
._phy
.tx
.rdy
),
125 self
._rx
_rdy
_ev
.stb
.eq(self
._rx
_fifo
.r_rdy
),
126 self
._rx
_err
_ev
.stb
.eq(self
._phy
.rx
.err
.any()),
127 self
._tx
_mty
_ev
.stb
.eq(~self
._tx
_fifo
.r_rdy
),