259c89d240993c92f2d136535113f352ce3b94ea
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 # Automatically create the necessary periph/pad Records/Signals
58 # depending on the given dict specification
59 for pad
in self
.requested
.keys():
61 self
.pads
[pad
]["pad"] = Record(name
=pad
, layout
=io_layout
)
62 self
.muxes
[pad
] = IOMuxBlockSingle(self
.n_banks
)
63 for mux
in self
.requested
[pad
].keys():
64 periph
= self
.requested
[pad
][mux
][0]
65 unit_num
= self
.requested
[pad
][mux
][1]
66 if len(self
.requested
[pad
][mux
]) == 3:
67 pin
= self
.requested
[pad
][mux
][2]
71 self
.pads
[pad
][mux
] = Record(name
="gp%d" % unit_num
,
73 elif periph
== "uart":
75 self
.pads
[pad
][mux
] = Record(name
="tx%d" % unit_num
,
76 layout
=uart_tx_layout
)
78 self
.pads
[pad
][mux
] = Signal(name
="rx%d" % unit_num
)
81 self
.pads
[pad
][mux
] = Record(name
="sda%d" % unit_num
,
84 self
.pads
[pad
][mux
] = Record(name
="scl%d" % unit_num
,
87 def elaborate(self
, platform
):
89 comb
, sync
= m
.d
.comb
, m
.d
.sync
93 for pad
in 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 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 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():
139 for mux
in self
.pads
[pad
].keys():
140 if type(self
.pads
[pad
][mux
]) == Signal
:
141 yield self
.pads
[pad
][mux
]
143 for field
in self
.pads
[pad
][mux
].fields
.values():
150 def set_bank(dut
, bank
, delay
=1e-6):
151 yield dut
.bank
.eq(bank
)
156 Set the gpio output based on given data sequence, checked at pad.o
157 Then sends the same byte via pad.i to gpio input
159 def gpio(gpio
, pad
, data
, delay
=1e-6):
160 # Output test - Control GPIO output
163 n_bits
= len(bin(data
)[2:])
165 for i
in range(0, n_bits
):
166 bit
= (data
>> i
) & 0x1
171 assert data
== read
, f
"GPIO Sent: %x | Pad Read: %x" % (data
, read
)
172 # Input test - Control Pad input
176 for i
in range(0, n_bits
):
177 bit
= (read
>> i
) & 0x1
182 assert read2
== read
, f
"Pad Sent: %x | GPIO Read: %x" % (data
, read
)
189 Sends a byte via uart tx, checked at output pad
190 Then sends the same byte via input pad to uart rx
191 Input and output pads are different, so must specify both
193 def uart_send(tx
, rx
, pad_tx
, pad_rx
, byte
, delay
=1e-6):
194 # Drive uart tx - check the word seen at the Pad
198 yield tx
.o
.eq(0) # start bit
201 # send one byte, lsb first
202 for i
in range(0, 8):
203 bit
= (byte
>> i
) & 0x1
206 test_bit
= yield pad_tx
.o
207 read |
= (test_bit
<< i
)
208 yield tx
.o
.eq(1) # stop bit
210 assert byte
== read
, f
"UART Sent: %x | Pad Read: %x" % (byte
, read
)
211 # Drive Pad i - check word at uart rx
214 yield pad_rx
.i
.eq(0) # start bit
217 for i
in range(0, 8):
218 bit
= (read
>> i
) & 0x1
219 yield pad_rx
.i
.eq(bit
)
222 read2 |
= (test_bit
<< i
)
223 yield pad_rx
.i
.eq(1) # stop bit
225 assert read
== read2
, f
"Pad Sent: %x | UART Read: %x" % (read
, read2
)
229 Sends a byte via SDA.o (peripheral side), checked at output pad
230 Then sends the same byte via input pad to master SDA.i
231 This transaction doesn't make the distinction between read/write bit.
233 def i2c_send(sda
, scl
, sda_pad
, byte
, delay
=1e-6):
235 # No pull-up on line implemented, set high instead
240 yield sda_pad
.i
.eq(1)
243 yield sda
.o
.eq(0) # start bit
245 for i
in range(0, 8):
246 bit
= (byte
>> i
) & 0x1
251 temp
= yield sda_pad
.o
254 yield sda
.o
.eq(1) # Master releases SDA line
256 assert byte
== read
, f
"I2C Sent: %x | Pad Read: %x" % (byte
, read
)
258 yield sda_pad
.i
.eq(0)
263 # Send byte back to master
265 for i
in range(0, 8):
266 bit
= (read
>> i
) & 0x1
267 yield sda_pad
.i
.eq(bit
)
274 assert read
== read2
, f
"Pad Sent: %x | I2C Read: %x" % (read
, read2
)
282 # Stop condition - SDA line high after SCL high
287 yield sda
.o
.eq(1) # 'release' the SDA line
289 # Test the GPIO/UART/I2C connectivity
290 def test_man_pinmux(dut
, pad_names
):
293 yield from set_bank(dut
, GPIO_BANK
)
294 yield from gpio(dut
.pads
["N1"]["mux%d" % GPIO_BANK
],
295 dut
.pads
["N1"]["pad"], 0x5a5)
296 yield from gpio(dut
.pads
["N2"]["mux%d" % GPIO_BANK
],
297 dut
.pads
["N2"]["pad"], 0x5a5)
299 yield from set_bank(dut
, UART_BANK
)
300 yield from uart_send(dut
.pads
["N1"]["mux%d" % UART_BANK
],
301 dut
.pads
["N2"]["mux%d" % UART_BANK
],
302 dut
.pads
['N1']["pad"], dut
.pads
['N2']["pad"], 0x42)
303 #yield dut.pads['N2'].i.eq(0)
306 yield from set_bank(dut
, I2C_BANK
)
307 yield from i2c_send(dut
.pads
["N1"]["mux%d" % I2C_BANK
],
308 dut
.pads
["N2"]["mux%d" % I2C_BANK
],
309 dut
.pads
['N1']["pad"], 0x67)
311 def sim_man_pinmux():
312 filename
= "test_man_pinmux"
313 pad_names
= ["N1", "N2"]
314 dut
= ManPinmux(pad_names
)
315 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
316 with
open(filename
+".il", "w") as f
:
320 m
.submodules
.manpinmux
= dut
324 sim
.add_process(wrap(test_man_pinmux(dut
, pad_names
)))
325 sim_writer
= sim
.write_vcd(filename
+".vcd")
328 #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
330 if __name__
== '__main__':