soc/cores/uart: rename UARTMultiplexer to RS232PHYMultiplexer. UARTMultiplexer now...
[litex.git] / litex / soc / cores / uart.py
1 from migen import *
2 from migen.genlib.record import Record
3 from migen.genlib.cdc import MultiReg
4
5 from litex.soc.interconnect.csr import *
6 from litex.soc.interconnect.csr_eventmanager import *
7 from litex.soc.interconnect import stream
8 from litex.soc.interconnect.wishbonebridge import WishboneStreamingBridge
9
10
11 class RS232PHYInterface:
12 def __init__(self):
13 self.sink = stream.Endpoint([("data", 8)])
14 self.source = stream.Endpoint([("data", 8)])
15
16
17 class RS232PHYRX(Module):
18 def __init__(self, pads, tuning_word):
19 self.source = stream.Endpoint([("data", 8)])
20
21 # # #
22
23 uart_clk_rxen = Signal()
24 phase_accumulator_rx = Signal(32)
25
26 rx = Signal()
27 self.specials += MultiReg(pads.rx, rx)
28 rx_r = Signal()
29 rx_reg = Signal(8)
30 rx_bitcount = Signal(4)
31 rx_busy = Signal()
32 rx_done = self.source.valid
33 rx_data = self.source.data
34 self.sync += [
35 rx_done.eq(0),
36 rx_r.eq(rx),
37 If(~rx_busy,
38 If(~rx & rx_r, # look for start bit
39 rx_busy.eq(1),
40 rx_bitcount.eq(0),
41 )
42 ).Else(
43 If(uart_clk_rxen,
44 rx_bitcount.eq(rx_bitcount + 1),
45 If(rx_bitcount == 0,
46 If(rx, # verify start bit
47 rx_busy.eq(0)
48 )
49 ).Elif(rx_bitcount == 9,
50 rx_busy.eq(0),
51 If(rx, # verify stop bit
52 rx_data.eq(rx_reg),
53 rx_done.eq(1)
54 )
55 ).Else(
56 rx_reg.eq(Cat(rx_reg[1:], rx))
57 )
58 )
59 )
60 ]
61 self.sync += \
62 If(rx_busy,
63 Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
64 ).Else(
65 Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
66 )
67
68
69 class RS232PHYTX(Module):
70 def __init__(self, pads, tuning_word):
71 self.sink = stream.Endpoint([("data", 8)])
72
73 # # #
74
75 uart_clk_txen = Signal()
76 phase_accumulator_tx = Signal(32)
77
78 pads.tx.reset = 1
79
80 tx_reg = Signal(8)
81 tx_bitcount = Signal(4)
82 tx_busy = Signal()
83 self.sync += [
84 self.sink.ready.eq(0),
85 If(self.sink.valid & ~tx_busy & ~self.sink.ready,
86 tx_reg.eq(self.sink.data),
87 tx_bitcount.eq(0),
88 tx_busy.eq(1),
89 pads.tx.eq(0)
90 ).Elif(uart_clk_txen & tx_busy,
91 tx_bitcount.eq(tx_bitcount + 1),
92 If(tx_bitcount == 8,
93 pads.tx.eq(1)
94 ).Elif(tx_bitcount == 9,
95 pads.tx.eq(1),
96 tx_busy.eq(0),
97 self.sink.ready.eq(1),
98 ).Else(
99 pads.tx.eq(tx_reg[0]),
100 tx_reg.eq(Cat(tx_reg[1:], 0))
101 )
102 )
103 ]
104 self.sync += [
105 If(tx_busy,
106 Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
107 ).Else(
108 Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
109 )
110 ]
111
112
113 class RS232PHY(Module, AutoCSR):
114 def __init__(self, pads, clk_freq, baudrate=115200):
115 self._tuning_word = CSRStorage(32, reset=int((baudrate/clk_freq)*2**32))
116 self.submodules.tx = RS232PHYTX(pads, self._tuning_word.storage)
117 self.submodules.rx = RS232PHYRX(pads, self._tuning_word.storage)
118 self.sink, self.source = self.tx.sink, self.rx.source
119
120
121 class RS232PHYMultiplexer(Module):
122 def __init__(self, phys, phy):
123 self.sel = Signal(max=len(phys))
124
125 # # #
126
127 cases = {}
128 for n in range(len(phys)):
129 # don't stall uarts when not selected
130 self.comb += phys[n].sink.ready.eq(1)
131 # connect core to phy
132 cases[n] = [
133 phy.source.connect(phys[n].source),
134 phys[n].sink.connect(phy.sink)
135 ]
136 self.comb += Case(self.sel, cases)
137
138
139 class RS232PHYModel(Module):
140 def __init__(self, pads):
141 self.sink = stream.Endpoint([("data", 8)])
142 self.source = stream.Endpoint([("data", 8)])
143
144 self.comb += [
145 pads.source_valid.eq(self.sink.valid),
146 pads.source_data.eq(self.sink.data),
147 self.sink.ready.eq(pads.source_ready),
148
149 self.source.valid.eq(pads.sink_valid),
150 self.source.data.eq(pads.sink_data),
151 pads.sink_ready.eq(self.source.ready)
152 ]
153
154
155 def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
156 if sink_cd != source_cd:
157 fifo = stream.AsyncFIFO([("data", 8)], depth)
158 return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
159 else:
160 return stream.SyncFIFO([("data", 8)], depth)
161
162
163 class UART(Module, AutoCSR):
164 def __init__(self, phy,
165 tx_fifo_depth=16,
166 rx_fifo_depth=16,
167 phy_cd="sys"):
168 self._rxtx = CSR(8)
169 self._txfull = CSRStatus()
170 self._rxempty = CSRStatus()
171
172 self.submodules.ev = EventManager()
173 self.ev.tx = EventSourceProcess()
174 self.ev.rx = EventSourceProcess()
175 self.ev.finalize()
176
177 # # #
178
179 # TX
180 tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
181 self.submodules += tx_fifo
182
183 self.comb += [
184 tx_fifo.sink.valid.eq(self._rxtx.re),
185 tx_fifo.sink.data.eq(self._rxtx.r),
186 self._txfull.status.eq(~tx_fifo.sink.ready),
187 tx_fifo.source.connect(phy.sink),
188 # Generate TX IRQ when tx_fifo becomes non-full
189 self.ev.tx.trigger.eq(~tx_fifo.sink.ready)
190 ]
191
192 # RX
193 rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
194 self.submodules += rx_fifo
195
196 self.comb += [
197 phy.source.connect(rx_fifo.sink),
198 self._rxempty.status.eq(~rx_fifo.source.valid),
199 self._rxtx.w.eq(rx_fifo.source.data),
200 rx_fifo.source.ready.eq(self.ev.rx.clear),
201 # Generate RX IRQ when tx_fifo becomes non-empty
202 self.ev.rx.trigger.eq(~rx_fifo.source.valid)
203 ]
204
205
206 class UARTStub(Module, AutoCSR):
207 def __init__(self):
208 self._rxtx = CSR(8)
209 self._txfull = CSRStatus()
210 self._rxempty = CSRStatus()
211
212 self.submodules.ev = EventManager()
213 self.ev.tx = EventSourceProcess()
214 self.ev.rx = EventSourceProcess()
215 self.ev.finalize()
216
217 # # #
218
219 self.comb += [
220 self._txfull.status.eq(0),
221 self.ev.tx.trigger.eq(~(self._rxtx.re & self._rxtx.r)),
222 self._rxempty.status.eq(1)
223 ]
224
225
226 class UARTWishboneBridge(WishboneStreamingBridge):
227 def __init__(self, pads, clk_freq, baudrate=115200):
228 self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
229 WishboneStreamingBridge.__init__(self, self.phy, clk_freq)
230
231
232 def UARTPads():
233 return Record([("tx", 1), ("rx", 1)])
234
235
236 class UARTMultiplexer(Module):
237 def __init__(self, uarts, uart):
238 self.sel = Signal(max=len(uarts))
239
240 # # #
241
242 cases = {}
243 for n in range(len(uarts)):
244 cases[n] = [
245 uart.tx.eq(uarts[n].tx),
246 uarts[n].rx.eq(uart.rx)
247 ]
248 self.comb += Case(self.sel, cases)