2 from nmigen
.lib
.fifo
import SyncFIFO
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.
24 Receiver ready. The receiver FIFO is non-empty.
26 Receiver error flags. See :class:`nmigen_stdio.serial.AsyncSerialRX` for layout.
30 Transmitter ready. The transmitter FIFO is non-full.
34 rx_rdy : level-triggered
35 Receiver ready. The receiver FIFO is non-empty.
36 rx_err : edge-triggered (rising)
37 Receiver error. Error cause is available in the ``rx_err`` register.
38 tx_mty : edge-triggered (rising)
39 Transmitter empty. The transmitter FIFO is empty.
44 Depth of the receiver FIFO.
46 Depth of the transmitter FIFO.
48 Clock divisor reset value. Should be set to ``int(clk_frequency // baudrate)``.
50 Optional. Clock divisor width. If omitted, ``bits_for(divisor)`` is used instead.
53 parity : ``"none"``, ``"mark"``, ``"space"``, ``"even"``, ``"odd"``
55 pins : :class:`Record`
56 Optional. UART pins. See :class:`nmigen_boards.resources.UARTResource`.
60 bus : :class:`nmigen_soc.wishbone.Interface`
61 Wishbone bus interface.
62 irq : :class:`IRQLine`
63 Interrupt request line.
65 def __init__(self
, *, rx_depth
=16, tx_depth
=16, **kwargs
):
68 self
._phy
= AsyncSerial(**kwargs
)
69 self
._rx
_fifo
= SyncFIFO(width
=self
._phy
.rx
.data
.width
, depth
=rx_depth
)
70 self
._tx
_fifo
= SyncFIFO(width
=self
._phy
.tx
.data
.width
, depth
=tx_depth
)
72 bank
= self
.csr_bank()
73 self
._divisor
= bank
.csr(self
._phy
.divisor
.width
, "rw")
74 self
._rx
_data
= bank
.csr(self
._phy
.rx
.data
.width
, "r")
75 self
._rx
_rdy
= bank
.csr(1, "r")
76 self
._rx
_err
= bank
.csr(len(self
._phy
.rx
.err
), "r")
77 self
._tx
_data
= bank
.csr(self
._phy
.tx
.data
.width
, "w")
78 self
._tx
_rdy
= bank
.csr(1, "r")
80 self
._rx
_rdy
_ev
= self
.event(mode
="level")
81 self
._rx
_err
_ev
= self
.event(mode
="rise")
82 self
._tx
_mty
_ev
= self
.event(mode
="rise")
84 self
._bridge
= self
.bridge(data_width
=32, granularity
=8, alignment
=2)
85 self
.bus
= self
._bridge
.bus
86 self
.irq
= self
._bridge
.irq
88 def elaborate(self
, platform
):
90 m
.submodules
.bridge
= self
._bridge
92 m
.submodules
.phy
= self
._phy
93 m
.submodules
.rx_fifo
= self
._rx
_fifo
94 m
.submodules
.tx_fifo
= self
._tx
_fifo
96 m
.d
.comb
+= self
._divisor
.r_data
.eq(self
._phy
.divisor
)
97 with m
.If(self
._divisor
.w_stb
):
98 m
.d
.sync
+= self
._phy
.divisor
.eq(self
._divisor
.w_data
)
101 self
._rx
_data
.r_data
.eq(self
._rx
_fifo
.r_data
),
102 self
._rx
_fifo
.r_en
.eq(self
._rx
_data
.r_stb
),
103 self
._rx
_rdy
.r_data
.eq(self
._rx
_fifo
.r_rdy
),
105 self
._rx
_fifo
.w_data
.eq(self
._phy
.rx
.data
),
106 self
._rx
_fifo
.w_en
.eq(self
._phy
.rx
.rdy
),
107 self
._phy
.rx
.ack
.eq(self
._rx
_fifo
.w_rdy
),
108 self
._rx
_err
.r_data
.eq(self
._phy
.rx
.err
),
110 self
._tx
_fifo
.w_en
.eq(self
._tx
_data
.w_stb
),
111 self
._tx
_fifo
.w_data
.eq(self
._tx
_data
.w_data
),
112 self
._tx
_rdy
.r_data
.eq(self
._tx
_fifo
.w_rdy
),
114 self
._phy
.tx
.data
.eq(self
._tx
_fifo
.r_data
),
115 self
._phy
.tx
.ack
.eq(self
._tx
_fifo
.r_rdy
),
116 self
._tx
_fifo
.r_en
.eq(self
._phy
.tx
.rdy
),
118 self
._rx
_rdy
_ev
.stb
.eq(self
._rx
_fifo
.r_rdy
),
119 self
._rx
_err
_ev
.stb
.eq(self
._phy
.rx
.err
.any()),
120 self
._tx
_mty
_ev
.stb
.eq(~self
._tx
_fifo
.r_rdy
),