feat: I2C demo test now loopback
[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 """
133 GPIO test function
134 Set the gpio output based on given data sequence, checked at pad.o
135 Then sends the same byte via pad.i to gpio input
136 """
137 def gpio(gpio, pad, data, delay=1e-6):
138 # Output test - Control GPIO output
139 yield gpio.oe.eq(1)
140 yield Delay(delay)
141 n_bits = len(bin(data)[2:])
142 read = 0
143 for i in range(0, n_bits):
144 bit = (data >> i) & 0x1
145 yield gpio.o.eq(bit)
146 yield Delay(delay)
147 temp = yield pad.o
148 read |= (temp << i)
149 assert data == read, f"GPIO Sent: %x | Pad Read: %x" % (data, read)
150 # Input test - Control Pad input
151 yield gpio.oe.eq(0)
152 yield Delay(delay)
153 read2 = 0
154 for i in range(0, n_bits):
155 bit = (read >> i) & 0x1
156 yield pad.i.eq(bit)
157 yield Delay(delay)
158 temp = yield gpio.i
159 read2 |= (temp << i)
160 assert read2 == read, f"Pad Sent: %x | GPIO Read: %x" % (data, read)
161 # reset input signal
162 yield pad.i.eq(0)
163 yield Delay(delay)
164
165 """
166 UART test function
167 Sends a byte via uart tx, checked at output pad
168 Then sends the same byte via input pad to uart rx
169 Input and output pads are different, so must specify both
170 """
171 def uart_send(uart, pad_o, pad_i, byte, delay=1e-6):
172 # Drive uart tx - check the word seen at the Pad
173 yield uart.oe.eq(1)
174 yield uart.tx.eq(1)
175 yield Delay(2*delay)
176 yield uart.tx.eq(0) # start bit
177 yield Delay(delay)
178 read = 0
179 # send one byte, lsb first
180 for i in range(0, 8):
181 bit = (byte >> i) & 0x1
182 yield uart.tx.eq(bit)
183 yield Delay(delay)
184 test_bit = yield pad_o
185 read |= (test_bit << i)
186 yield uart.tx.eq(1) # stop bit
187 yield Delay(delay)
188 assert byte == read, f"UART Sent: %x | Pad Read: %x" % (byte, read)
189 # Drive Pad i - check word at uart rx
190 yield pad_i.eq(1)
191 yield Delay(2*delay)
192 yield pad_i.eq(0) # start bit
193 yield Delay(delay)
194 read2 = 0
195 for i in range(0, 8):
196 bit = (read >> i) & 0x1
197 yield pad_i.eq(bit)
198 yield Delay(delay)
199 test_bit = yield uart.rx
200 read2 |= (test_bit << i)
201 yield pad_i.eq(1) # stop bit
202 yield Delay(delay)
203 assert read == read2, f"Pad Sent: %x | UART Read: %x" % (read, read2)
204
205 """
206 I2C test function
207 Sends a byte via SDA.o (peripheral side), checked at output pad
208 Then sends the same byte via input pad to master SDA.i
209 This transaction doesn't make the distinction between read/write bit.
210 """
211 def i2c_send(sda, scl, sda_pad, byte, delay=1e-6):
212 # No checking yet
213 # No pull-up on line implemented, set high instead
214 yield sda.oe.eq(1)
215 yield sda.o.eq(1)
216 yield scl.oe.eq(1)
217 yield scl.o.eq(1)
218 yield sda_pad.i.eq(1)
219 yield Delay(delay)
220 read = 0
221 yield sda.o.eq(0) # start bit
222 yield Delay(delay)
223 for i in range(0, 8):
224 bit = (byte >> i) & 0x1
225 yield sda.o.eq(bit)
226 yield scl.o.eq(0)
227 yield Delay(delay/2)
228 yield scl.o.eq(1)
229 temp = yield sda_pad.o
230 read |= (temp << i)
231 yield Delay(delay/2)
232 yield sda.o.eq(1) # Master releases SDA line
233 yield sda.oe.eq(0)
234 assert byte == read, f"I2C Sent: %x | Pad Read: %x" % (byte, read)
235 # Slave ACK
236 yield sda_pad.i.eq(0)
237 yield scl.o.eq(0)
238 yield Delay(delay/2)
239 yield scl.o.eq(1)
240 yield Delay(delay/2)
241 # Send byte back to master
242 read2 = 0
243 for i in range(0, 8):
244 bit = (read >> i) & 0x1
245 yield sda_pad.i.eq(bit)
246 yield scl.o.eq(0)
247 yield Delay(delay/2)
248 yield scl.o.eq(1)
249 temp = yield sda.i
250 read2 |= (temp << i)
251 yield Delay(delay/2)
252 assert read == read2, f"Pad Sent: %x | I2C Read: %x" % (read, read2)
253 # Master ACK
254 yield sda.oe.eq(1)
255 yield sda.o.eq(0)
256 yield scl.o.eq(0)
257 yield Delay(delay/2)
258 yield scl.o.eq(1)
259 yield Delay(delay/2)
260 # Stop condition - SDA line high after SCL high
261 yield scl.o.eq(0)
262 yield Delay(delay/2)
263 yield scl.o.eq(1)
264 yield Delay(delay/2)
265 yield sda.o.eq(1) # 'release' the SDA line
266
267 # Test the GPIO/UART/I2C connectivity
268 def test_man_pinmux(dut, pad_names):
269 delay = 1e-6
270 # GPIO test
271 yield from set_bank(dut, GPIO_BANK)
272 yield from gpio(dut.gpio['0'], dut.pads['N1'], 0x5a5)
273 yield from gpio(dut.gpio['1'], dut.pads['N2'], 0x5a5)
274 # UART test
275 yield from set_bank(dut, UART_BANK)
276 yield from uart_send(dut.uart, dut.pads['N1'].o, dut.pads['N2'].i, 0x42)
277 yield dut.pads['N2'].i.eq(0)
278 yield Delay(delay)
279 # I2C test
280 yield from set_bank(dut, I2C_BANK)
281 yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'], 0x67)
282
283 yield dut.gpio['0'].oe.eq(1)
284 yield Delay(delay)
285 yield dut.gpio['0'].oe.eq(0)
286 yield Delay(delay)
287
288 def sim_man_pinmux():
289 filename = "test_man_pinmux"
290 pad_names = ["N1", "N2"]
291 dut = ManPinmux(pad_names)
292 vl = rtlil.convert(dut, ports=dut.ports())
293 with open(filename+".il", "w") as f:
294 f.write(vl)
295
296 m = Module()
297 m.submodules.manpinmux = dut
298
299 sim = Simulator(m)
300
301 sim.add_process(wrap(test_man_pinmux(dut, pad_names)))
302 sim_writer = sim.write_vcd(filename+".vcd")
303 with sim_writer:
304 sim.run()
305 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
306
307 if __name__ == '__main__':
308 sim_man_pinmux()