From: Andrey Miroshnikov Date: Thu, 1 Sep 2022 21:49:38 +0000 (+0000) Subject: Added gpio demo, parametrised pads X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d7d60feb7ac8cf84e9ef0bbbcc992dcb84ad922f;p=pinmux.git Added gpio demo, parametrised pads --- diff --git a/src/spec/stage2.py b/src/spec/stage2.py index c04a3b2..38f130e 100644 --- a/src/spec/stage2.py +++ b/src/spec/stage2.py @@ -30,20 +30,25 @@ uart_layout = (("rx", 1), ("oe", 1) ) -UART_BANK = 0 -I2C_BANK = 1 +GPIO_BANK = 0 +UART_BANK = 1 +I2C_BANK = 2 """ Really basic example, uart tx/rx and i2c sda/scl pinmux """ class ManPinmux(Elaboratable): - def __init__(self): + def __init__(self, pad_names): print("Test Manual Pinmux!") - self.n_banks = 2 + self.n_banks = 4 self.iomux1 = IOMuxBlockSingle(self.n_banks) self.iomux2 = IOMuxBlockSingle(self.n_banks) - self.pad1 = Record(name="Pad1", layout=io_layout) - self.pad2 = Record(name="Pad2", layout=io_layout) + self.pads = {} + for pad in pad_names: + self.pads[pad] = Record(name=pad, layout=io_layout) + self.gpio = {"0": Record(name="gp0", layout=io_layout), + "1": Record(name="gp1", layout=io_layout) + } self.uart = Record(name="uart", layout=uart_layout) self.i2c = {"sda": Record(name="sda", layout=io_layout), "scl": Record(name="scl", layout=io_layout) @@ -58,8 +63,8 @@ class ManPinmux(Elaboratable): m.submodules.iomux1 = iomux1 m.submodules.iomux2 = iomux2 - pad1 = self.pad1 - pad2 = self.pad2 + pads = self.pads + gpio = self.gpio uart = self.uart i2c = self.i2c bank = self.bank @@ -67,11 +72,21 @@ class ManPinmux(Elaboratable): comb += iomux1.bank.eq(bank) comb += iomux2.bank.eq(bank) - # uart connected to bank 0 - Pad 1 tx, Pad 2 rx + # --------------------------- + # This section is muxing only - doesn'care about pad names + # --------------------------- + # gpio - gpio0 on Pad1, gpio1 on Pad2 + comb += iomux1.bank_ports[GPIO_BANK].o.eq(gpio["0"].o) + comb += iomux1.bank_ports[GPIO_BANK].oe.eq(gpio["0"].oe) + comb += gpio["0"].i.eq(iomux1.bank_ports[GPIO_BANK].i) + comb += iomux2.bank_ports[GPIO_BANK].o.eq(gpio["1"].o) + comb += iomux2.bank_ports[GPIO_BANK].oe.eq(gpio["1"].oe) + comb += gpio["1"].i.eq(iomux2.bank_ports[GPIO_BANK].i) + # uart Pad 1 tx, Pad 2 rx comb += iomux1.bank_ports[UART_BANK].o.eq(uart.tx) comb += iomux1.bank_ports[UART_BANK].oe.eq(uart.oe) comb += uart.rx.eq(iomux2.bank_ports[UART_BANK].i) - # i2c connected to bank 1 - Pad 1 sda, Pad 2 scl + # i2c Pad 1 sda, Pad 2 scl comb += iomux1.bank_ports[I2C_BANK].o.eq(i2c["sda"].o) comb += iomux1.bank_ports[I2C_BANK].oe.eq(i2c["sda"].oe) comb += i2c["sda"].i.eq(iomux1.bank_ports[I2C_BANK].i) @@ -79,12 +94,16 @@ class ManPinmux(Elaboratable): comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe) comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i) - comb += pad1.o.eq(iomux1.out_port.o) - comb += pad1.oe.eq(iomux1.out_port.oe) - comb += iomux1.out_port.i.eq(pad1.i) - comb += pad2.o.eq(iomux2.out_port.o) - comb += pad2.oe.eq(iomux2.out_port.oe) - comb += iomux2.out_port.i.eq(pad2.i) + # --------------------------- + # Here is where the muxes are assigned to the actual pads + # --------------------------- + # TODO: for-loop to autoconnect muxes to pads (n_pads var?) + comb += pads['N1'].o.eq(iomux1.out_port.o) + comb += pads['N1'].oe.eq(iomux1.out_port.oe) + comb += iomux1.out_port.i.eq(pads['N1'].i) + comb += pads['N2'].o.eq(iomux2.out_port.o) + comb += pads['N2'].oe.eq(iomux2.out_port.oe) + comb += iomux2.out_port.i.eq(pads['N2'].i) #temp for testing - connect pad rx-tx #comb += pad2.i.eq(pad1.o) @@ -92,10 +111,9 @@ class ManPinmux(Elaboratable): return m def __iter__(self): - for field in self.pad1.fields.values(): - yield field - for field in self.pad2.fields.values(): - yield field + for pad in list(self.pads.keys()): + for field in self.pads[pad].fields.values(): + yield field for field in self.uart.fields.values(): yield field for field in self.i2c["sda"].fields.values(): @@ -111,6 +129,31 @@ def set_bank(dut, bank, delay=1e-6): yield dut.bank.eq(bank) yield Delay(delay) +def gpio(gpio, pad, data, delay=1e-6): + # Output test - Control GPIO output + yield gpio.oe.eq(1) + yield Delay(delay) + n_bits = len(bin(data)[2:]) + read = 0 + for i in range(0, n_bits): + bit = (data >> i) & 0x1 + yield gpio.o.eq(bit) + yield Delay(delay) + temp = yield pad.o + read |= (temp << i) + assert data == read, f"GPIO Sent: %x | Pad Read: %x" % (data, read) + # Input test - Control Pad input + yield gpio.oe.eq(0) + yield Delay(delay) + read2 = 0 + for i in range(0, n_bits): + bit = (read >> i) & 0x1 + yield pad.i.eq(bit) + yield Delay(delay) + temp = yield gpio.i + read2 |= (temp << i) + assert read2 == read, f"Pad Sent: %x | GPIO Read: %x" % (data, read) + def uart_send(tx, rx, byte, oe=None, delay=1e-6): if oe is not None: yield oe.eq(1) @@ -133,14 +176,14 @@ def uart_send(tx, rx, byte, oe=None, delay=1e-6): else: print("Received: %x does NOT match sent: %x" % (byte, result)) -def i2c_send(sda, scl, rx_sda, byte, delay=1e-6): +def i2c_send(sda, scl, sda_pad_i, byte, delay=1e-6): # No checking yet # No pull-up on line implemented, set high instead yield sda.oe.eq(1) yield sda.o.eq(1) yield scl.oe.eq(1) yield scl.o.eq(1) - yield rx_sda.eq(1) + yield sda_pad_i.eq(1) yield Delay(delay) yield sda.o.eq(0) # start bit yield Delay(delay) @@ -153,29 +196,36 @@ def i2c_send(sda, scl, rx_sda, byte, delay=1e-6): yield Delay(delay/2) yield sda.o.eq(1) # Master releases SDA line yield sda.oe.eq(0) - yield rx_sda.eq(0) # ACK + yield sda_pad_i.eq(0) # ACK yield Delay(delay) - yield rx_sda.eq(1) + yield sda_pad_i.eq(1) -def test_man_pinmux(dut): +def test_man_pinmux(dut, pad_names): delay = 1e-6 + # GPIO test + yield from gpio(dut.gpio['0'], dut.pads['N1'], 0x5a5) + yield from gpio(dut.gpio['1'], dut.pads['N2'], 0x5a5) # UART test yield from set_bank(dut, UART_BANK) - yield from uart_send(dut.uart.tx, dut.pad1.o, 0x42, oe=dut.uart.oe) - #yield dut.pad1.i.eq(1) - yield from uart_send(dut.pad2.i, dut.uart.rx, 0x5A) - yield dut.pad2.i.eq(0) + yield from uart_send(dut.uart.tx, dut.pads['N1'].o, 0x42, oe=dut.uart.oe) + yield from uart_send(dut.pads['N2'].i, dut.uart.rx, 0x5a) + yield dut.pads['N2'].i.eq(0) yield Delay(delay) # I2C test yield from set_bank(dut, I2C_BANK) - yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pad1.i, 0x67) + yield from i2c_send(dut.i2c['sda'], dut.i2c['scl'], dut.pads['N1'].i, 0x67) + yield dut.gpio['0'].oe.eq(1) + yield Delay(delay) + yield dut.gpio['0'].oe.eq(0) + yield Delay(delay) def sim_man_pinmux(): filename = "test_man_pinmux" - dut = ManPinmux() + pad_names = ["N1", "N2"] + dut = ManPinmux(pad_names) vl = rtlil.convert(dut, ports=dut.ports()) with open(filename+".il", "w") as f: f.write(vl) @@ -185,7 +235,7 @@ def sim_man_pinmux(): sim = Simulator(m) - sim.add_process(wrap(test_man_pinmux(dut))) + sim.add_process(wrap(test_man_pinmux(dut, pad_names))) sim_writer = sim.write_vcd(filename+".vcd") with sim_writer: sim.run()