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>
10 from migen
.genlib
.record
import Record
11 from migen
.genlib
.cdc
import MultiReg
12 from migen
.genlib
.misc
import WaitTimer
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
19 # Common -------------------------------------------------------------------------------------------
22 return Record([("tx", 1), ("rx", 1)])
26 self
.sink
= stream
.Endpoint([("data", 8)])
27 self
.source
= stream
.Endpoint([("data", 8)])
29 # RS232 PHY ----------------------------------------------------------------------------------------
31 class RS232PHYInterface(UARTInterface
):
34 class RS232PHYRX(Module
):
35 def __init__(self
, pads
, tuning_word
):
36 self
.source
= stream
.Endpoint([("data", 8)])
40 uart_clk_rxen
= Signal()
41 phase_accumulator_rx
= Signal(32, reset_less
=True)
45 rx_reg
= Signal(8, reset_less
=True)
46 rx_bitcount
= Signal(4, reset_less
=True)
48 rx_done
= self
.source
.valid
49 rx_data
= self
.source
.data
50 self
.specials
+= MultiReg(pads
.rx
, rx
)
55 If(~rx
& rx_r
, # look for start bit
61 rx_bitcount
.eq(rx_bitcount
+ 1),
63 If(rx
, # verify start bit
66 ).Elif(rx_bitcount
== 9,
68 If(rx
, # verify stop bit
73 rx_reg
.eq(Cat(rx_reg
[1:], rx
))
80 Cat(phase_accumulator_rx
, uart_clk_rxen
).eq(phase_accumulator_rx
+ tuning_word
)
82 Cat(phase_accumulator_rx
, uart_clk_rxen
).eq(2**31)
86 class RS232PHYTX(Module
):
87 def __init__(self
, pads
, tuning_word
):
88 self
.sink
= stream
.Endpoint([("data", 8)])
92 uart_clk_txen
= Signal()
93 phase_accumulator_tx
= Signal(32, reset_less
=True)
97 tx_reg
= Signal(8, reset_less
=True)
98 tx_bitcount
= Signal(4, reset_less
=True)
101 self
.sink
.ready
.eq(0),
102 If(self
.sink
.valid
& ~tx_busy
& ~self
.sink
.ready
,
103 tx_reg
.eq(self
.sink
.data
),
107 ).Elif(uart_clk_txen
& tx_busy
,
108 tx_bitcount
.eq(tx_bitcount
+ 1),
111 ).Elif(tx_bitcount
== 9,
114 self
.sink
.ready
.eq(1),
116 pads
.tx
.eq(tx_reg
[0]),
117 tx_reg
.eq(Cat(tx_reg
[1:], 0))
123 Cat(phase_accumulator_tx
, uart_clk_txen
).eq(phase_accumulator_tx
+ tuning_word
)
125 Cat(phase_accumulator_tx
, uart_clk_txen
).eq(tuning_word
)
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
138 class RS232PHYMultiplexer(Module
):
139 def __init__(self
, phys
, phy
):
140 self
.sel
= Signal(max=len(phys
))
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
150 phy
.source
.connect(phys
[n
].source
),
151 phys
[n
].sink
.connect(phy
.sink
)
153 self
.comb
+= Case(self
.sel
, cases
)
156 class RS232PHYModel(Module
):
157 def __init__(self
, pads
):
158 self
.sink
= stream
.Endpoint([("data", 8)])
159 self
.source
= stream
.Endpoint([("data", 8)])
162 pads
.source_valid
.eq(self
.sink
.valid
),
163 pads
.source_data
.eq(self
.sink
.data
),
164 self
.sink
.ready
.eq(pads
.source_ready
),
166 self
.source
.valid
.eq(pads
.sink_valid
),
167 self
.source
.data
.eq(pads
.sink_data
),
168 pads
.sink_ready
.eq(self
.source
.ready
)
171 # UART ---------------------------------------------------------------------------------------------
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
)
178 return stream
.SyncFIFO([("data", 8)], depth
, buffered
=True)
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
)
187 return RS232PHY(pads
, clk_freq
, baudrate
)
189 class UART(Module
, AutoCSR
, UARTInterface
):
190 def __init__(self
, phy
=None,
193 rx_fifo_rx_we
= False,
196 self
._txfull
= CSRStatus()
197 self
._rxempty
= CSRStatus()
199 self
.submodules
.ev
= EventManager()
200 self
.ev
.tx
= EventSourceProcess()
201 self
.ev
.rx
= EventSourceProcess()
206 UARTInterface
.__init
__(self
)
211 phy
.source
.connect(self
.sink
),
212 self
.source
.connect(phy
.sink
)
216 tx_fifo
= _get_uart_fifo(tx_fifo_depth
, source_cd
=phy_cd
)
217 self
.submodules
+= tx_fifo
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
)
229 rx_fifo
= _get_uart_fifo(rx_fifo_depth
, sink_cd
=phy_cd
)
230 self
.submodules
+= rx_fifo
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
)
241 # UART Bone ----------------------------------------------------------------------------------------
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.
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)
260 bytes_count_done
= (bytes_count
== (data_width
//8 - 1))
261 words_count_done
= (words_count
== (length
- 1))
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),
272 NextValue(cmd
, phy
.source
.data
),
273 NextState("RECEIVE-LENGTH")
276 fsm
.act("RECEIVE-LENGTH",
278 NextValue(length
, phy
.source
.data
),
279 NextState("RECEIVE-ADDRESS")
282 fsm
.act("RECEIVE-ADDRESS",
284 NextValue(address
, Cat(phy
.source
.data
, address
)),
285 NextValue(bytes_count
, bytes_count
+ 1),
288 NextState("RECEIVE-DATA")
289 ).Elif(cmd
== CMD_READ
,
290 NextState("READ-DATA")
292 NextState("RECEIVE-CMD")
297 fsm
.act("RECEIVE-DATA",
299 NextValue(data
, Cat(phy
.source
.data
, data
)),
300 NextValue(bytes_count
, bytes_count
+ 1),
302 NextState("WRITE-DATA")
307 self
.wishbone
.adr
.eq(address
),
308 self
.wishbone
.dat_w
.eq(data
),
309 self
.wishbone
.sel
.eq(2**(data_width
//8) - 1)
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),
319 NextState("RECEIVE-CMD")
321 NextState("RECEIVE-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")
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
)
339 phy
.sink
.valid
.eq(1),
341 NextValue(bytes_count
, bytes_count
+ 1),
343 NextValue(words_count
, words_count
+ 1),
344 NextValue(address
, address
+ 1),
346 NextState("RECEIVE-CMD")
348 NextState("READ-DATA")
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
)
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
)
363 class UARTWishboneBridge(UARTBone
): pass
365 # UART Multiplexer ---------------------------------------------------------------------------------
367 class UARTMultiplexer(Module
):
368 def __init__(self
, uarts
, uart
):
369 self
.sel
= Signal(max=len(uarts
))
374 for n
in range(len(uarts
)):
376 uart
.tx
.eq(uarts
[n
].tx
),
377 uarts
[n
].rx
.eq(uart
.rx
)
379 self
.comb
+= Case(self
.sel
, cases
)
381 # UART Crossover -----------------------------------------------------------------------------------
383 class UARTCrossover(UART
):
385 UART crossover trough Wishbone bridge.
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.
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)
395 self
.source
.connect(self
.xover
.sink
),
396 self
.xover
.source
.connect(self
.sink
)