Improved bit-bang UART test func for demo
[pinmux.git] / src / spec / stage2.py
1 #!/usr/bin/env python3
2 """
3 pinmux documented here https://libre-soc.org/docs/pinmux/
4 """
5 from nmigen import Elaboratable, Module, Signal, Record, Array, Cat
6 from nmigen.hdl.rec import Layout
7 from nmigen.utils import log2_int
8 from nmigen.cli import rtlil
9 from soc.minerva.wishbone import make_wb_layout
10 from nmutil.util import wrap
11 #from soc.bus.test.wb_rw import wb_read, wb_write
12
13 from nmutil.gtkw import write_gtkw
14
15 cxxsim = False
16 if cxxsim:
17 from nmigen.sim.cxxsim import Simulator, Settle, Delay
18 else:
19 from nmigen.sim import Simulator, Settle, Delay
20
21 from iomux import IOMuxBlockSingle
22
23 io_layout = (("i", 1),
24 ("oe", 1),
25 ("o", 1)
26 )
27
28 uart_layout = (("rx", 1),
29 ("tx", 1),
30 ("oe", 1)
31 )
32
33 UART_BANK = 0
34 I2C_BANK = 1
35
36 """
37 Really basic example, uart tx/rx and i2c sda/scl pinmux
38 """
39 class ManPinmux(Elaboratable):
40 def __init__(self):
41 print("Test Manual Pinmux!")
42 self.n_banks = 2
43 self.iomux1 = IOMuxBlockSingle(self.n_banks)
44 self.iomux2 = IOMuxBlockSingle(self.n_banks)
45 self.pad1 = Record(name="Pad1", layout=io_layout)
46 self.pad2 = Record(name="Pad2", layout=io_layout)
47 self.uart = Record(name="uart", layout=uart_layout)
48 self.i2c = {"sda": Record(name="sda", layout=io_layout),
49 "scl": Record(name="scl", layout=io_layout)
50 }
51 self.bank = Signal(log2_int(self.n_banks))
52
53 def elaborate(self, platform):
54 m = Module()
55 comb, sync = m.d.comb, m.d.sync
56 iomux1 = self.iomux1
57 iomux2 = self.iomux2
58 m.submodules.iomux1 = iomux1
59 m.submodules.iomux2 = iomux2
60
61 pad1 = self.pad1
62 pad2 = self.pad2
63 uart = self.uart
64 i2c = self.i2c
65 bank = self.bank
66
67 comb += iomux1.bank.eq(bank)
68 comb += iomux2.bank.eq(bank)
69
70 # uart connected to bank 0 - Pad 1 tx, Pad 2 rx
71 comb += iomux1.bank_ports[UART_BANK].o.eq(uart.tx)
72 comb += iomux1.bank_ports[UART_BANK].oe.eq(uart.oe)
73 comb += uart.rx.eq(iomux2.bank_ports[UART_BANK].i)
74 # i2c connected to bank 1 - Pad 1 sda, Pad 2 scl
75 comb += iomux1.bank_ports[I2C_BANK].o.eq(i2c["sda"].o)
76 comb += iomux1.bank_ports[I2C_BANK].oe.eq(i2c["sda"].oe)
77 comb += i2c["sda"].i.eq(iomux1.bank_ports[I2C_BANK].i)
78 comb += iomux2.bank_ports[I2C_BANK].o.eq(i2c["scl"].o)
79 comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe)
80 comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i)
81
82 comb += pad1.o.eq(iomux1.out_port.o)
83 comb += pad1.oe.eq(iomux1.out_port.oe)
84 comb += iomux1.out_port.i.eq(pad1.i)
85 comb += pad2.o.eq(iomux2.out_port.o)
86 comb += pad2.oe.eq(iomux2.out_port.oe)
87 comb += iomux2.out_port.i.eq(pad2.i)
88
89 #temp for testing - connect pad rx-tx
90 #comb += pad2.i.eq(pad1.o)
91
92 return m
93
94 def __iter__(self):
95 for field in self.pad1.fields.values():
96 yield field
97 for field in self.pad2.fields.values():
98 yield field
99 for field in self.uart.fields.values():
100 yield field
101 for field in self.i2c["sda"].fields.values():
102 yield field
103 for field in self.i2c["scl"].fields.values():
104 yield field
105 yield self.bank
106
107 def ports(self):
108 return list(self)
109
110 def set_bank(dut, bank, delay=1e-6):
111 yield dut.bank.eq(bank)
112 yield Delay(delay)
113
114 def uart_send(tx, rx, byte, oe=None, delay=1e-6):
115 if oe is not None:
116 yield oe.eq(1)
117 yield tx.eq(1)
118 yield Delay(2*delay)
119 yield tx.eq(0) # start bit
120 yield Delay(delay)
121 result = 0
122 # send one byte, lsb first
123 for i in range(0, 8):
124 bit = (byte >> i) & 0x1
125 yield tx.eq(bit)
126 yield Delay(delay)
127 test_bit = yield rx
128 result |= (test_bit << i)
129 yield tx.eq(1) # stop bit
130 yield Delay(delay)
131 if result == byte:
132 print("Received: %x | Sent: %x" % (byte, result))
133 else:
134 print("Received: %x does NOT match sent: %x" % (byte, result))
135
136
137 def test_man_pinmux(dut):
138 delay = 1e-6
139 yield from set_bank(dut, UART_BANK)
140 yield from uart_send(dut.uart.tx, dut.pad1.o, 0x42, oe=dut.uart.oe)
141 yield dut.pad1.i.eq(1)
142 yield from uart_send(dut.pad2.i, dut.uart.rx, 0x5A)
143
144
145 def sim_man_pinmux():
146 filename = "test_man_pinmux"
147 dut = ManPinmux()
148 vl = rtlil.convert(dut, ports=dut.ports())
149 with open(filename+".il", "w") as f:
150 f.write(vl)
151
152 m = Module()
153 m.submodules.manpinmux = dut
154
155 sim = Simulator(m)
156
157 sim.add_process(wrap(test_man_pinmux(dut)))
158 sim_writer = sim.write_vcd(filename+".vcd")
159 with sim_writer:
160 sim.run()
161 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
162
163 if __name__ == '__main__':
164 sim_man_pinmux()