add opencores uart16550 instance wrapper
[soc.git] / src / soc / bus / uart_16550.py
1 #!/usr/bin/env python3
2 #
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.
7 #
8 # this is a wrapper around the opencores verilog uart16550 module
9
10 from nmigen import (Elaboratable, Cat, Module, Signal, ClockSignal, Instance,
11 ResetSignal)
12
13 from nmigen_soc.wishbone.bus import Interface
14 from nmigen.cli import rtlil, verilog
15
16 __all__ = ["UART16550"]
17
18
19 class UART16550(Elaboratable):
20 """16550 UART from opencores, nmigen wrapper
21 """
22
23 def __init__(self, bus=None, features=None, name=None):
24 if name is not None:
25 # convention: give the name in the format "name_number"
26 self.idx = int(name.split("_")[-1])
27 else:
28 self.idx = 0
29
30 # set up the wishbone bus
31 if features is None:
32 features = frozenset()
33 if bus is None:
34 bus = Interface(addr_width=5,
35 data_width=32,
36 features=features,
37 name=name+"_wb_%d" % self.idx)
38 self.bus = bus
39 assert len(self.bus.dat_r) == 32, "bus width must be 32"
40
41 # IRQ for data buffer receive/xmit
42 self.irq = Signal()
43
44 # 9-pin UART signals (if anyone still remembers those...)
45 self.tx_o = Signal() # transmit
46 self.rx_i = Signal() # receive
47 self.rts_o = Signal() # ready to send
48 self.cts_i = Signal() # clear to send
49 self.dtr_o = Signal() # data terminal ready
50 self.dsr_i = Signal() # data send ready
51 self.ri_i = Signal() # can't even remember what this is!
52 self.dcd_i = Signal() # or this!
53
54 def elaborate(self, platform):
55 m = Module()
56
57 # create external verilog 16550 uart here
58 idx, bus = self.idx, self.bus
59 uart = Instance("uart_top_%d" % idx,
60 i_wb_clk_i=ClockSignal(),
61 i_wb_rst_i=ResetSignal(),
62 i_wb_adr_i=bus.adr,
63 i_wb_dat_i=bus.dat_w,
64 i_wb_sel_i=bus.sel,
65 o_wb_dat_o=bus.dat_r,
66 i_wb_we_i=bus.we,
67 i_wb_stb_i=bus.stb,
68 i_wb_cyc_i=bus.cyc,
69 o_wb_ack_o=bus.ack,
70 o_int_o=self.irq,
71 o_stx_pad_o=self.tx_o,
72 i_srx_pad_i=self.rx_i,
73 o_rts_pad_o=self.rts_o,
74 i_cts_pad_i=self.cts_i,
75 o_dtr_pad_o=self.dtr_o,
76 i_dsr_pad_i=self.dsr_i,
77 i_ri_pad_i=self.ri_i,
78 i_dcd_pad_i=self.dcd_i
79 );
80
81 m.submodules['uart16550_%d' % self.idx] = uart
82
83 return m
84
85
86 def create_ilang(dut, ports, test_name):
87 vl = rtlil.convert(dut, name=test_name, ports=ports)
88 with open("%s.il" % test_name, "w") as f:
89 f.write(vl)
90
91 def create_verilog(dut, ports, test_name):
92 vl = verilog.convert(dut, name=test_name, ports=ports)
93 with open("%s.v" % test_name, "w") as f:
94 f.write(vl)
95
96
97 if __name__ == "__main__":
98 uart = UART16550(name="uart_0")
99 create_ilang(uart, [uart.bus.cyc, uart.bus.stb, uart.bus.ack,
100 uart.bus.dat_r, uart.bus.dat_w, uart.bus.adr,
101 uart.bus.we, uart.bus.sel,
102 uart.irq,
103 uart.tx_o, uart.rx_i, uart.rts_o, uart.cts_i,
104 uart.dtr_o, uart.dsr_i, uart.ri_i, uart.dcd_i
105 ], "uart_0")
106