feat(stage2.py): Added new pads now tested with uart
[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 uart_tx_layout = (("o", 1),
33 ("oe", 1)
34 )
35 GPIO_BANK = 0
36 UART_BANK = 1
37 I2C_BANK = 2
38
39 """
40 Really basic example, uart tx/rx and i2c sda/scl pinmux
41 """
42 class ManPinmux(Elaboratable):
43 def __init__(self, pad_names):
44 print("Test Manual Pinmux!")
45 self.n_banks = 4
46 self.iomux1 = IOMuxBlockSingle(self.n_banks)
47 self.iomux2 = IOMuxBlockSingle(self.n_banks)
48 """
49 self.pads = {}
50 for pad in pad_names:
51 self.pads[pad] = Record(name=pad, layout=io_layout)
52 self.gpio = {"0": Record(name="gp0", layout=io_layout),
53 "1": Record(name="gp1", layout=io_layout)
54 }
55 self.uart = Record(name="uart", layout=uart_layout)
56 self.i2c = {"sda": Record(name="sda", layout=io_layout),
57 "scl": Record(name="scl", layout=io_layout)
58 }
59 """
60 self.bank = Signal(log2_int(self.n_banks))
61 self.pads = {pad_names[0]:{}, pad_names[1]:{}}
62 self.pads["N1"]["pad"] = Record(name=pad_names[0], layout=io_layout)
63 self.pads["N1"]["mux%d" % GPIO_BANK] = Record(name="gp0", layout=io_layout)
64 self.pads["N1"]["mux%d" % UART_BANK] = Record(name="tx", layout=uart_tx_layout)
65 self.pads["N1"]["mux%d" % I2C_BANK] = Record(name="sda", layout=io_layout)
66 self.pads["N2"]["pad"] = Record(name=pad_names[1], layout=io_layout)
67 self.pads["N2"]["mux%d" % GPIO_BANK] = Record(name="gp1", layout=io_layout)
68 self.pads["N2"]["mux%d" % UART_BANK] = Signal(name="rx") # Only one signal
69 self.pads["N2"]["mux%d" % I2C_BANK] = Record(name="scl", layout=io_layout)
70
71 def elaborate(self, platform):
72 m = Module()
73 comb, sync = m.d.comb, m.d.sync
74 iomux1 = self.iomux1
75 iomux2 = self.iomux2
76 m.submodules.iomux1 = iomux1
77 m.submodules.iomux2 = iomux2
78
79 pads = self.pads
80 pad0 = self.pads["N1"]["pad"]
81 gp0 = self.pads["N1"]["mux%d" % GPIO_BANK]
82 gp1 = self.pads["N2"]["mux%d" % GPIO_BANK]
83 tx = self.pads["N1"]["mux%d" % UART_BANK]
84 rx = self.pads["N2"]["mux%d" % UART_BANK]
85 #i2c = self.i2c
86 bank = self.bank
87
88 comb += iomux1.bank.eq(bank)
89 comb += iomux2.bank.eq(bank)
90
91 # ---------------------------
92 # This section is muxing only - doesn'care about pad names
93 # ---------------------------
94 # gpio - gpio0 on Pad1, gpio1 on Pad2
95 comb += iomux1.bank_ports[GPIO_BANK].o.eq(gp0.o)
96 comb += iomux1.bank_ports[GPIO_BANK].oe.eq(gp0.oe)
97 comb += gp0.i.eq(iomux1.bank_ports[GPIO_BANK].i)
98 comb += iomux2.bank_ports[GPIO_BANK].o.eq(gp1.o)
99 comb += iomux2.bank_ports[GPIO_BANK].oe.eq(gp1.oe)
100 comb += gp1.i.eq(iomux2.bank_ports[GPIO_BANK].i)
101 # uart Pad 1 tx, Pad 2 rx
102 comb += iomux1.bank_ports[UART_BANK].o.eq(tx.o)
103 comb += iomux1.bank_ports[UART_BANK].oe.eq(tx.oe)
104 comb += rx.eq(iomux2.bank_ports[UART_BANK].i)
105 # i2c Pad 1 sda, Pad 2 scl
106 #comb += iomux1.bank_ports[I2C_BANK].o.eq(i2c["sda"].o)
107 #comb += iomux1.bank_ports[I2C_BANK].oe.eq(i2c["sda"].oe)
108 #comb += i2c["sda"].i.eq(iomux1.bank_ports[I2C_BANK].i)
109 #comb += iomux2.bank_ports[I2C_BANK].o.eq(i2c["scl"].o)
110 #comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe)
111 #comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i)
112
113 # ---------------------------
114 # Here is where the muxes are assigned to the actual pads
115 # ---------------------------
116 # TODO: for-loop to autoconnect muxes to pads (n_pads var?)
117 comb += pads['N1']["pad"].o.eq(iomux1.out_port.o)
118 comb += pads['N1']["pad"].oe.eq(iomux1.out_port.oe)
119 comb += iomux1.out_port.i.eq(pads['N1']["pad"].i)
120 comb += pads['N2']["pad"].o.eq(iomux2.out_port.o)
121 comb += pads['N2']["pad"].oe.eq(iomux2.out_port.oe)
122 comb += iomux2.out_port.i.eq(pads['N2']["pad"].i)
123
124 return m
125
126 def __iter__(self):
127 for pad in list(self.pads.keys()):
128 for field in self.pads[pad]["pad"].fields.values():
129 yield field
130 #for field in self.uart.fields.values():
131 # yield field
132 #for field in self.i2c["sda"].fields.values():
133 # yield field
134 #for field in self.i2c["scl"].fields.values():
135 # yield field
136 yield self.bank
137
138 def ports(self):
139 return list(self)
140
141 def set_bank(dut, bank, delay=1e-6):
142 yield dut.bank.eq(bank)
143 yield Delay(delay)
144
145 """
146 GPIO test function
147 Set the gpio output based on given data sequence, checked at pad.o
148 Then sends the same byte via pad.i to gpio input
149 """
150 def gpio(gpio, pad, data, delay=1e-6):
151 # Output test - Control GPIO output
152 yield gpio.oe.eq(1)
153 yield Delay(delay)
154 n_bits = len(bin(data)[2:])
155 read = 0
156 for i in range(0, n_bits):
157 bit = (data >> i) & 0x1
158 yield gpio.o.eq(bit)
159 yield Delay(delay)
160 temp = yield pad.o
161 read |= (temp << i)
162 assert data == read, f"GPIO Sent: %x | Pad Read: %x" % (data, read)
163 # Input test - Control Pad input
164 yield gpio.oe.eq(0)
165 yield Delay(delay)
166 read2 = 0
167 for i in range(0, n_bits):
168 bit = (read >> i) & 0x1
169 yield pad.i.eq(bit)
170 yield Delay(delay)
171 temp = yield gpio.i
172 read2 |= (temp << i)
173 assert read2 == read, f"Pad Sent: %x | GPIO Read: %x" % (data, read)
174 # reset input signal
175 yield pad.i.eq(0)
176 yield Delay(delay)
177
178 """
179 UART test function
180 Sends a byte via uart tx, checked at output pad
181 Then sends the same byte via input pad to uart rx
182 Input and output pads are different, so must specify both
183 """
184 def uart_send(tx, rx, pad_tx, pad_rx, byte, delay=1e-6):
185 # Drive uart tx - check the word seen at the Pad
186 yield tx.oe.eq(1)
187 yield tx.o.eq(1)
188 yield Delay(2*delay)
189 yield tx.o.eq(0) # start bit
190 yield Delay(delay)
191 read = 0
192 # send one byte, lsb first
193 for i in range(0, 8):
194 bit = (byte >> i) & 0x1
195 yield tx.o.eq(bit)
196 yield Delay(delay)
197 test_bit = yield pad_tx.o
198 read |= (test_bit << i)
199 yield tx.o.eq(1) # stop bit
200 yield Delay(delay)
201 assert byte == read, f"UART Sent: %x | Pad Read: %x" % (byte, read)
202 # Drive Pad i - check word at uart rx
203 yield pad_rx.i.eq(1)
204 yield Delay(2*delay)
205 yield pad_rx.i.eq(0) # start bit
206 yield Delay(delay)
207 read2 = 0
208 for i in range(0, 8):
209 bit = (read >> i) & 0x1
210 yield pad_rx.i.eq(bit)
211 yield Delay(delay)
212 test_bit = yield rx
213 read2 |= (test_bit << i)
214 yield pad_rx.i.eq(1) # stop bit
215 yield Delay(delay)
216 assert read == read2, f"Pad Sent: %x | UART Read: %x" % (read, read2)
217
218 """
219 I2C test function
220 Sends a byte via SDA.o (peripheral side), checked at output pad
221 Then sends the same byte via input pad to master SDA.i
222 This transaction doesn't make the distinction between read/write bit.
223 """
224 def i2c_send(sda, scl, sda_pad, byte, delay=1e-6):
225 # No checking yet
226 # No pull-up on line implemented, set high instead
227 yield sda.oe.eq(1)
228 yield sda.o.eq(1)
229 yield scl.oe.eq(1)
230 yield scl.o.eq(1)
231 yield sda_pad.i.eq(1)
232 yield Delay(delay)
233 read = 0
234 yield sda.o.eq(0) # start bit
235 yield Delay(delay)
236 for i in range(0, 8):
237 bit = (byte >> i) & 0x1
238 yield sda.o.eq(bit)
239 yield scl.o.eq(0)
240 yield Delay(delay/2)
241 yield scl.o.eq(1)
242 temp = yield sda_pad.o
243 read |= (temp << i)
244 yield Delay(delay/2)
245 yield sda.o.eq(1) # Master releases SDA line
246 yield sda.oe.eq(0)
247 assert byte == read, f"I2C Sent: %x | Pad Read: %x" % (byte, read)
248 # Slave ACK
249 yield sda_pad.i.eq(0)
250 yield scl.o.eq(0)
251 yield Delay(delay/2)
252 yield scl.o.eq(1)
253 yield Delay(delay/2)
254 # Send byte back to master
255 read2 = 0
256 for i in range(0, 8):
257 bit = (read >> i) & 0x1
258 yield sda_pad.i.eq(bit)
259 yield scl.o.eq(0)
260 yield Delay(delay/2)
261 yield scl.o.eq(1)
262 temp = yield sda.i
263 read2 |= (temp << i)
264 yield Delay(delay/2)
265 assert read == read2, f"Pad Sent: %x | I2C Read: %x" % (read, read2)
266 # Master ACK
267 yield sda.oe.eq(1)
268 yield sda.o.eq(0)
269 yield scl.o.eq(0)
270 yield Delay(delay/2)
271 yield scl.o.eq(1)
272 yield Delay(delay/2)
273 # Stop condition - SDA line high after SCL high
274 yield scl.o.eq(0)
275 yield Delay(delay/2)
276 yield scl.o.eq(1)
277 yield Delay(delay/2)
278 yield sda.o.eq(1) # 'release' the SDA line
279
280 # Test the GPIO/UART/I2C connectivity
281 def test_man_pinmux(dut, pad_names):
282 delay = 1e-6
283 # GPIO test
284 yield from set_bank(dut, GPIO_BANK)
285 yield from gpio(dut.pads["N1"]["mux%d" % GPIO_BANK],
286 dut.pads["N1"]["pad"], 0x5a5)
287 yield from gpio(dut.pads["N2"]["mux%d" % GPIO_BANK],
288 dut.pads["N2"]["pad"], 0x5a5)
289 # UART test
290 yield from set_bank(dut, UART_BANK)
291 yield from uart_send(dut.pads["N1"]["mux%d" % UART_BANK],
292 dut.pads["N2"]["mux%d" % UART_BANK],
293 dut.pads['N1']["pad"], dut.pads['N2']["pad"], 0x42)
294 #yield dut.pads['N2'].i.eq(0)
295 #yield Delay(delay)
296 # I2C test
297 #yield from set_bank(dut, I2C_BANK)
298 #yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'], 0x67)
299
300 def sim_man_pinmux():
301 filename = "test_man_pinmux"
302 pad_names = ["N1", "N2"]
303 dut = ManPinmux(pad_names)
304 vl = rtlil.convert(dut, ports=dut.ports())
305 with open(filename+".il", "w") as f:
306 f.write(vl)
307
308 m = Module()
309 m.submodules.manpinmux = dut
310
311 sim = Simulator(m)
312
313 sim.add_process(wrap(test_man_pinmux(dut, pad_names)))
314 sim_writer = sim.write_vcd(filename+".vcd")
315 with sim_writer:
316 sim.run()
317 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
318
319 if __name__ == '__main__':
320 sim_man_pinmux()