3 pinmux documented here https://libre-soc.org/docs/pinmux/
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
13 from nmutil
.gtkw
import write_gtkw
17 from nmigen
.sim
.cxxsim
import Simulator
, Settle
, Delay
19 from nmigen
.sim
import Simulator
, Settle
, Delay
21 from iomux
import IOMuxBlockSingle
23 io_layout
= (("i", 1),
28 uart_layout
= (("rx", 1),
32 uart_tx_layout
= (("o", 1),
40 Really basic example, uart tx/rx and i2c sda/scl pinmux
42 class ManPinmux(Elaboratable
):
43 def __init__(self
, pad_names
):
44 print("Test Manual Pinmux!")
46 self
.iomux1
= IOMuxBlockSingle(self
.n_banks
)
47 self
.iomux2
= IOMuxBlockSingle(self
.n_banks
)
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)
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)
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
)
71 def elaborate(self
, platform
):
73 comb
, sync
= m
.d
.comb
, m
.d
.sync
76 m
.submodules
.iomux1
= iomux1
77 m
.submodules
.iomux2
= iomux2
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
]
88 comb
+= iomux1
.bank
.eq(bank
)
89 comb
+= iomux2
.bank
.eq(bank
)
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)
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
)
127 for pad
in list(self
.pads
.keys()):
128 for field
in self
.pads
[pad
]["pad"].fields
.values():
130 #for field in self.uart.fields.values():
132 #for field in self.i2c["sda"].fields.values():
134 #for field in self.i2c["scl"].fields.values():
141 def set_bank(dut
, bank
, delay
=1e-6):
142 yield dut
.bank
.eq(bank
)
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
150 def gpio(gpio
, pad
, data
, delay
=1e-6):
151 # Output test - Control GPIO output
154 n_bits
= len(bin(data
)[2:])
156 for i
in range(0, n_bits
):
157 bit
= (data
>> i
) & 0x1
162 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
163 # Input test - Control Pad input
167 for i
in range(0, n_bits
):
168 bit
= (read
>> i
) & 0x1
173 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
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
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
189 yield tx
.o
.eq(0) # start bit
192 # send one byte, lsb first
193 for i
in range(0, 8):
194 bit
= (byte
>> i
) & 0x1
197 test_bit
= yield pad_tx
.o
198 read |
= (test_bit
<< i
)
199 yield tx
.o
.eq(1) # stop bit
201 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
202 # Drive Pad i - check word at uart rx
205 yield pad_rx
.i
.eq(0) # start bit
208 for i
in range(0, 8):
209 bit
= (read
>> i
) & 0x1
210 yield pad_rx
.i
.eq(bit
)
213 read2 |
= (test_bit
<< i
)
214 yield pad_rx
.i
.eq(1) # stop bit
216 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
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.
224 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
226 # No pull-up on line implemented, set high instead
231 yield sda_pad
.i
.eq(1)
234 yield sda
.o
.eq(0) # start bit
236 for i
in range(0, 8):
237 bit
= (byte
>> i
) & 0x1
242 temp
= yield sda_pad
.o
245 yield sda
.o
.eq(1) # Master releases SDA line
247 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
249 yield sda_pad
.i
.eq(0)
254 # Send byte back to master
256 for i
in range(0, 8):
257 bit
= (read
>> i
) & 0x1
258 yield sda_pad
.i
.eq(bit
)
265 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
273 # Stop condition - SDA line high after SCL high
278 yield sda
.o
.eq(1) # 'release' the SDA line
280 # Test the GPIO/UART/I2C connectivity
281 def test_man_pinmux(dut
, pad_names
):
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)
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)
297 #yield from set_bank(dut, I2C_BANK)
298 #yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'], 0x67)
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
:
309 m
.submodules
.manpinmux
= dut
313 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
314 sim_writer
= sim
.write_vcd(filename
+".vcd")
317 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
319 if __name__
== '__main__':