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),
38 Really basic example, uart tx/rx and i2c sda/scl pinmux
40 class ManPinmux(Elaboratable
):
41 def __init__(self
, pad_names
):
42 print("Test Manual Pinmux!")
44 self
.iomux1
= IOMuxBlockSingle(self
.n_banks
)
45 self
.iomux2
= IOMuxBlockSingle(self
.n_banks
)
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
)
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
)
56 self
.bank
= Signal(log2_int(self
.n_banks
))
58 def elaborate(self
, platform
):
60 comb
, sync
= m
.d
.comb
, m
.d
.sync
63 m
.submodules
.iomux1
= iomux1
64 m
.submodules
.iomux2
= iomux2
72 comb
+= iomux1
.bank
.eq(bank
)
73 comb
+= iomux2
.bank
.eq(bank
)
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
)
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
)
108 #temp for testing - connect pad rx-tx
109 #comb += pad2.i.eq(pad1.o)
114 for pad
in list(self
.pads
.keys()):
115 for field
in self
.pads
[pad
].fields
.values():
117 for field
in self
.uart
.fields
.values():
119 for field
in self
.i2c
["sda"].fields
.values():
121 for field
in self
.i2c
["scl"].fields
.values():
128 def set_bank(dut
, bank
, delay
=1e-6):
129 yield dut
.bank
.eq(bank
)
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
137 def gpio(gpio
, pad
, data
, delay
=1e-6):
138 # Output test - Control GPIO output
141 n_bits
= len(bin(data
)[2:])
143 for i
in range(0, n_bits
):
144 bit
= (data
>> i
) & 0x1
149 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
150 # Input test - Control Pad input
154 for i
in range(0, n_bits
):
155 bit
= (read
>> i
) & 0x1
160 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
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
171 def uart_send(uart
, pad_o
, pad_i
, byte
, delay
=1e-6):
172 # Drive uart tx - check the word seen at the Pad
176 yield uart
.tx
.eq(0) # start bit
179 # send one byte, lsb first
180 for i
in range(0, 8):
181 bit
= (byte
>> i
) & 0x1
182 yield uart
.tx
.eq(bit
)
184 test_bit
= yield pad_o
185 read |
= (test_bit
<< i
)
186 yield uart
.tx
.eq(1) # stop bit
188 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
189 # Drive Pad i - check word at uart rx
192 yield pad_i
.eq(0) # start bit
195 for i
in range(0, 8):
196 bit
= (read
>> i
) & 0x1
199 test_bit
= yield uart
.rx
200 read2 |
= (test_bit
<< i
)
201 yield pad_i
.eq(1) # stop bit
203 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
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.
211 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
213 # No pull-up on line implemented, set high instead
218 yield sda_pad
.i
.eq(1)
221 yield sda
.o
.eq(0) # start bit
223 for i
in range(0, 8):
224 bit
= (byte
>> i
) & 0x1
229 temp
= yield sda_pad
.o
232 yield sda
.o
.eq(1) # Master releases SDA line
234 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
236 yield sda_pad
.i
.eq(0)
241 # Send byte back to master
243 for i
in range(0, 8):
244 bit
= (read
>> i
) & 0x1
245 yield sda_pad
.i
.eq(bit
)
252 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
260 # Stop condition - SDA line high after SCL high
265 yield sda
.o
.eq(1) # 'release' the SDA line
267 # Test the GPIO/UART/I2C connectivity
268 def test_man_pinmux(dut
, pad_names
):
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)
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)
280 yield from set_bank(dut
, I2C_BANK
)
281 yield from i2c_send(dut
.i2c
['sda'], dut
.i2c
['scl'], dut
.pads
['N1'], 0x67)
283 yield dut
.gpio
['0'].oe
.eq(1)
285 yield dut
.gpio
['0'].oe
.eq(0)
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
:
297 m
.submodules
.manpinmux
= dut
301 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
302 sim_writer
= sim
.write_vcd(filename
+".vcd")
305 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
307 if __name__
== '__main__':