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
)
132 def gpio(gpio
, pad
, data
, delay
=1e-6):
133 # Output test - Control GPIO output
136 n_bits
= len(bin(data
)[2:])
138 for i
in range(0, n_bits
):
139 bit
= (data
>> i
) & 0x1
144 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
145 # Input test - Control Pad input
149 for i
in range(0, n_bits
):
150 bit
= (read
>> i
) & 0x1
155 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
157 def uart_send(tx
, rx
, byte
, oe
=None, delay
=1e-6):
162 yield tx
.eq(0) # start bit
165 # send one byte, lsb first
166 for i
in range(0, 8):
167 bit
= (byte
>> i
) & 0x1
171 result |
= (test_bit
<< i
)
172 yield tx
.eq(1) # stop bit
175 print("Received: %x | Sent: %x" % (byte
, result
))
177 print("Received: %x does NOT match sent: %x" % (byte
, result
))
179 def i2c_send(sda
, scl
, sda_pad_i
, byte
, delay
=1e-6):
181 # No pull-up on line implemented, set high instead
186 yield sda_pad_i
.eq(1)
188 yield sda
.o
.eq(0) # start bit
190 for i
in range(0, 8):
191 bit
= (byte
>> i
) & 0x1
197 yield sda
.o
.eq(1) # Master releases SDA line
199 yield sda_pad_i
.eq(0) # ACK
201 yield sda_pad_i
.eq(1)
205 def test_man_pinmux(dut
, pad_names
):
208 yield from gpio(dut
.gpio
['0'], dut
.pads
['N1'], 0x5a5)
209 yield from gpio(dut
.gpio
['1'], dut
.pads
['N2'], 0x5a5)
211 yield from set_bank(dut
, UART_BANK
)
212 yield from uart_send(dut
.uart
.tx
, dut
.pads
['N1'].o
, 0x42, oe
=dut
.uart
.oe
)
213 yield from uart_send(dut
.pads
['N2'].i
, dut
.uart
.rx
, 0x5a)
214 yield dut
.pads
['N2'].i
.eq(0)
217 yield from set_bank(dut
, I2C_BANK
)
218 yield from i2c_send(dut
.i2c
['sda'], dut
.i2c
['scl'], dut
.pads
['N1'].i
, 0x67)
220 yield dut
.gpio
['0'].oe
.eq(1)
222 yield dut
.gpio
['0'].oe
.eq(0)
225 def sim_man_pinmux():
226 filename
= "test_man_pinmux"
227 pad_names
= ["N1", "N2"]
228 dut
= ManPinmux(pad_names
)
229 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
230 with
open(filename
+".il", "w") as f
:
234 m
.submodules
.manpinmux
= dut
238 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
239 sim_writer
= sim
.write_vcd(filename
+".vcd")
242 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
244 if __name__
== '__main__':