X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fspec%2Fstage2.py;h=8eb1f92037ce4b1f9cb848ad63c27f95f7cd9801;hb=ec0be6c8d3e83ddbd210c1c87babeae882c49cd0;hp=378d590331e270c9b2b9ed3c68660cda46c16bc6;hpb=70f7512232b7582f2f0e210aaf83114ea3e57c30;p=pinmux.git diff --git a/src/spec/stage2.py b/src/spec/stage2.py index 378d590..8eb1f92 100644 --- a/src/spec/stage2.py +++ b/src/spec/stage2.py @@ -29,7 +29,9 @@ uart_layout = (("rx", 1), ("tx", 1), ("oe", 1) ) - +uart_tx_layout = (("o", 1), + ("oe", 1) + ) GPIO_BANK = 0 UART_BANK = 1 I2C_BANK = 2 @@ -43,6 +45,7 @@ class ManPinmux(Elaboratable): self.n_banks = 4 self.iomux1 = IOMuxBlockSingle(self.n_banks) self.iomux2 = IOMuxBlockSingle(self.n_banks) + """ self.pads = {} for pad in pad_names: self.pads[pad] = Record(name=pad, layout=io_layout) @@ -53,7 +56,22 @@ class ManPinmux(Elaboratable): self.i2c = {"sda": Record(name="sda", layout=io_layout), "scl": Record(name="scl", layout=io_layout) } + """ self.bank = Signal(log2_int(self.n_banks)) + self.pads = {pad_names[0]:{}, pad_names[1]:{}} + self.pads["N1"]["pad"] = Record(name=pad_names[0], layout=io_layout) + self.pads["N1"]["mux%d" % GPIO_BANK] = Record(name="gp0", + layout=io_layout) + self.pads["N1"]["mux%d" % UART_BANK] = Record(name="tx", + layout=uart_tx_layout) + self.pads["N1"]["mux%d" % I2C_BANK] = Record(name="sda", + layout=io_layout) + self.pads["N2"]["pad"] = Record(name=pad_names[1], layout=io_layout) + self.pads["N2"]["mux%d" % GPIO_BANK] = Record(name="gp1", + layout=io_layout) + self.pads["N2"]["mux%d" % UART_BANK] = Signal(name="rx") # One signal + self.pads["N2"]["mux%d" % I2C_BANK] = Record(name="scl", + layout=io_layout) def elaborate(self, platform): m = Module() @@ -64,9 +82,13 @@ class ManPinmux(Elaboratable): m.submodules.iomux2 = iomux2 pads = self.pads - gpio = self.gpio - uart = self.uart - i2c = self.i2c + pad0 = self.pads["N1"]["pad"] + gp0 = self.pads["N1"]["mux%d" % GPIO_BANK] + gp1 = self.pads["N2"]["mux%d" % GPIO_BANK] + tx = self.pads["N1"]["mux%d" % UART_BANK] + rx = self.pads["N2"]["mux%d" % UART_BANK] + sda = self.pads["N1"]["mux%d" % I2C_BANK] + scl = self.pads["N2"]["mux%d" % I2C_BANK] bank = self.bank comb += iomux1.bank.eq(bank) @@ -76,50 +98,47 @@ class ManPinmux(Elaboratable): # 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) + comb += iomux1.bank_ports[GPIO_BANK].o.eq(gp0.o) + comb += iomux1.bank_ports[GPIO_BANK].oe.eq(gp0.oe) + comb += gp0.i.eq(iomux1.bank_ports[GPIO_BANK].i) + comb += iomux2.bank_ports[GPIO_BANK].o.eq(gp1.o) + comb += iomux2.bank_ports[GPIO_BANK].oe.eq(gp1.oe) + comb += gp1.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) + comb += iomux1.bank_ports[UART_BANK].o.eq(tx.o) + comb += iomux1.bank_ports[UART_BANK].oe.eq(tx.oe) + comb += rx.eq(iomux2.bank_ports[UART_BANK].i) # 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) - comb += iomux2.bank_ports[I2C_BANK].o.eq(i2c["scl"].o) - comb += iomux2.bank_ports[I2C_BANK].oe.eq(i2c["scl"].oe) - comb += i2c["scl"].i.eq(iomux2.bank_ports[I2C_BANK].i) + comb += iomux1.bank_ports[I2C_BANK].o.eq(sda.o) + comb += iomux1.bank_ports[I2C_BANK].oe.eq(sda.oe) + comb += sda.i.eq(iomux1.bank_ports[I2C_BANK].i) + comb += iomux2.bank_ports[I2C_BANK].o.eq(scl.o) + comb += iomux2.bank_ports[I2C_BANK].oe.eq(scl.oe) + comb += scl.i.eq(iomux2.bank_ports[I2C_BANK].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) + comb += pads['N1']["pad"].o.eq(iomux1.out_port.o) + comb += pads['N1']["pad"].oe.eq(iomux1.out_port.oe) + comb += iomux1.out_port.i.eq(pads['N1']["pad"].i) + comb += pads['N2']["pad"].o.eq(iomux2.out_port.o) + comb += pads['N2']["pad"].oe.eq(iomux2.out_port.oe) + comb += iomux2.out_port.i.eq(pads['N2']["pad"].i) return m def __iter__(self): for pad in list(self.pads.keys()): - for field in self.pads[pad].fields.values(): + for field in self.pads[pad]["pad"].fields.values(): yield field - for field in self.uart.fields.values(): - yield field - for field in self.i2c["sda"].fields.values(): - yield field - for field in self.i2c["scl"].fields.values(): - yield field + #for field in self.uart.fields.values(): + # yield field + #for field in self.i2c["sda"].fields.values(): + # yield field + #for field in self.i2c["scl"].fields.values(): + # yield field yield self.bank def ports(self): @@ -168,50 +187,56 @@ Sends a byte via uart tx, checked at output pad Then sends the same byte via input pad to uart rx Input and output pads are different, so must specify both """ -def uart_send(uart, pad_o, pad_i, byte, delay=1e-6): +def uart_send(tx, rx, pad_tx, pad_rx, byte, delay=1e-6): # Drive uart tx - check the word seen at the Pad - yield uart.oe.eq(1) - yield uart.tx.eq(1) + yield tx.oe.eq(1) + yield tx.o.eq(1) yield Delay(2*delay) - yield uart.tx.eq(0) # start bit + yield tx.o.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 uart.tx.eq(bit) + yield tx.o.eq(bit) yield Delay(delay) - test_bit = yield pad_o + test_bit = yield pad_tx.o read |= (test_bit << i) - yield uart.tx.eq(1) # stop bit + yield tx.o.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 pad_i.eq(1) + yield pad_rx.i.eq(1) yield Delay(2*delay) - yield pad_i.eq(0) # start bit + yield pad_rx.i.eq(0) # start bit yield Delay(delay) read2 = 0 for i in range(0, 8): bit = (read >> i) & 0x1 - yield pad_i.eq(bit) + yield pad_rx.i.eq(bit) yield Delay(delay) - test_bit = yield uart.rx + test_bit = yield rx read2 |= (test_bit << i) - yield pad_i.eq(1) # stop bit + yield pad_rx.i.eq(1) # stop bit yield Delay(delay) assert read == read2, f"Pad Sent: %x | UART Read: %x" % (read, read2) - -def i2c_send(sda, scl, sda_pad_i, byte, delay=1e-6): +""" +I2C test function +Sends a byte via SDA.o (peripheral side), checked at output pad +Then sends the same byte via input pad to master SDA.i +This transaction doesn't make the distinction between read/write bit. +""" +def i2c_send(sda, scl, sda_pad, 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 sda_pad_i.eq(1) + yield sda_pad.i.eq(1) yield Delay(delay) + read = 0 yield sda.o.eq(0) # start bit yield Delay(delay) for i in range(0, 8): @@ -220,33 +245,65 @@ def i2c_send(sda, scl, sda_pad_i, byte, delay=1e-6): yield scl.o.eq(0) yield Delay(delay/2) yield scl.o.eq(1) + temp = yield sda_pad.o + read |= (temp << i) yield Delay(delay/2) yield sda.o.eq(1) # Master releases SDA line yield sda.oe.eq(0) - yield sda_pad_i.eq(0) # ACK - yield Delay(delay) - yield sda_pad_i.eq(1) - - + assert byte == read, f"I2C Sent: %x | Pad Read: %x" % (byte, read) + # Slave ACK + yield sda_pad.i.eq(0) + yield scl.o.eq(0) + yield Delay(delay/2) + yield scl.o.eq(1) + yield Delay(delay/2) + # Send byte back to master + read2 = 0 + for i in range(0, 8): + bit = (read >> i) & 0x1 + yield sda_pad.i.eq(bit) + yield scl.o.eq(0) + yield Delay(delay/2) + yield scl.o.eq(1) + temp = yield sda.i + read2 |= (temp << i) + yield Delay(delay/2) + assert read == read2, f"Pad Sent: %x | I2C Read: %x" % (read, read2) + # Master ACK + yield sda.oe.eq(1) + yield sda.o.eq(0) + yield scl.o.eq(0) + yield Delay(delay/2) + yield scl.o.eq(1) + yield Delay(delay/2) + # Stop condition - SDA line high after SCL high + yield scl.o.eq(0) + yield Delay(delay/2) + yield scl.o.eq(1) + yield Delay(delay/2) + yield sda.o.eq(1) # 'release' the SDA line +# Test the GPIO/UART/I2C connectivity 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) + 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) # UART test yield from set_bank(dut, UART_BANK) - yield from uart_send(dut.uart, dut.pads['N1'].o, dut.pads['N2'].i, 0x42) - yield dut.pads['N2'].i.eq(0) - yield Delay(delay) + 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) # I2C test yield from set_bank(dut, I2C_BANK) - 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) + yield from i2c_send(dut.pads["N1"]["mux%d" % I2C_BANK], + dut.pads["N2"]["mux%d" % I2C_BANK], + dut.pads['N1']["pad"], 0x67) def sim_man_pinmux(): filename = "test_man_pinmux"