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
]
87 comb
+= iomux1
.bank
.eq(bank
)
88 comb
+= iomux2
.bank
.eq(bank
)
90 # ---------------------------
91 # This section is muxing only - doesn'care about pad names
92 # ---------------------------
93 # gpio - gpio0 on Pad1, gpio1 on Pad2
94 comb
+= iomux1
.bank_ports
[GPIO_BANK
].o
.eq(gp0
.o
)
95 comb
+= iomux1
.bank_ports
[GPIO_BANK
].oe
.eq(gp0
.oe
)
96 comb
+= gp0
.i
.eq(iomux1
.bank_ports
[GPIO_BANK
].i
)
97 comb
+= iomux2
.bank_ports
[GPIO_BANK
].o
.eq(gp1
.o
)
98 comb
+= iomux2
.bank_ports
[GPIO_BANK
].oe
.eq(gp1
.oe
)
99 comb
+= gp1
.i
.eq(iomux2
.bank_ports
[GPIO_BANK
].i
)
100 # uart Pad 1 tx, Pad 2 rx
101 #comb += iomux1.bank_ports[UART_BANK].o.eq(uart.tx)
102 #comb += iomux1.bank_ports[UART_BANK].oe.eq(uart.oe)
103 #comb += uart.rx.eq(iomux2.bank_ports[UART_BANK].i)
104 # i2c Pad 1 sda, Pad 2 scl
105 #comb += iomux1.bank_ports[I2C_BANK].o.eq(i2c["sda"].o)
106 #comb += iomux1.bank_ports[I2C_BANK].oe.eq(i2c["sda"].oe)
107 #comb += i2c["sda"].i.eq(iomux1.bank_ports[I2C_BANK].i)
108 #comb += iomux2.bank_ports[I2C_BANK].o.eq(i2c["scl"].o)
109 #comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe)
110 #comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i)
112 # ---------------------------
113 # Here is where the muxes are assigned to the actual pads
114 # ---------------------------
115 # TODO: for-loop to autoconnect muxes to pads (n_pads var?)
116 comb
+= pads
['N1']["pad"].o
.eq(iomux1
.out_port
.o
)
117 comb
+= pads
['N1']["pad"].oe
.eq(iomux1
.out_port
.oe
)
118 comb
+= iomux1
.out_port
.i
.eq(pads
['N1']["pad"].i
)
119 comb
+= pads
['N2']["pad"].o
.eq(iomux2
.out_port
.o
)
120 comb
+= pads
['N2']["pad"].oe
.eq(iomux2
.out_port
.oe
)
121 comb
+= iomux2
.out_port
.i
.eq(pads
['N2']["pad"].i
)
126 for pad
in list(self
.pads
.keys()):
127 for field
in self
.pads
[pad
]["pad"].fields
.values():
129 #for field in self.uart.fields.values():
131 #for field in self.i2c["sda"].fields.values():
133 #for field in self.i2c["scl"].fields.values():
140 def set_bank(dut
, bank
, delay
=1e-6):
141 yield dut
.bank
.eq(bank
)
146 Set the gpio output based on given data sequence, checked at pad.o
147 Then sends the same byte via pad.i to gpio input
149 def gpio(gpio
, pad
, data
, delay
=1e-6):
150 # Output test - Control GPIO output
153 n_bits
= len(bin(data
)[2:])
155 for i
in range(0, n_bits
):
156 bit
= (data
>> i
) & 0x1
161 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
162 # Input test - Control Pad input
166 for i
in range(0, n_bits
):
167 bit
= (read
>> i
) & 0x1
172 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
179 Sends a byte via uart tx, checked at output pad
180 Then sends the same byte via input pad to uart rx
181 Input and output pads are different, so must specify both
183 def uart_send(uart
, pad_o
, pad_i
, byte
, delay
=1e-6):
184 # Drive uart tx - check the word seen at the Pad
188 yield uart
.tx
.eq(0) # start bit
191 # send one byte, lsb first
192 for i
in range(0, 8):
193 bit
= (byte
>> i
) & 0x1
194 yield uart
.tx
.eq(bit
)
196 test_bit
= yield pad_o
197 read |
= (test_bit
<< i
)
198 yield uart
.tx
.eq(1) # stop bit
200 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
201 # Drive Pad i - check word at uart rx
204 yield pad_i
.eq(0) # start bit
207 for i
in range(0, 8):
208 bit
= (read
>> i
) & 0x1
211 test_bit
= yield uart
.rx
212 read2 |
= (test_bit
<< i
)
213 yield pad_i
.eq(1) # stop bit
215 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
219 Sends a byte via SDA.o (peripheral side), checked at output pad
220 Then sends the same byte via input pad to master SDA.i
221 This transaction doesn't make the distinction between read/write bit.
223 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
225 # No pull-up on line implemented, set high instead
230 yield sda_pad
.i
.eq(1)
233 yield sda
.o
.eq(0) # start bit
235 for i
in range(0, 8):
236 bit
= (byte
>> i
) & 0x1
241 temp
= yield sda_pad
.o
244 yield sda
.o
.eq(1) # Master releases SDA line
246 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
248 yield sda_pad
.i
.eq(0)
253 # Send byte back to master
255 for i
in range(0, 8):
256 bit
= (read
>> i
) & 0x1
257 yield sda_pad
.i
.eq(bit
)
264 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
272 # Stop condition - SDA line high after SCL high
277 yield sda
.o
.eq(1) # 'release' the SDA line
279 # Test the GPIO/UART/I2C connectivity
280 def test_man_pinmux(dut
, pad_names
):
283 yield from set_bank(dut
, GPIO_BANK
)
284 yield from gpio(dut
.pads
["N1"]["mux0"], dut
.pads
["N1"]["pad"], 0x5a5)
285 yield from gpio(dut
.pads
["N2"]["mux0"], dut
.pads
["N2"]["pad"], 0x5a5)
287 #yield from set_bank(dut, UART_BANK)
288 #yield from uart_send(dut.uart, dut.pads['N1'].o, dut.pads['N2'].i, 0x42)
289 #yield dut.pads['N2'].i.eq(0)
292 #yield from set_bank(dut, I2C_BANK)
293 #yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'], 0x67)
295 def sim_man_pinmux():
296 filename
= "test_man_pinmux"
297 pad_names
= ["N1", "N2"]
298 dut
= ManPinmux(pad_names
)
299 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
300 with
open(filename
+".il", "w") as f
:
304 m
.submodules
.manpinmux
= dut
308 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
309 sim_writer
= sim
.write_vcd(filename
+".vcd")
312 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
314 if __name__
== '__main__':