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
.requested
= {"N1": {"mux%d" % GPIO_BANK
: ["gpio", 0],
47 "mux%d" % UART_BANK
: ["uart", 0, "tx"],
48 "mux%d" % I2C_BANK
: ["i2c", 0, "sda"]},
49 "N2": {"mux%d" % GPIO_BANK
: ["gpio", 1],
50 "mux%d" % UART_BANK
: ["uart", 0, "rx"],
51 "mux%d" % I2C_BANK
: ["i2c", 0, "scl"]}
54 self
.bank
= Signal(log2_int(self
.n_banks
))
57 for pad
in self
.requested
.keys():
59 self
.pads
[pad
]["pad"] = Record(name
=pad
, layout
=io_layout
)
60 self
.muxes
[pad
] = IOMuxBlockSingle(self
.n_banks
)
61 for mux
in self
.requested
[pad
].keys():
62 periph
= self
.requested
[pad
][mux
][0]
63 unit_num
= self
.requested
[pad
][mux
][1]
64 if len(self
.requested
[pad
][mux
]) == 3:
65 pin
= self
.requested
[pad
][mux
][2]
69 self
.pads
[pad
][mux
] = Record(name
="gp%d" % unit_num
,
71 elif periph
== "uart":
73 self
.pads
[pad
][mux
] = Record(name
="tx%d" % unit_num
,
74 layout
=uart_tx_layout
)
76 self
.pads
[pad
][mux
] = Signal(name
="rx%d" % unit_num
)
79 self
.pads
[pad
][mux
] = Record(name
="sda%d" % unit_num
,
82 self
.pads
[pad
][mux
] = Record(name
="scl%d" % unit_num
,
85 def elaborate(self
, platform
):
87 comb
, sync
= m
.d
.comb
, m
.d
.sync
90 # TODO: replace with pin specific
93 for pad
in self
.pads
.keys():
94 m
.submodules
[pad
+"_mux"] = muxes
[pad
]
95 # all muxes controlled by the same multi-bit signal
96 comb
+= muxes
[pad
].bank
.eq(bank
)
98 # print(self.requested)
101 # ---------------------------
102 # This section connects the periphs to the assigned banks
103 # ---------------------------
104 for pad
in self
.pads
.keys():
105 for mux
in self
.requested
[pad
].keys():
106 periph
= self
.requested
[pad
][mux
][0]
108 if len(self
.requested
[pad
][mux
]) == 3:
109 pin
= self
.requested
[pad
][mux
][2]
112 if periph
== "gpio" or periph
== "i2c":
113 comb
+= muxes
[pad
].bank_ports
[num
].o
.eq(pads
[pad
][mux
].o
)
114 comb
+= muxes
[pad
].bank_ports
[num
].oe
.eq(pads
[pad
][mux
].oe
)
115 comb
+= pads
[pad
][mux
].i
.eq(muxes
[pad
].bank_ports
[num
].i
)
116 elif periph
== "uart":
118 comb
+= muxes
[pad
].bank_ports
[num
].o
.eq(
120 comb
+= muxes
[pad
].bank_ports
[num
].oe
.eq(
123 comb
+= pads
[pad
][mux
].eq(muxes
[pad
].bank_ports
[num
].i
)
125 # ---------------------------
126 # Here is where the muxes are assigned to the actual pads
127 # ---------------------------
128 for pad
in self
.pads
.keys():
129 comb
+= pads
[pad
]["pad"].o
.eq(muxes
[pad
].out_port
.o
)
130 comb
+= pads
[pad
]["pad"].oe
.eq(muxes
[pad
].out_port
.oe
)
131 comb
+= muxes
[pad
].out_port
.i
.eq(pads
[pad
]["pad"].i
)
136 for pad
in list(self
.pads
.keys()):
137 for field
in self
.pads
[pad
]["pad"].fields
.values():
140 #for field in self.uart.fields.values():
142 #for field in self.i2c["sda"].fields.values():
144 #for field in self.i2c["scl"].fields.values():
151 def set_bank(dut
, bank
, delay
=1e-6):
152 yield dut
.bank
.eq(bank
)
157 Set the gpio output based on given data sequence, checked at pad.o
158 Then sends the same byte via pad.i to gpio input
160 def gpio(gpio
, pad
, data
, delay
=1e-6):
161 # Output test - Control GPIO output
164 n_bits
= len(bin(data
)[2:])
166 for i
in range(0, n_bits
):
167 bit
= (data
>> i
) & 0x1
172 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
173 # Input test - Control Pad input
177 for i
in range(0, n_bits
):
178 bit
= (read
>> i
) & 0x1
183 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
190 Sends a byte via uart tx, checked at output pad
191 Then sends the same byte via input pad to uart rx
192 Input and output pads are different, so must specify both
194 def uart_send(tx
, rx
, pad_tx
, pad_rx
, byte
, delay
=1e-6):
195 # Drive uart tx - check the word seen at the Pad
199 yield tx
.o
.eq(0) # start bit
202 # send one byte, lsb first
203 for i
in range(0, 8):
204 bit
= (byte
>> i
) & 0x1
207 test_bit
= yield pad_tx
.o
208 read |
= (test_bit
<< i
)
209 yield tx
.o
.eq(1) # stop bit
211 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
212 # Drive Pad i - check word at uart rx
215 yield pad_rx
.i
.eq(0) # start bit
218 for i
in range(0, 8):
219 bit
= (read
>> i
) & 0x1
220 yield pad_rx
.i
.eq(bit
)
223 read2 |
= (test_bit
<< i
)
224 yield pad_rx
.i
.eq(1) # stop bit
226 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
230 Sends a byte via SDA.o (peripheral side), checked at output pad
231 Then sends the same byte via input pad to master SDA.i
232 This transaction doesn't make the distinction between read/write bit.
234 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
236 # No pull-up on line implemented, set high instead
241 yield sda_pad
.i
.eq(1)
244 yield sda
.o
.eq(0) # start bit
246 for i
in range(0, 8):
247 bit
= (byte
>> i
) & 0x1
252 temp
= yield sda_pad
.o
255 yield sda
.o
.eq(1) # Master releases SDA line
257 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
259 yield sda_pad
.i
.eq(0)
264 # Send byte back to master
266 for i
in range(0, 8):
267 bit
= (read
>> i
) & 0x1
268 yield sda_pad
.i
.eq(bit
)
275 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
283 # Stop condition - SDA line high after SCL high
288 yield sda
.o
.eq(1) # 'release' the SDA line
290 # Test the GPIO/UART/I2C connectivity
291 def test_man_pinmux(dut
, pad_names
):
294 yield from set_bank(dut
, GPIO_BANK
)
295 yield from gpio(dut
.pads
["N1"]["mux%d" % GPIO_BANK
],
296 dut
.pads
["N1"]["pad"], 0x5a5)
297 yield from gpio(dut
.pads
["N2"]["mux%d" % GPIO_BANK
],
298 dut
.pads
["N2"]["pad"], 0x5a5)
300 yield from set_bank(dut
, UART_BANK
)
301 yield from uart_send(dut
.pads
["N1"]["mux%d" % UART_BANK
],
302 dut
.pads
["N2"]["mux%d" % UART_BANK
],
303 dut
.pads
['N1']["pad"], dut
.pads
['N2']["pad"], 0x42)
304 #yield dut.pads['N2'].i.eq(0)
307 yield from set_bank(dut
, I2C_BANK
)
308 yield from i2c_send(dut
.pads
["N1"]["mux%d" % I2C_BANK
],
309 dut
.pads
["N2"]["mux%d" % I2C_BANK
],
310 dut
.pads
['N1']["pad"], 0x67)
312 def sim_man_pinmux():
313 filename
= "test_man_pinmux"
314 pad_names
= ["N1", "N2"]
315 dut
= ManPinmux(pad_names
)
316 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
317 with
open(filename
+".il", "w") as f
:
321 m
.submodules
.manpinmux
= dut
325 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
326 sim_writer
= sim
.write_vcd(filename
+".vcd")
329 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
331 if __name__
== '__main__':