366696e977a0993d603eb7fafedcf57e333dce25
3 # SPDX-License-Identifier: LGPLv3+
4 # Copyright (C) 2022 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
5 # Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073
6 # Part of the Libre-SOC Project.
8 # this is a wrapper around the opencores verilog uart16550 module
10 from nmigen
import (Elaboratable
, Cat
, Module
, Signal
, ClockSignal
, Instance
,
13 from nmigen_soc
.wishbone
.bus
import Interface
14 from nmigen
.cli
import rtlil
, verilog
17 __all__
= ["UART16550"]
20 class UART16550(Elaboratable
):
21 """16550 UART from opencores, nmigen wrapper. remember to call
22 UART16550.add_verilog_source
25 def __init__(self
, bus
=None, features
=None, name
=None, data_width
=32,
28 # convention: give the name in the format "name_number"
29 self
.idx
= int(name
.split("_")[-1])
33 self
.data_width
= data_width
35 # set up the wishbone bus
37 features
= frozenset()
39 bus
= Interface(addr_width
=5,
40 data_width
=data_width
,
43 name
=name
+"_wb_%d" % self
.idx
)
45 assert len(self
.bus
.dat_r
) == data_width
, \
46 "bus width must be %d" % data_width
48 # IRQ for data buffer receive/xmit
51 # 9-pin UART signals (if anyone still remembers those...)
52 self
.tx_o
= Signal() # transmit
53 self
.rx_i
= Signal() # receive
54 self
.rts_o
= Signal() # ready to send
55 self
.cts_i
= Signal() # clear to send
56 self
.dtr_o
= Signal() # data terminal ready
57 self
.dsr_i
= Signal() # data send ready
58 self
.ri_i
= Signal() # can't even remember what this is!
59 self
.dcd_i
= Signal() # or this!
65 def add_verilog_source(cls
, verilog_src_dir
, platform
):
66 # add each of the verilog sources, needed for when doing platform.build
67 for fname
in ['raminfr.v', 'uart_defines.v', 'uart_rfifo.v',
68 'uart_top.v', 'timescale.v', 'uart_receiver.v',
69 'uart_sync_flops.v', 'uart_transmitter.v',
70 'uart_debug_if.v', 'uart_regs.v',
71 'uart_tfifo.v', 'uart_wb.v'
73 # prepend the src directory to each filename, add its contents
74 fullname
= os
.path
.join(verilog_src_dir
, fname
)
75 with
open(fullname
) as f
:
76 platform
.add_file(fullname
, f
)
78 def elaborate(self
, platform
):
82 # create definition of external verilog 16550 uart here, so that # nmigen understands I/O directions (defined by i_ and o_ prefixes)
83 idx
, bus
= self
.idx
, self
.bus
84 uart
= Instance("uart_top",
85 # clock/reset (use DomainRenamer if needed)
86 i_wb_clk_i
=ClockSignal(),
87 i_wb_rst_i
=ResetSignal(),
88 # wishbone bus signals
99 # 9-pin RS232/UART signals
100 o_stx_pad_o
=self
.tx_o
,
101 i_srx_pad_i
=self
.rx_i
,
102 o_rts_pad_o
=self
.rts_o
,
103 i_cts_pad_i
=self
.cts_i
,
104 o_dtr_pad_o
=self
.dtr_o
,
105 i_dsr_pad_i
=self
.dsr_i
,
106 i_ri_pad_i
=self
.ri_i
,
107 i_dcd_pad_i
=self
.dcd_i
110 m
.submodules
['uart16550_%d' % self
.idx
] = uart
112 if self
.pins
is not None:
113 comb
+= self
.pins
.tx
.eq(self
.tx_o
)
114 comb
+= self
.rx_i
.eq(self
.pins
.rx
)
119 def create_ilang(dut
, ports
, test_name
):
120 vl
= rtlil
.convert(dut
, name
=test_name
, ports
=ports
)
121 with
open("%s.il" % test_name
, "w") as f
:
124 def create_verilog(dut
, ports
, test_name
):
125 vl
= verilog
.convert(dut
, name
=test_name
, ports
=ports
)
126 with
open("%s.v" % test_name
, "w") as f
:
130 if __name__
== "__main__":
131 uart
= UART16550(name
="uart_0", data_width
=8)
132 create_ilang(uart
, [uart
.bus
.cyc
, uart
.bus
.stb
, uart
.bus
.ack
,
133 uart
.bus
.dat_r
, uart
.bus
.dat_w
, uart
.bus
.adr
,
134 uart
.bus
.we
, uart
.bus
.sel
,
136 uart
.tx_o
, uart
.rx_i
, uart
.rts_o
, uart
.cts_i
,
137 uart
.dtr_o
, uart
.dsr_i
, uart
.ri_i
, uart
.dcd_i