8eb1f92037ce4b1f9cb848ad63c27f95f7cd9801
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",
65 self
.pads
["N1"]["mux%d" % UART_BANK
] = Record(name
="tx",
66 layout
=uart_tx_layout
)
67 self
.pads
["N1"]["mux%d" % I2C_BANK
] = Record(name
="sda",
69 self
.pads
["N2"]["pad"] = Record(name
=pad_names
[1], layout
=io_layout
)
70 self
.pads
["N2"]["mux%d" % GPIO_BANK
] = Record(name
="gp1",
72 self
.pads
["N2"]["mux%d" % UART_BANK
] = Signal(name
="rx") # One signal
73 self
.pads
["N2"]["mux%d" % I2C_BANK
] = Record(name
="scl",
76 def elaborate(self
, platform
):
78 comb
, sync
= m
.d
.comb
, m
.d
.sync
81 m
.submodules
.iomux1
= iomux1
82 m
.submodules
.iomux2
= iomux2
85 pad0
= self
.pads
["N1"]["pad"]
86 gp0
= self
.pads
["N1"]["mux%d" % GPIO_BANK
]
87 gp1
= self
.pads
["N2"]["mux%d" % GPIO_BANK
]
88 tx
= self
.pads
["N1"]["mux%d" % UART_BANK
]
89 rx
= self
.pads
["N2"]["mux%d" % UART_BANK
]
90 sda
= self
.pads
["N1"]["mux%d" % I2C_BANK
]
91 scl
= self
.pads
["N2"]["mux%d" % I2C_BANK
]
94 comb
+= iomux1
.bank
.eq(bank
)
95 comb
+= iomux2
.bank
.eq(bank
)
97 # ---------------------------
98 # This section is muxing only - doesn'care about pad names
99 # ---------------------------
100 # gpio - gpio0 on Pad1, gpio1 on Pad2
101 comb
+= iomux1
.bank_ports
[GPIO_BANK
].o
.eq(gp0
.o
)
102 comb
+= iomux1
.bank_ports
[GPIO_BANK
].oe
.eq(gp0
.oe
)
103 comb
+= gp0
.i
.eq(iomux1
.bank_ports
[GPIO_BANK
].i
)
104 comb
+= iomux2
.bank_ports
[GPIO_BANK
].o
.eq(gp1
.o
)
105 comb
+= iomux2
.bank_ports
[GPIO_BANK
].oe
.eq(gp1
.oe
)
106 comb
+= gp1
.i
.eq(iomux2
.bank_ports
[GPIO_BANK
].i
)
107 # uart Pad 1 tx, Pad 2 rx
108 comb
+= iomux1
.bank_ports
[UART_BANK
].o
.eq(tx
.o
)
109 comb
+= iomux1
.bank_ports
[UART_BANK
].oe
.eq(tx
.oe
)
110 comb
+= rx
.eq(iomux2
.bank_ports
[UART_BANK
].i
)
111 # i2c Pad 1 sda, Pad 2 scl
112 comb
+= iomux1
.bank_ports
[I2C_BANK
].o
.eq(sda
.o
)
113 comb
+= iomux1
.bank_ports
[I2C_BANK
].oe
.eq(sda
.oe
)
114 comb
+= sda
.i
.eq(iomux1
.bank_ports
[I2C_BANK
].i
)
115 comb
+= iomux2
.bank_ports
[I2C_BANK
].o
.eq(scl
.o
)
116 comb
+= iomux2
.bank_ports
[I2C_BANK
].oe
.eq(scl
.oe
)
117 comb
+= scl
.i
.eq(iomux2
.bank_ports
[I2C_BANK
].i
)
119 # ---------------------------
120 # Here is where the muxes are assigned to the actual pads
121 # ---------------------------
122 # TODO: for-loop to autoconnect muxes to pads (n_pads var?)
123 comb
+= pads
['N1']["pad"].o
.eq(iomux1
.out_port
.o
)
124 comb
+= pads
['N1']["pad"].oe
.eq(iomux1
.out_port
.oe
)
125 comb
+= iomux1
.out_port
.i
.eq(pads
['N1']["pad"].i
)
126 comb
+= pads
['N2']["pad"].o
.eq(iomux2
.out_port
.o
)
127 comb
+= pads
['N2']["pad"].oe
.eq(iomux2
.out_port
.oe
)
128 comb
+= iomux2
.out_port
.i
.eq(pads
['N2']["pad"].i
)
133 for pad
in list(self
.pads
.keys()):
134 for field
in self
.pads
[pad
]["pad"].fields
.values():
136 #for field in self.uart.fields.values():
138 #for field in self.i2c["sda"].fields.values():
140 #for field in self.i2c["scl"].fields.values():
147 def set_bank(dut
, bank
, delay
=1e-6):
148 yield dut
.bank
.eq(bank
)
153 Set the gpio output based on given data sequence, checked at pad.o
154 Then sends the same byte via pad.i to gpio input
156 def gpio(gpio
, pad
, data
, delay
=1e-6):
157 # Output test - Control GPIO output
160 n_bits
= len(bin(data
)[2:])
162 for i
in range(0, n_bits
):
163 bit
= (data
>> i
) & 0x1
168 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
169 # Input test - Control Pad input
173 for i
in range(0, n_bits
):
174 bit
= (read
>> i
) & 0x1
179 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
186 Sends a byte via uart tx, checked at output pad
187 Then sends the same byte via input pad to uart rx
188 Input and output pads are different, so must specify both
190 def uart_send(tx
, rx
, pad_tx
, pad_rx
, byte
, delay
=1e-6):
191 # Drive uart tx - check the word seen at the Pad
195 yield tx
.o
.eq(0) # start bit
198 # send one byte, lsb first
199 for i
in range(0, 8):
200 bit
= (byte
>> i
) & 0x1
203 test_bit
= yield pad_tx
.o
204 read |
= (test_bit
<< i
)
205 yield tx
.o
.eq(1) # stop bit
207 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
208 # Drive Pad i - check word at uart rx
211 yield pad_rx
.i
.eq(0) # start bit
214 for i
in range(0, 8):
215 bit
= (read
>> i
) & 0x1
216 yield pad_rx
.i
.eq(bit
)
219 read2 |
= (test_bit
<< i
)
220 yield pad_rx
.i
.eq(1) # stop bit
222 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
226 Sends a byte via SDA.o (peripheral side), checked at output pad
227 Then sends the same byte via input pad to master SDA.i
228 This transaction doesn't make the distinction between read/write bit.
230 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
232 # No pull-up on line implemented, set high instead
237 yield sda_pad
.i
.eq(1)
240 yield sda
.o
.eq(0) # start bit
242 for i
in range(0, 8):
243 bit
= (byte
>> i
) & 0x1
248 temp
= yield sda_pad
.o
251 yield sda
.o
.eq(1) # Master releases SDA line
253 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
255 yield sda_pad
.i
.eq(0)
260 # Send byte back to master
262 for i
in range(0, 8):
263 bit
= (read
>> i
) & 0x1
264 yield sda_pad
.i
.eq(bit
)
271 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
279 # Stop condition - SDA line high after SCL high
284 yield sda
.o
.eq(1) # 'release' the SDA line
286 # Test the GPIO/UART/I2C connectivity
287 def test_man_pinmux(dut
, pad_names
):
290 yield from set_bank(dut
, GPIO_BANK
)
291 yield from gpio(dut
.pads
["N1"]["mux%d" % GPIO_BANK
],
292 dut
.pads
["N1"]["pad"], 0x5a5)
293 yield from gpio(dut
.pads
["N2"]["mux%d" % GPIO_BANK
],
294 dut
.pads
["N2"]["pad"], 0x5a5)
296 yield from set_bank(dut
, UART_BANK
)
297 yield from uart_send(dut
.pads
["N1"]["mux%d" % UART_BANK
],
298 dut
.pads
["N2"]["mux%d" % UART_BANK
],
299 dut
.pads
['N1']["pad"], dut
.pads
['N2']["pad"], 0x42)
300 #yield dut.pads['N2'].i.eq(0)
303 yield from set_bank(dut
, I2C_BANK
)
304 yield from i2c_send(dut
.pads
["N1"]["mux%d" % I2C_BANK
],
305 dut
.pads
["N2"]["mux%d" % I2C_BANK
],
306 dut
.pads
['N1']["pad"], 0x67)
308 def sim_man_pinmux():
309 filename
= "test_man_pinmux"
310 pad_names
= ["N1", "N2"]
311 dut
= ManPinmux(pad_names
)
312 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
313 with
open(filename
+".il", "w") as f
:
317 m
.submodules
.manpinmux
= dut
321 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
322 sim_writer
= sim
.write_vcd(filename
+".vcd")
325 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
327 if __name__
== '__main__':