afbe48775cd1ad420f16d2e66ca3fa1d3c23f8c1
4 class UART(Elaboratable
):
9 Set to ``round(clk-rate / baud-rate)``.
10 E.g. ``12e6 / 115200`` = ``104``.
12 def __init__(self
, divisor
, data_bits
=8):
15 self
.data_bits
= data_bits
16 self
.divisor
= divisor
21 self
.tx_data
= Signal(data_bits
)
22 self
.tx_rdy
= Signal()
23 self
.tx_ack
= Signal()
25 self
.rx_data
= Signal(data_bits
)
26 self
.rx_err
= Signal()
27 self
.rx_ovf
= Signal()
28 self
.rx_rdy
= Signal()
29 self
.rx_ack
= Signal()
31 def elaborate(self
, platform
):
34 tx_phase
= Signal(range(self
.divisor
))
35 tx_shreg
= Signal(1 + self
.data_bits
+ 1, reset
=-1)
36 tx_count
= Signal(range(len(tx_shreg
) + 1))
38 m
.d
.comb
+= self
.tx_o
.eq(tx_shreg
[0])
39 with m
.If(tx_count
== 0):
40 m
.d
.comb
+= self
.tx_ack
.eq(1)
41 with m
.If(self
.tx_rdy
):
43 tx_shreg
.eq(Cat(C(0, 1), self
.tx_data
, C(1, 1))),
44 tx_count
.eq(len(tx_shreg
)),
45 tx_phase
.eq(self
.divisor
- 1),
48 with m
.If(tx_phase
!= 0):
49 m
.d
.sync
+= tx_phase
.eq(tx_phase
- 1)
52 tx_shreg
.eq(Cat(tx_shreg
[1:], C(1, 1))),
53 tx_count
.eq(tx_count
- 1),
54 tx_phase
.eq(self
.divisor
- 1),
57 rx_phase
= Signal(range(self
.divisor
))
58 rx_shreg
= Signal(1 + self
.data_bits
+ 1, reset
=-1)
59 rx_count
= Signal(range(len(rx_shreg
) + 1))
61 m
.d
.comb
+= self
.rx_data
.eq(rx_shreg
[1:-1])
62 with m
.If(rx_count
== 0):
63 m
.d
.comb
+= self
.rx_err
.eq(~
(~rx_shreg
[0] & rx_shreg
[-1]))
64 with m
.If(~self
.rx_i
):
65 with m
.If(self
.rx_ack | ~self
.rx_rdy
):
69 rx_count
.eq(len(rx_shreg
)),
70 rx_phase
.eq(self
.divisor
// 2),
73 m
.d
.sync
+= self
.rx_ovf
.eq(1)
75 with m
.If(rx_phase
!= 0):
76 m
.d
.sync
+= rx_phase
.eq(rx_phase
- 1)
79 rx_shreg
.eq(Cat(rx_shreg
[1:], self
.rx_i
)),
80 rx_count
.eq(rx_count
- 1),
81 rx_phase
.eq(self
.divisor
- 1),
83 with m
.If(rx_count
== 1):
84 m
.d
.sync
+= self
.rx_rdy
.eq(1)
89 if __name__
== "__main__":
90 uart
= UART(divisor
=5)
93 uart
.tx_data
, uart
.tx_rdy
, uart
.tx_ack
,
94 uart
.rx_data
, uart
.rx_rdy
, uart
.rx_err
, uart
.rx_ovf
, uart
.rx_ack
99 parser
= argparse
.ArgumentParser()
100 p_action
= parser
.add_subparsers(dest
="action")
101 p_action
.add_parser("simulate")
102 p_action
.add_parser("generate")
104 args
= parser
.parse_args()
105 if args
.action
== "simulate":
106 from nmigen
.back
.pysim
import Simulator
, Passive
108 sim
= Simulator(uart
)
114 yield uart
.rx_i
.eq((yield uart
.tx_o
))
116 sim
.add_sync_process(loopback_proc
)
119 assert (yield uart
.tx_ack
)
120 assert not (yield uart
.rx_rdy
)
122 yield uart
.tx_data
.eq(0x5A)
123 yield uart
.tx_rdy
.eq(1)
125 yield uart
.tx_rdy
.eq(0)
127 assert not (yield uart
.tx_ack
)
129 for _
in range(uart
.divisor
* 12): yield
131 assert (yield uart
.tx_ack
)
132 assert (yield uart
.rx_rdy
)
133 assert not (yield uart
.rx_err
)
134 assert (yield uart
.rx_data
) == 0x5A
136 yield uart
.rx_ack
.eq(1)
138 sim
.add_sync_process(transmit_proc
)
140 with sim
.write_vcd("uart.vcd", "uart.gtkw"):
143 if args
.action
== "generate":
144 from nmigen
.back
import verilog
146 print(verilog
.convert(uart
, ports
=ports
))