201fdbb625ffb30ee2f25e24f5bdcaf77a7f1e33
[litex.git] / litex / soc / cores / uart.py
1 # This file is Copyright (c) 2014 Yann Sionneau <ys@m-labs.hk>
2 # This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
3 # This file is Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
4 # This file is Copyright (c) 2018 Tim 'mithro' Ansell <me@mith.ro>
5 # License: BSD
6
7 from math import log2
8
9 from migen import *
10 from migen.genlib.record import Record
11 from migen.genlib.cdc import MultiReg
12 from migen.genlib.misc import WaitTimer
13
14 from litex.soc.interconnect.csr import *
15 from litex.soc.interconnect.csr_eventmanager import *
16 from litex.soc.interconnect import wishbone
17 from litex.soc.interconnect import stream
18
19 # Common -------------------------------------------------------------------------------------------
20
21 def UARTPads():
22 return Record([("tx", 1), ("rx", 1)])
23
24 class UARTInterface:
25 def __init__(self):
26 self.sink = stream.Endpoint([("data", 8)])
27 self.source = stream.Endpoint([("data", 8)])
28
29 # RS232 PHY ----------------------------------------------------------------------------------------
30
31 class RS232PHYInterface(UARTInterface):
32 pass
33
34 class RS232PHYRX(Module):
35 def __init__(self, pads, tuning_word):
36 self.source = stream.Endpoint([("data", 8)])
37
38 # # #
39
40 uart_clk_rxen = Signal()
41 phase_accumulator_rx = Signal(32, reset_less=True)
42
43 rx = Signal()
44 rx_r = Signal()
45 rx_reg = Signal(8, reset_less=True)
46 rx_bitcount = Signal(4, reset_less=True)
47 rx_busy = Signal()
48 rx_done = self.source.valid
49 rx_data = self.source.data
50 self.specials += MultiReg(pads.rx, rx)
51 self.sync += [
52 rx_done.eq(0),
53 rx_r.eq(rx),
54 If(~rx_busy,
55 If(~rx & rx_r, # look for start bit
56 rx_busy.eq(1),
57 rx_bitcount.eq(0),
58 )
59 ).Else(
60 If(uart_clk_rxen,
61 rx_bitcount.eq(rx_bitcount + 1),
62 If(rx_bitcount == 0,
63 If(rx, # verify start bit
64 rx_busy.eq(0)
65 )
66 ).Elif(rx_bitcount == 9,
67 rx_busy.eq(0),
68 If(rx, # verify stop bit
69 rx_data.eq(rx_reg),
70 rx_done.eq(1)
71 )
72 ).Else(
73 rx_reg.eq(Cat(rx_reg[1:], rx))
74 )
75 )
76 )
77 ]
78 self.sync += \
79 If(rx_busy,
80 Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
81 ).Else(
82 Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
83 )
84
85
86 class RS232PHYTX(Module):
87 def __init__(self, pads, tuning_word):
88 self.sink = stream.Endpoint([("data", 8)])
89
90 # # #
91
92 uart_clk_txen = Signal()
93 phase_accumulator_tx = Signal(32, reset_less=True)
94
95 pads.tx.reset = 1
96
97 tx_reg = Signal(8, reset_less=True)
98 tx_bitcount = Signal(4, reset_less=True)
99 tx_busy = Signal()
100 self.sync += [
101 self.sink.ready.eq(0),
102 If(self.sink.valid & ~tx_busy & ~self.sink.ready,
103 tx_reg.eq(self.sink.data),
104 tx_bitcount.eq(0),
105 tx_busy.eq(1),
106 pads.tx.eq(0)
107 ).Elif(uart_clk_txen & tx_busy,
108 tx_bitcount.eq(tx_bitcount + 1),
109 If(tx_bitcount == 8,
110 pads.tx.eq(1)
111 ).Elif(tx_bitcount == 9,
112 pads.tx.eq(1),
113 tx_busy.eq(0),
114 self.sink.ready.eq(1),
115 ).Else(
116 pads.tx.eq(tx_reg[0]),
117 tx_reg.eq(Cat(tx_reg[1:], 0))
118 )
119 )
120 ]
121 self.sync += [
122 If(tx_busy,
123 Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
124 ).Else(
125 Cat(phase_accumulator_tx, uart_clk_txen).eq(tuning_word)
126 )
127 ]
128
129
130 class RS232PHY(Module, AutoCSR):
131 def __init__(self, pads, clk_freq, baudrate=115200):
132 self._tuning_word = CSRStorage(32, reset=int((baudrate/clk_freq)*2**32))
133 self.submodules.tx = RS232PHYTX(pads, self._tuning_word.storage)
134 self.submodules.rx = RS232PHYRX(pads, self._tuning_word.storage)
135 self.sink, self.source = self.tx.sink, self.rx.source
136
137
138 class RS232PHYMultiplexer(Module):
139 def __init__(self, phys, phy):
140 self.sel = Signal(max=len(phys))
141
142 # # #
143
144 cases = {}
145 for n in range(len(phys)):
146 # don't stall uarts when not selected
147 self.comb += phys[n].sink.ready.eq(1)
148 # connect core to phy
149 cases[n] = [
150 phy.source.connect(phys[n].source),
151 phys[n].sink.connect(phy.sink)
152 ]
153 self.comb += Case(self.sel, cases)
154
155
156 class RS232PHYModel(Module):
157 def __init__(self, pads):
158 self.sink = stream.Endpoint([("data", 8)])
159 self.source = stream.Endpoint([("data", 8)])
160
161 self.comb += [
162 pads.source_valid.eq(self.sink.valid),
163 pads.source_data.eq(self.sink.data),
164 self.sink.ready.eq(pads.source_ready),
165
166 self.source.valid.eq(pads.sink_valid),
167 self.source.data.eq(pads.sink_data),
168 pads.sink_ready.eq(self.source.ready)
169 ]
170
171 # UART ---------------------------------------------------------------------------------------------
172
173 def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
174 if sink_cd != source_cd:
175 fifo = stream.AsyncFIFO([("data", 8)], depth)
176 return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
177 else:
178 return stream.SyncFIFO([("data", 8)], depth, buffered=True)
179
180 def UARTPHY(pads, clk_freq, baudrate):
181 # FT245 Asynchronous FIFO mode (baudrate ignored)
182 if hasattr(pads, "rd_n") and hasattr(pads, "wr_n"):
183 from litex.soc.cores.usb_fifo import FT245PHYAsynchronous
184 return FT245PHYAsynchronous(pads, clk_freq)
185 # RS232
186 else:
187 return RS232PHY(pads, clk_freq, baudrate)
188
189 class UART(Module, AutoCSR, UARTInterface):
190 def __init__(self, phy=None,
191 tx_fifo_depth = 16,
192 rx_fifo_depth = 16,
193 rx_fifo_rx_we = False,
194 phy_cd = "sys"):
195 self._rxtx = CSR(8)
196 self._txfull = CSRStatus()
197 self._rxempty = CSRStatus()
198
199 self.submodules.ev = EventManager()
200 self.ev.tx = EventSourceProcess()
201 self.ev.rx = EventSourceProcess()
202 self.ev.finalize()
203
204 # # #
205
206 UARTInterface.__init__(self)
207
208 # PHY
209 if phy is not None:
210 self.comb += [
211 phy.source.connect(self.sink),
212 self.source.connect(phy.sink)
213 ]
214
215 # TX
216 tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
217 self.submodules += tx_fifo
218
219 self.comb += [
220 tx_fifo.sink.valid.eq(self._rxtx.re),
221 tx_fifo.sink.data.eq(self._rxtx.r),
222 self._txfull.status.eq(~tx_fifo.sink.ready),
223 tx_fifo.source.connect(self.source),
224 # Generate TX IRQ when tx_fifo becomes non-full
225 self.ev.tx.trigger.eq(~tx_fifo.sink.ready)
226 ]
227
228 # RX
229 rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
230 self.submodules += rx_fifo
231
232 self.comb += [
233 self.sink.connect(rx_fifo.sink),
234 self._rxempty.status.eq(~rx_fifo.source.valid),
235 self._rxtx.w.eq(rx_fifo.source.data),
236 rx_fifo.source.ready.eq(self.ev.rx.clear | (rx_fifo_rx_we & self._rxtx.we)),
237 # Generate RX IRQ when rx_fifo becomes non-empty
238 self.ev.rx.trigger.eq(~rx_fifo.source.valid)
239 ]
240
241 # UART Bone ----------------------------------------------------------------------------------------
242
243 CMD_WRITE = 0x01
244 CMD_READ = 0x02
245
246 class Stream2Wishbone(Module):
247 def __init__(self, phy, clk_freq, data_width=32, address_width=32):
248 self.wishbone = wishbone.Interface()
249 self.comb += phy.source.ready.eq(1) # Always accept incoming stream.
250
251 # # #
252
253 cmd = Signal(8, reset_less=True)
254 length = Signal(8, reset_less=True)
255 address = Signal(address_width, reset_less=True)
256 data = Signal(data_width, reset_less=True)
257 bytes_count = Signal(int(log2(data_width//8)), reset_less=True)
258 words_count = Signal(8, reset_less=True)
259
260 bytes_count_done = (bytes_count == (data_width//8 - 1))
261 words_count_done = (words_count == (length - 1))
262
263 fsm = ResetInserter()(FSM(reset_state="RECEIVE-CMD"))
264 timer = WaitTimer(int(100e-3*clk_freq))
265 self.comb += timer.wait.eq(~fsm.ongoing("RECEIVE-CMD"))
266 self.submodules += fsm, timer
267 self.comb += fsm.reset.eq(timer.done)
268 fsm.act("RECEIVE-CMD",
269 NextValue(bytes_count, 0),
270 NextValue(words_count, 0),
271 If(phy.source.valid,
272 NextValue(cmd, phy.source.data),
273 NextState("RECEIVE-LENGTH")
274 )
275 )
276 fsm.act("RECEIVE-LENGTH",
277 If(phy.source.valid,
278 NextValue(length, phy.source.data),
279 NextState("RECEIVE-ADDRESS")
280 )
281 )
282 fsm.act("RECEIVE-ADDRESS",
283 If(phy.source.valid,
284 NextValue(address, Cat(phy.source.data, address)),
285 NextValue(bytes_count, bytes_count + 1),
286 If(bytes_count_done,
287 If(cmd == CMD_WRITE,
288 NextState("RECEIVE-DATA")
289 ).Elif(cmd == CMD_READ,
290 NextState("READ-DATA")
291 ).Else(
292 NextState("RECEIVE-CMD")
293 )
294 )
295 )
296 )
297 fsm.act("RECEIVE-DATA",
298 If(phy.source.valid,
299 NextValue(data, Cat(phy.source.data, data)),
300 NextValue(bytes_count, bytes_count + 1),
301 If(bytes_count_done,
302 NextState("WRITE-DATA")
303 )
304 )
305 )
306 self.comb += [
307 self.wishbone.adr.eq(address),
308 self.wishbone.dat_w.eq(data),
309 self.wishbone.sel.eq(2**(data_width//8) - 1)
310 ]
311 fsm.act("WRITE-DATA",
312 self.wishbone.stb.eq(1),
313 self.wishbone.we.eq(1),
314 self.wishbone.cyc.eq(1),
315 If(self.wishbone.ack,
316 NextValue(words_count, words_count + 1),
317 NextValue(address, address + 1),
318 If(words_count_done,
319 NextState("RECEIVE-CMD")
320 ).Else(
321 NextState("RECEIVE-DATA")
322 )
323 )
324 )
325 fsm.act("READ-DATA",
326 self.wishbone.stb.eq(1),
327 self.wishbone.we.eq(0),
328 self.wishbone.cyc.eq(1),
329 If(self.wishbone.ack,
330 NextValue(data, self.wishbone.dat_r),
331 NextState("SEND-DATA")
332 )
333 )
334 cases = {}
335 for i, n in enumerate(reversed(range(data_width//8))):
336 cases[i] = phy.sink.data.eq(data[8*n:])
337 self.comb += Case(bytes_count, cases)
338 fsm.act("SEND-DATA",
339 phy.sink.valid.eq(1),
340 If(phy.sink.ready,
341 NextValue(bytes_count, bytes_count + 1),
342 If(bytes_count_done,
343 NextValue(words_count, words_count + 1),
344 NextValue(address, address + 1),
345 If(words_count_done,
346 NextState("RECEIVE-CMD")
347 ).Else(
348 NextState("READ-DATA")
349 )
350 )
351 )
352 )
353 self.comb += phy.sink.last.eq(bytes_count_done & words_count_done)
354 if hasattr(phy.sink, "length"):
355 self.comb += phy.sink.length.eq((data_width//8)*length)
356
357
358 class UARTBone(Stream2Wishbone):
359 def __init__(self, pads, clk_freq, baudrate=115200):
360 self.submodules.phy = RS232PHY(pads, clk_freq, baudrate)
361 Stream2Wishbone.__init__(self, self.phy, clk_freq)
362
363 class UARTWishboneBridge(UARTBone): pass
364
365 # UART Multiplexer ---------------------------------------------------------------------------------
366
367 class UARTMultiplexer(Module):
368 def __init__(self, uarts, uart):
369 self.sel = Signal(max=len(uarts))
370
371 # # #
372
373 cases = {}
374 for n in range(len(uarts)):
375 cases[n] = [
376 uart.tx.eq(uarts[n].tx),
377 uarts[n].rx.eq(uart.rx)
378 ]
379 self.comb += Case(self.sel, cases)
380
381 # UART Crossover -----------------------------------------------------------------------------------
382
383 class UARTCrossover(UART):
384 """
385 UART crossover trough Wishbone bridge.
386
387 Creates a fully compatible UART that can be used by the CPU as a regular UART and adds a second
388 UART, cross-connected to the main one to allow terminal emulation over a Wishbone bridge.
389 """
390 def __init__(self, **kwargs):
391 assert kwargs.get("phy", None) == None
392 UART.__init__(self, **kwargs)
393 self.submodules.xover = UART(tx_fifo_depth=1, rx_fifo_depth=1, rx_fifo_rx_we=True)
394 self.comb += [
395 self.source.connect(self.xover.sink),
396 self.xover.source.connect(self.sink)
397 ]