Added gpio demo, parametrised pads
[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 GPIO_BANK = 0
34 UART_BANK = 1
35 I2C_BANK = 2
36
37 """
38 Really basic example, uart tx/rx and i2c sda/scl pinmux
39 """
40 class ManPinmux(Elaboratable):
41 def __init__(self, pad_names):
42 print("Test Manual Pinmux!")
43 self.n_banks = 4
44 self.iomux1 = IOMuxBlockSingle(self.n_banks)
45 self.iomux2 = IOMuxBlockSingle(self.n_banks)
46 self.pads = {}
47 for pad in pad_names:
48 self.pads[pad] = Record(name=pad, layout=io_layout)
49 self.gpio = {"0": Record(name="gp0", layout=io_layout),
50 "1": Record(name="gp1", layout=io_layout)
51 }
52 self.uart = Record(name="uart", layout=uart_layout)
53 self.i2c = {"sda": Record(name="sda", layout=io_layout),
54 "scl": Record(name="scl", layout=io_layout)
55 }
56 self.bank = Signal(log2_int(self.n_banks))
57
58 def elaborate(self, platform):
59 m = Module()
60 comb, sync = m.d.comb, m.d.sync
61 iomux1 = self.iomux1
62 iomux2 = self.iomux2
63 m.submodules.iomux1 = iomux1
64 m.submodules.iomux2 = iomux2
65
66 pads = self.pads
67 gpio = self.gpio
68 uart = self.uart
69 i2c = self.i2c
70 bank = self.bank
71
72 comb += iomux1.bank.eq(bank)
73 comb += iomux2.bank.eq(bank)
74
75 # ---------------------------
76 # This section is muxing only - doesn'care about pad names
77 # ---------------------------
78 # gpio - gpio0 on Pad1, gpio1 on Pad2
79 comb += iomux1.bank_ports[GPIO_BANK].o.eq(gpio["0"].o)
80 comb += iomux1.bank_ports[GPIO_BANK].oe.eq(gpio["0"].oe)
81 comb += gpio["0"].i.eq(iomux1.bank_ports[GPIO_BANK].i)
82 comb += iomux2.bank_ports[GPIO_BANK].o.eq(gpio["1"].o)
83 comb += iomux2.bank_ports[GPIO_BANK].oe.eq(gpio["1"].oe)
84 comb += gpio["1"].i.eq(iomux2.bank_ports[GPIO_BANK].i)
85 # uart Pad 1 tx, Pad 2 rx
86 comb += iomux1.bank_ports[UART_BANK].o.eq(uart.tx)
87 comb += iomux1.bank_ports[UART_BANK].oe.eq(uart.oe)
88 comb += uart.rx.eq(iomux2.bank_ports[UART_BANK].i)
89 # i2c Pad 1 sda, Pad 2 scl
90 comb += iomux1.bank_ports[I2C_BANK].o.eq(i2c["sda"].o)
91 comb += iomux1.bank_ports[I2C_BANK].oe.eq(i2c["sda"].oe)
92 comb += i2c["sda"].i.eq(iomux1.bank_ports[I2C_BANK].i)
93 comb += iomux2.bank_ports[I2C_BANK].o.eq(i2c["scl"].o)
94 comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe)
95 comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i)
96
97 # ---------------------------
98 # Here is where the muxes are assigned to the actual pads
99 # ---------------------------
100 # TODO: for-loop to autoconnect muxes to pads (n_pads var?)
101 comb += pads['N1'].o.eq(iomux1.out_port.o)
102 comb += pads['N1'].oe.eq(iomux1.out_port.oe)
103 comb += iomux1.out_port.i.eq(pads['N1'].i)
104 comb += pads['N2'].o.eq(iomux2.out_port.o)
105 comb += pads['N2'].oe.eq(iomux2.out_port.oe)
106 comb += iomux2.out_port.i.eq(pads['N2'].i)
107
108 #temp for testing - connect pad rx-tx
109 #comb += pad2.i.eq(pad1.o)
110
111 return m
112
113 def __iter__(self):
114 for pad in list(self.pads.keys()):
115 for field in self.pads[pad].fields.values():
116 yield field
117 for field in self.uart.fields.values():
118 yield field
119 for field in self.i2c["sda"].fields.values():
120 yield field
121 for field in self.i2c["scl"].fields.values():
122 yield field
123 yield self.bank
124
125 def ports(self):
126 return list(self)
127
128 def set_bank(dut, bank, delay=1e-6):
129 yield dut.bank.eq(bank)
130 yield Delay(delay)
131
132 def gpio(gpio, pad, data, delay=1e-6):
133 # Output test - Control GPIO output
134 yield gpio.oe.eq(1)
135 yield Delay(delay)
136 n_bits = len(bin(data)[2:])
137 read = 0
138 for i in range(0, n_bits):
139 bit = (data >> i) & 0x1
140 yield gpio.o.eq(bit)
141 yield Delay(delay)
142 temp = yield pad.o
143 read |= (temp << i)
144 assert data == read, f"GPIO Sent: %x | Pad Read: %x" % (data, read)
145 # Input test - Control Pad input
146 yield gpio.oe.eq(0)
147 yield Delay(delay)
148 read2 = 0
149 for i in range(0, n_bits):
150 bit = (read >> i) & 0x1
151 yield pad.i.eq(bit)
152 yield Delay(delay)
153 temp = yield gpio.i
154 read2 |= (temp << i)
155 assert read2 == read, f"Pad Sent: %x | GPIO Read: %x" % (data, read)
156
157 def uart_send(tx, rx, byte, oe=None, delay=1e-6):
158 if oe is not None:
159 yield oe.eq(1)
160 yield tx.eq(1)
161 yield Delay(2*delay)
162 yield tx.eq(0) # start bit
163 yield Delay(delay)
164 result = 0
165 # send one byte, lsb first
166 for i in range(0, 8):
167 bit = (byte >> i) & 0x1
168 yield tx.eq(bit)
169 yield Delay(delay)
170 test_bit = yield rx
171 result |= (test_bit << i)
172 yield tx.eq(1) # stop bit
173 yield Delay(delay)
174 if result == byte:
175 print("Received: %x | Sent: %x" % (byte, result))
176 else:
177 print("Received: %x does NOT match sent: %x" % (byte, result))
178
179 def i2c_send(sda, scl, sda_pad_i, byte, delay=1e-6):
180 # No checking yet
181 # No pull-up on line implemented, set high instead
182 yield sda.oe.eq(1)
183 yield sda.o.eq(1)
184 yield scl.oe.eq(1)
185 yield scl.o.eq(1)
186 yield sda_pad_i.eq(1)
187 yield Delay(delay)
188 yield sda.o.eq(0) # start bit
189 yield Delay(delay)
190 for i in range(0, 8):
191 bit = (byte >> i) & 0x1
192 yield sda.o.eq(bit)
193 yield scl.o.eq(0)
194 yield Delay(delay/2)
195 yield scl.o.eq(1)
196 yield Delay(delay/2)
197 yield sda.o.eq(1) # Master releases SDA line
198 yield sda.oe.eq(0)
199 yield sda_pad_i.eq(0) # ACK
200 yield Delay(delay)
201 yield sda_pad_i.eq(1)
202
203
204
205 def test_man_pinmux(dut, pad_names):
206 delay = 1e-6
207 # GPIO test
208 yield from gpio(dut.gpio['0'], dut.pads['N1'], 0x5a5)
209 yield from gpio(dut.gpio['1'], dut.pads['N2'], 0x5a5)
210 # UART test
211 yield from set_bank(dut, UART_BANK)
212 yield from uart_send(dut.uart.tx, dut.pads['N1'].o, 0x42, oe=dut.uart.oe)
213 yield from uart_send(dut.pads['N2'].i, dut.uart.rx, 0x5a)
214 yield dut.pads['N2'].i.eq(0)
215 yield Delay(delay)
216 # I2C test
217 yield from set_bank(dut, I2C_BANK)
218 yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'].i, 0x67)
219
220 yield dut.gpio['0'].oe.eq(1)
221 yield Delay(delay)
222 yield dut.gpio['0'].oe.eq(0)
223 yield Delay(delay)
224
225 def sim_man_pinmux():
226 filename = "test_man_pinmux"
227 pad_names = ["N1", "N2"]
228 dut = ManPinmux(pad_names)
229 vl = rtlil.convert(dut, ports=dut.ports())
230 with open(filename+".il", "w") as f:
231 f.write(vl)
232
233 m = Module()
234 m.submodules.manpinmux = dut
235
236 sim = Simulator(m)
237
238 sim.add_process(wrap(test_man_pinmux(dut, pad_names)))
239 sim_writer = sim.write_vcd(filename+".vcd")
240 with sim_writer:
241 sim.run()
242 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
243
244 if __name__ == '__main__':
245 sim_man_pinmux()