from nmigen.sim import Simulator, Settle, Delay
from iomux import IOMuxBlockSingle
+from base import PinSpec
+from jtag import iotypes
io_layout = (("i", 1),
("oe", 1),
Really basic example, uart tx/rx and i2c sda/scl pinmux
"""
class ManPinmux(Elaboratable):
- def __init__(self, pad_names):
+ def __init__(self, requested):
print("Test Manual Pinmux!")
- self.requested = {"N1": {"mux%d" % GPIO_BANK: ["gpio", 0],
- "mux%d" % UART_BANK: ["uart", 0, "tx"],
- "mux%d" % I2C_BANK: ["i2c", 0, "sda"]},
- "N2": {"mux%d" % GPIO_BANK: ["gpio", 1],
- "mux%d" % UART_BANK: ["uart", 0, "rx"],
- "mux%d" % I2C_BANK: ["i2c", 0, "scl"]}
- }
+ self.requested = requested
self.n_banks = 4
self.bank = Signal(log2_int(self.n_banks))
self.pads = {}
self.muxes[pad] = IOMuxBlockSingle(self.n_banks)
for mux in self.requested[pad].keys():
periph = self.requested[pad][mux][0]
- unit_num = self.requested[pad][mux][1]
- if len(self.requested[pad][mux]) == 3:
- pin = self.requested[pad][mux][2]
- else:
- pin = "io"
- if periph == "gpio":
- self.pads[pad][mux] = Record(name="gp%d" % unit_num,
+ unit = self.requested[pad][mux][1]
+ sig = self.requested[pad][mux][2][:-1]
+ sig_type = iotypes[self.requested[pad][mux][2][-1]]
+ #print(sig, sig_type)
+ if sig_type == iotypes['*']:
+ self.pads[pad][mux] = Record(name="%s%d" % (sig, unit),
layout=io_layout)
- elif periph == "uart":
- if pin == "tx":
- self.pads[pad][mux] = Record(name="tx%d" % unit_num,
- layout=uart_tx_layout)
- elif pin == "rx":
- self.pads[pad][mux] = Signal(name="rx%d" % unit_num)
- elif periph == "i2c":
- if pin == "sda":
- self.pads[pad][mux] = Record(name="sda%d" % unit_num,
- layout=io_layout)
- elif pin == "scl":
- self.pads[pad][mux] = Record(name="scl%d" % unit_num,
- layout=io_layout)
+ elif sig_type == iotypes['+']:
+ self.pads[pad][mux] = Signal(name="%s%d_o" % (sig, unit))
+ elif sig_type == iotypes['-']:
+ self.pads[pad][mux] = Signal(name="%s%d_i" % (sig, unit))
+ print(self.pads)
def elaborate(self, platform):
m = Module()
for mux in self.requested[pad].keys():
periph = self.requested[pad][mux][0]
num = int(mux[3])
- if len(self.requested[pad][mux]) == 3:
- pin = self.requested[pad][mux][2]
- else:
- pin = "io"
- if periph == "gpio" or periph == "i2c":
+ sig = self.requested[pad][mux][2][:-1]
+ sig_type = iotypes[self.requested[pad][mux][2][-1]]
+ if sig_type == iotypes['*']:
comb += muxes[pad].bank_ports[num].o.eq(pads[pad][mux].o)
comb += muxes[pad].bank_ports[num].oe.eq(pads[pad][mux].oe)
comb += pads[pad][mux].i.eq(muxes[pad].bank_ports[num].i)
- elif periph == "uart":
- if pin == "tx":
- comb += muxes[pad].bank_ports[num].o.eq(
- pads[pad][mux].o)
- comb += muxes[pad].bank_ports[num].oe.eq(
- pads[pad][mux].oe)
- elif pin == "rx":
- comb += pads[pad][mux].eq(muxes[pad].bank_ports[num].i)
-
+ elif sig_type == iotypes['+']:
+ comb += muxes[pad].bank_ports[num].o.eq(pads[pad][mux])
+ elif sig_type == iotypes['-']:
+ comb += pads[pad][mux].eq(muxes[pad].bank_ports[num].i)
# ---------------------------
# Here is where the muxes are assigned to the actual pads
# ---------------------------
"""
def uart_send(tx, rx, pad_tx, pad_rx, byte, delay=1e-6):
# Drive uart tx - check the word seen at the Pad
- yield tx.oe.eq(1)
- yield tx.o.eq(1)
+ print(type(tx))
+ #yield tx.oe.eq(1)
+ yield tx.eq(1)
yield Delay(2*delay)
- yield tx.o.eq(0) # start bit
+ yield tx.eq(0) # start bit
yield Delay(delay)
read = 0
# send one byte, lsb first
for i in range(0, 8):
bit = (byte >> i) & 0x1
- yield tx.o.eq(bit)
+ yield tx.eq(bit)
yield Delay(delay)
test_bit = yield pad_tx.o
read |= (test_bit << i)
- yield tx.o.eq(1) # stop bit
+ yield tx.eq(1) # stop bit
yield Delay(delay)
assert byte == read, f"UART Sent: %x | Pad Read: %x" % (byte, read)
# Drive Pad i - check word at uart rx
yield sda.o.eq(1) # 'release' the SDA line
# Test the GPIO/UART/I2C connectivity
-def test_man_pinmux(dut, pad_names):
+def test_man_pinmux(dut, requested):
+ # TODO: Convert to automatic
+ # [{"pad":%s, "bank":%d}, {"pad":%s, "bank":%d},...]
+ #gpios = [{"padname":"N1", "bank":GPIO_BANK},
+ # {"padname":"N2", "bank":GPIO_BANK}]
+ # [[txPAD, MUXx, rxPAD, MUXx],...] - diff banks not supported yet
+ uarts = [{"txpadname":"N1", "rxpadname":"N2", "bank":UART_BANK}]
+ # [[sdaPAD, MUXx, sclPAD, MUXx],...] - diff banks not supported yet
+ i2cs = [{"sdapadname":"N1", "sclpadname":"N2", "bank":I2C_BANK}]
+
+ gpios = []
delay = 1e-6
+ for pad in requested.keys():
+ for mux in requested[pad].keys():
+ periph = requested[pad][mux][0]
+
+ if periph == "gpio":
+ # [{"padname":%s, "bank": %d}, ...]
+ gpios.append({"padname":pad, "bank": int(mux[3])})
+ if periph == "uart":
+ # TODO:
+ pass
+ if periph == "i2c":
+ # TODO:
+ pass
+ print(gpios)
# GPIO test
- yield from set_bank(dut, GPIO_BANK)
- yield from gpio(dut.pads["N1"]["mux%d" % GPIO_BANK],
- dut.pads["N1"]["pad"], 0x5a5)
- yield from gpio(dut.pads["N2"]["mux%d" % GPIO_BANK],
- dut.pads["N2"]["pad"], 0x5a5)
+ for gpio_periph in gpios:
+ padname = gpio_periph["padname"]
+ gpio_bank = gpio_periph["bank"]
+ gp = dut.pads[padname]["mux%d" % gpio_bank]
+ pad = dut.pads[padname]["pad"]
+ yield from set_bank(dut, gpio_bank)
+ yield from gpio(gp, pad, 0x5a5)
+
# UART test
- yield from set_bank(dut, UART_BANK)
- yield from uart_send(dut.pads["N1"]["mux%d" % UART_BANK],
- dut.pads["N2"]["mux%d" % UART_BANK],
- dut.pads['N1']["pad"], dut.pads['N2']["pad"], 0x42)
- #yield dut.pads['N2'].i.eq(0)
- #yield Delay(delay)
+ for uart_periph in uarts:
+ txpadname = uart_periph["txpadname"]
+ rxpadname = uart_periph["rxpadname"]
+ uart_bank = uart_periph["bank"]
+ tx = dut.pads[txpadname]["mux%d" % uart_bank]
+ rx = dut.pads[rxpadname]["mux%d" % uart_bank]
+ txpad = dut.pads[txpadname]["pad"]
+ rxpad = dut.pads[rxpadname]["pad"]
+ yield from set_bank(dut, UART_BANK)
+ yield from uart_send(tx, rx, txpad, rxpad, 0x42)
+
# I2C test
+ for i2c_periph in i2cs:
+ sdapadname = i2c_periph["sdapadname"]
+ sclpadname = i2c_periph["sclpadname"]
+ i2c_bank = i2c_periph["bank"]
+ sda = dut.pads[sdapadname]["mux%d" % i2c_bank]
+ scl = dut.pads[sclpadname]["mux%d" % i2c_bank]
+ sdapad = dut.pads[sdapadname]["pad"]
+
yield from set_bank(dut, I2C_BANK)
- yield from i2c_send(dut.pads["N1"]["mux%d" % I2C_BANK],
- dut.pads["N2"]["mux%d" % I2C_BANK],
- dut.pads['N1']["pad"], 0x67)
+ yield from i2c_send(sda, scl, sdapad, 0x67)
+
+def gen_gtkw_doc(module_name, requested, filename):
+ # GTKWave doc generation
+ style = {
+ '': {'base': 'hex'},
+ 'in': {'color': 'orange'},
+ 'out': {'color': 'yellow'},
+ 'debug': {'module': 'top', 'color': 'red'}
+ }
+ # Create a trace list, each block expected to be a tuple()
+ traces = []
+ temp = 0
+ n_banks = 0
+ for pad in requested.keys():
+ temp = len(requested[pad].keys())
+ if n_banks < temp:
+ n_banks = temp
+ temp_traces = ("Pad %s" % pad, [])
+ # Pad signals
+ temp_traces[1].append(('%s__i' % pad, 'in'))
+ temp_traces[1].append(('%s__o' % pad, 'out'))
+ temp_traces[1].append(('%s__oe' % pad, 'out'))
+ for mux in requested[pad].keys():
+ periph = requested[pad][mux][0]
+ unit_num = requested[pad][mux][1]
+ if len(requested[pad][mux]) == 3:
+ pin = requested[pad][mux][2]
+ else:
+ pin = "io"
+
+ if periph == "gpio":
+ temp_traces[1].append(('gp%d__i' % unit_num, 'in'))
+ temp_traces[1].append(('gp%d__o' % unit_num, 'out'))
+ temp_traces[1].append(('gp%d__oe' % unit_num, 'out'))
+ elif periph == "uart":
+ if pin == "tx":
+ temp_traces[1].append(('tx%d__o' % unit_num, 'out'))
+ temp_traces[1].append(('tx%d__oe' % unit_num, 'out'))
+ pass
+ elif pin == "rx":
+ temp_traces[1].append(('rx%d' % unit_num, 'in'))
+ pass
+ elif periph == "i2c":
+ temp_traces[1].append(('%s%d__i' % (pin, unit_num), 'in'))
+ temp_traces[1].append(('%s%d__o' % (pin, unit_num), 'out'))
+ temp_traces[1].append(('%s%d__oe' % (pin, unit_num), 'out'))
+ traces.append(temp_traces)
+
+ # master bank signal
+ temp_traces = ('Misc', [
+ ('bank[%d:0]' % ((n_banks-1).bit_length()-1), 'in')
+ ])
+ traces.append(temp_traces)
+
+ #print(traces)
+
+ write_gtkw(filename+".gtkw", filename+".vcd", traces, style,
+ module=module_name)
+
def sim_man_pinmux():
filename = "test_man_pinmux"
- pad_names = ["N1", "N2"]
- dut = ManPinmux(pad_names)
+ requested = {"N1": {"mux%d" % GPIO_BANK: ["gpio", 0, '0*'],
+ "mux%d" % UART_BANK: ["uart", 0, 'tx+'],
+ "mux%d" % I2C_BANK: ["i2c", 0, 'sda*']},
+ "N2": {"mux%d" % GPIO_BANK: ["gpio", 1, '*'],
+ "mux%d" % UART_BANK: ["uart", 0, 'rx-'],
+ "mux%d" % I2C_BANK: ["i2c", 0, 'scl*']},
+ "N3": {"mux%d" % GPIO_BANK: ["gpio", 2, '0*']},
+ "N4": {"mux%d" % GPIO_BANK: ["gpio", 3, '0*']}
+ }
+ dut = ManPinmux(requested)
vl = rtlil.convert(dut, ports=dut.ports())
with open(filename+".il", "w") as f:
f.write(vl)
sim = Simulator(m)
- sim.add_process(wrap(test_man_pinmux(dut, pad_names)))
+ sim.add_process(wrap(test_man_pinmux(dut, requested)))
sim_writer = sim.write_vcd(filename+".vcd")
with sim_writer:
sim.run()
- #gen_gtkw_doc("top.manpinmux", dut.n_banks, filename)
+ gen_gtkw_doc("top.manpinmux", dut.requested, filename)
if __name__ == '__main__':
- sim_man_pinmux()
+ sim_man_pinmux()
+ #pinbanks = []
+ #fixedpins = []
+ #function_names = []
+ #testspec = PinSpec()
+ pinbanks = {
+ 'A': (4, 4), # (num of pads, num of banks)?
+ #'B': (18, 4),
+ #'C': (24, 1),
+ #'D': (93, 1),
+ }
+ fixedpins = {
+ 'POWER_GPIO': [
+ 'VDD_GPIOB',
+ 'GND_GPIOB',
+ ]}
+ function_names = {'TWI0': 'I2C 0',
+ 'UART0': 'UART (TX/RX) 0',
+ }
+ ps = PinSpec(pinbanks, fixedpins, function_names)
+ ps.gpio("", ('A', 0), 0, 0, 4)
+ ps.uart("0", ('A', 0), 1)
+ ps.i2c("0", ('A', 0), 2)
+
+ print(dir(ps.gpio))
+ print(ps.gpio.pinouts, ps.gpio.bankspec, ps.gpio.pinfn, ps.gpio.fname)