diff --git a/nmigen_boards/qmtech_10cl006.py b/nmigen_boards/qmtech_10cl006.py new file mode 100644 index 00000000..1f8bf47b --- /dev/null +++ b/nmigen_boards/qmtech_10cl006.py @@ -0,0 +1,131 @@ +import os +import subprocess + +from nmigen.build import * +from nmigen.vendor.intel import * +from nmigen_boards.resources import * +from nmigen_boards.qmtech_daughterboard import QMTechDaughterboard + + +__all__ = ["QMTech10CL006Platform"] + + +class QMTech10CL006Platform(IntelPlatform): + device = "10CL006" + package = "YU256" + speed = "C8G" + default_clk = "clk50" + + def __init__(self, standalone=True): + if not standalone: + # D3 - we do not use LEDResources/ButtonResources here, because there are five LEDs + # on the daughterboard and this will then clash with those + self.resources[1] = Resource("core_led", 0, PinsN("L9"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[2] = Resource("core_button", 0, PinsN("F3"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[3] = Resource("core_button", 1, PinsN("J6"), Attrs(io_standard="3.3-V LVTTL")) + daughterboard = QMTechDaughterboard(Attrs(io_standard="3.3-V LVTTL")) + self.connectors += daughterboard.connectors + self.resources += daughterboard.resources + + super().__init__() + + resources = [ + Resource("clk50", 0, Pins("E1", dir="i"), + Clock(50e6), Attrs(io_standard="3.3-V LVTTL")), + + *LEDResources( + pins="L9", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *ButtonResources( + pins="F3 J6", invert=True, + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *SPIFlashResources(0, + cs_n="D2", clk="H1", copi="C1", cipo="H2", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + SDRAMResource(0, + clk="P2", cke="R1", cs_n="P8", we_n="P6", ras_n="M8", cas_n="M7", + ba="N8 L8", a="R7 T7 R8 T8 R6 T5 R5 T4 R4 T3 T6 R3 T2", + dq="K5 L3 L4 K6 N3 M6 P3 N5 N2 N1 L1 L2 K1 K2 J1 J2", dqm="N6 P1", + attrs=Attrs(io_standard="3.3-V LVTTL")), + ] + + # The connectors are named after the daughterboard, not the core board + # because on the different core boards the names vary, but on the + # daughterboard they stay the same, which we need to connect the + # daughterboard peripherals to the core board. + # On this board J2 is U7 and J3 is U8 + connectors = [ + Connector("J", 2, { + # odd row even row + "7": "G1", "8": "G2", + "9": "D1", "10": "C2", + "11": "B1", "12": "F5", + "13": "D3", "14": "C3", + "15": "B3", "16": "A3", + "17": "B4", "18": "A4", + "19": "E5", "20": "A2", + "21": "D4", "22": "E6", + "23": "C6", "24": "D6", + "25": "B5", "26": "A5", + "27": "B6", "28": "A6", + "29": "B7", "30": "A7", + "31": "D8", "32": "C8", + "33": "D9", "34": "C9", + "35": "B8", "36": "A8", + "37": "B9", "38": "A9", + "39": "E9", "40": "E8", + "41": "E11", "42": "E10", + "43": "A10", "44": "B10", + "45": "D12", "46": "D11", + "47": "B11", "48": "A11", + "49": "B12", "50": "A12", + "51": "B13", "52": "A13", + "53": "B14", "54": "A14", + "55": "D14", "56": "C14", + "57": "B16", "58": "A15", + "59": "C16", "60": "C15", + }), + Connector("J", 3, { + # odd row even row + "7": "R9", "8": "T9", + "9": "R10", "10": "T10", + "11": "R11", "12": "T11", + "13": "R12", "14": "T12", + "15": "N9", "16": "M9", + "17": "M10", "18": "P9", + "19": "P11", "20": "N11", + "21": "R13", "22": "T13", + "23": "T15", "24": "T14", + "25": "N12", "26": "M11", + "27": "R14", "28": "N13", + "29": "N14", "30": "P14", + "31": "P16", "32": "R16", + "33": "N16", "34": "N15", + "35": "M16", "36": "M15", + "37": "L16", "38": "L15", + "39": "P15", "40": "M12", + "41": "L14", "42": "L13", + "43": "K16", "44": "K15", + "45": "K12", "46": "J12", + "47": "J14", "48": "J13", + "49": "K11", "50": "J11", + "51": "G11", "52": "F11", + "53": "F13", "54": "F14", + "55": "F10", "56": "F9", + "57": "E16", "58": "E15", + "59": "D16", "60": "D15", + }) + ] + + def toolchain_program(self, products, name): + quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm") + with products.extract("{}.sof".format(name)) as bitstream_filename: + subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG", + "--operation", "P;" + bitstream_filename]) + +if __name__ == "__main__": + from nmigen_boards.test.blinky import Blinky + QMTech10CL006Platform(standalone=True).build(Blinky(), do_program=True) \ No newline at end of file diff --git a/nmigen_boards/qmtech_5cefa2.py b/nmigen_boards/qmtech_5cefa2.py new file mode 100644 index 00000000..644ab383 --- /dev/null +++ b/nmigen_boards/qmtech_5cefa2.py @@ -0,0 +1,131 @@ +import os +import subprocess + +from nmigen.build import * +from nmigen.vendor.intel import * +from nmigen_boards.resources import * +from nmigen_boards.qmtech_daughterboard import QMTechDaughterboard + + +__all__ = ["QMTech5CEFA2Platform"] + + +class QMTech5CEFA2Platform(IntelPlatform): + device = "5CEFA2" + package = "F23" + speed = "C8" + default_clk = "clk50" + + def __init__(self, standalone=True): + if not standalone: + # D3 - we do not use LEDResources/ButtonResources here, because there are five LEDs + # on the daughterboard and this will then clash with those + self.resources[1] = Resource("core_led", 0, PinsN("D17"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[2] = Resource("core_button", 0, PinsN("AB13"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[3] = Resource("core_button", 1, PinsN("V18"), Attrs(io_standard="3.3-V LVTTL")) + daughterboard = QMTechDaughterboard(Attrs(io_standard="3.3-V LVTTL")) + self.connectors += daughterboard.connectors + self.resources += daughterboard.resources + + super().__init__() + + resources = [ + Resource("clk50", 0, Pins("M9", dir="i"), + Clock(50e6), Attrs(io_standard="3.3-V LVTTL")), + + *LEDResources( + pins="D17", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *ButtonResources( + pins="AB13 V18", invert=True, + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *SPIFlashResources(0, + cs_n="R4", clk="V3", copi="AB4", cipo="AB3", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + SDRAMResource(0, + clk="AB11", cke="V9", cs_n="AB5", we_n="W9", ras_n="AB6", cas_n="AA7", + ba="T7 P9", a="P8 P7 N8 N6 U6 U7 V6 U8 T8 W8 R6 T9 Y9", + dq="AA12 Y11 AA10 AB10 Y10 AA9 AB8 AA8 U10 T10 U11 R12 U12 P12 R10 R11", dqm="AB7 V10", + attrs=Attrs(io_standard="3.3-V LVTTL")), + ] + + # The connectors are named after the daughterboard, not the core board + # because on the different core boards the names vary, but on the + # daughterboard they stay the same, which we need to connect the + # daughterboard peripherals to the core board. + # On this board J2 is U7 and J3 is U8 + connectors = [ + Connector("J", 2, { + # odd row even row + "7": "AA2", "8": "AA1", + "9": "Y3", "10": "W2", + "11": "U1", "12": "U2", + "13": "N1", "14": "N2", + "15": "L1", "16": "L2", + "17": "G1", "18": "G2", + "19": "E2", "20": "D3", + "21": "C1", "22": "C2", + "23": "G6", "24": "H6", + "25": "G8", "26": "H8", + "27": "F7", "28": "E7", + "29": "D6", "30": "C6", + "31": "E9", "32": "D9", + "33": "B5", "34": "A5", + "35": "B6", "36": "B7", + "37": "A7", "38": "A8", + "39": "A9", "40": "A10", + "41": "B10", "42": "C9", + "43": "G10", "44": "F10", + "45": "C11", "46": "B11", + "47": "B12", "48": "A12", + "49": "E12", "50": "D12", + "51": "D13", "52": "C13", + "53": "B13", "54": "A13", + "55": "A15", "56": "A14", + "57": "B15", "58": "C15", + "59": "C16", "60": "B16", + }), + Connector("J", 3, { + # odd row even row + "7": "AA14", "8": "AA13", + "9": "AA15", "10": "AB15", + "11": "Y15", "12": "Y14", + "13": "AB18", "14": "AB17", + "15": "Y17", "16": "Y16", + "17": "AA18", "18": "AA17", + "19": "AA20", "20": "AA19", + "21": "Y20", "22": "Y19", + "23": "AB21", "24": "AB20", + "25": "AA22", "26": "AB22", + "27": "W22", "28": "Y22", + "29": "Y21", "30": "W21", + "31": "U22", "32": "V21", + "33": "V20", "34": "W19", + "35": "U21", "36": "U20", + "37": "R22", "38": "T22", + "39": "P22", "40": "R21", + "41": "T20", "42": "T19", + "43": "P16", "44": "P17", + "45": "N20", "46": "N21", + "47": "M21", "48": "M20", + "49": "M18", "50": "N19", + "51": "L18", "52": "L19", + "53": "M22", "54": "L22", + "55": "L17", "56": "K17", + "57": "K22", "58": "K21", + "59": "M16", "60": "N16", + }) + ] + + def toolchain_program(self, products, name): + quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm") + with products.extract("{}.sof".format(name)) as bitstream_filename: + subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG", + "--operation", "P;" + bitstream_filename]) + +if __name__ == "__main__": + from nmigen_boards.test.blinky import Blinky + QMTech5CEFA2Platform(standalone=True).build(Blinky(), do_program=True) \ No newline at end of file diff --git a/nmigen_boards/qmtech_daughterboard.py b/nmigen_boards/qmtech_daughterboard.py new file mode 100644 index 00000000..51718075 --- /dev/null +++ b/nmigen_boards/qmtech_daughterboard.py @@ -0,0 +1,88 @@ +from nmigen.build import * +from nmigen_boards.resources import * + +__all__ = ["QMTechDaughterboard"] + +class QMTechDaughterboard: + def __init__(self, attrs) -> None: + self.resources = [ + UARTResource(0, + tx="J_2:15", rx="J_2:16", + attrs=attrs + ), + + *LEDResources( + pins="J_2:40 J_2:39 J_2:38 J_2:37 J_2:36", invert=True, + attrs=attrs), + + *ButtonResources( + pins="J_3:7 J_2:44 J_2:43 J_2:42 J_2:41", invert=True, + attrs=attrs), + + Resource("eth_gmii", 0, + Subsignal("rst", PinsN("-", dir="o")), + Subsignal("int", PinsN("J_3:26", dir="o")), + Subsignal("mdio", Pins("J_3:15", dir="io")), + Subsignal("mdc", Pins("J_3:16", dir="o")), # Max 8.3MHz + Subsignal("gtx_clk", Pins("J_3:29", dir="o")), + Subsignal("tx_clk", Pins("J_3:22", dir="i")), + Subsignal("tx_en", Pins("J_3:28", dir="o")), + Subsignal("tx_er", Pins("J_3:17", dir="o")), + Subsignal("tx_data", Pins("J_3:27 J_3:25 J_3:24 J_3:23 J_3:21 J_3:20 J_3:19 J_3:18", dir="o")), + Subsignal("rx_clk", Pins("J_3:37", dir="i")), + Subsignal("rx_dv", Pins("J_3:42", dir="i"), Attrs(PULLDOWN="TRUE")), + Subsignal("rx_er", Pins("J_3:32", dir="i")), + Subsignal("rx_data", Pins("J_3:41 J_3:40 J_3:39 J_3:38 J_3:36 J_3:35 J_3:34 J_3:33", dir="i")), + Subsignal("col", Pins("J_3:31", dir="i")), + Subsignal("crs", Pins("J_3:30", dir="i")), + attrs + ), + + # 3 digit 7 segment display + Display7SegResource(0, + a="J_2:31", b="J_2:26", c="J_2:28", d="J_2:32", e="J_2:34", f="J_2:29", g="J_2:25", dp="J_2:30", + invert=True, attrs=attrs), + Resource("display_7seg_ctrl", 0, + Subsignal("en", Pins("J_2:33 J_2:27 J_2:35", dir="o", invert=False)), + attrs + ), + + Resource("vga", 0, + Subsignal("r", Pins("J_3:57 J_3:56 J_3:59 J_3:58 J_3:60", dir="o")), + Subsignal("g", Pins("J_3:51 J_3:50 J_3:53 J_3:52 J_3:54 J_3:55", dir="o")), + Subsignal("b", Pins("J_3:46 J_3:45 J_3:48 J_3:47 J_3:49", dir="o")), + Subsignal("hs", Pins("J_3:44", dir="o")), + Subsignal("vs", Pins("J_3:43", dir="o")), + attrs + ), + + *SDCardResources(0, clk="J_3:11", cmd="J_3:12", dat0="J_3:10", dat1="J_3:9", + dat2="J_3:14", dat3="J_3:13", cd="J_3:8", + attrs=attrs), + ] + + connectors = [ + Connector("pmod", 0, "J_2:17 J_2:19 J_2:21 J_2:23 - - J_2:18 J_2:20 J_2:22 J_2:24 - -"), #J10 + Connector("pmod", 1, "J_2:7 J_2:9 J_2:11 J_2:13 - - J_2:8 J_2:10 J_2:12 J_2:14 - -"), #J11 + Connector("J", 1, { + "3": "J_2:60", + "4": "J_2:59", + "5": "J_2:58", + "6": "J_2:57", + "7": "J_2:56", + "8": "J_2:55", + "9": "J_2:54", + "10": "J_2:53", + "11": "J_2:52", + "12": "J_2:51", + "13": "J_2:50", + "14": "J_2:49", + "15": "J_2:48", + "16": "J_2:47", + "17": "J_2:46", + "18": "J_2:45" + }), #J1 + ] + +if __name__ == "__main__": + print("The class in this file serves as an extension to other platforms only and cannot be built on its own.") \ No newline at end of file diff --git a/nmigen_boards/qmtech_ep4ce.py b/nmigen_boards/qmtech_ep4ce.py new file mode 100644 index 00000000..67853d33 --- /dev/null +++ b/nmigen_boards/qmtech_ep4ce.py @@ -0,0 +1,135 @@ +import os +import subprocess + +from nmigen.build import * +from nmigen.vendor.intel import * +from nmigen_boards.resources import * +from nmigen_boards.qmtech_daughterboard import QMTechDaughterboard + + +__all__ = ["QMTechEP4CEPlatform"] + + +class QMTechEP4CEPlatform(IntelPlatform): + device = "EP4CE" + package = "F23" + speed = "C8" + default_clk = "clk50" + + # at the time of writing EP4CE15 and EP4CE55 are available from QMTech + # so no_kluts = 15 or 55 for these platforms + def __init__(self, no_kluts=15, standalone=True): + self.device += str(no_kluts) + + if not standalone: + # D3 - we do not use LEDResources/ButtonResources here, because there are five LEDs + # on the daughterboard and this will then clash with those + self.resources[1] = Resource("core_led", 0, PinsN("E4"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[2] = Resource("core_button", 0, PinsN("Y13"), Attrs(io_standard="3.3-V LVTTL")) + self.resources[3] = Resource("core_button", 1, PinsN("W13"), Attrs(io_standard="3.3-V LVTTL")) + daughterboard = QMTechDaughterboard(Attrs(io_standard="3.3-V LVTTL")) + self.connectors += daughterboard.connectors + self.resources += daughterboard.resources + + super().__init__() + + resources = [ + Resource("clk50", 0, Pins("T2", dir="i"), + Clock(50e6), Attrs(io_standard="3.3-V LVTTL")), + + *LEDResources( + pins="E4", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *ButtonResources( + pins="Y13 W13", invert=True, + attrs=Attrs(io_standard="3.3-V LVTTL")), + + *SPIFlashResources(0, + cs_n="E2", clk="K2", copi="D1", cipo="K1", + attrs=Attrs(io_standard="3.3-V LVTTL")), + + SDRAMResource(0, + clk="Y6", cke="W6", cs_n="AA3", we_n="AB4", ras_n="AB3", cas_n="AA4", + ba="Y1 W2", a="V2 V1 U2 U1 V3 V4 Y2 AA1 Y3 V5 W1 Y4 V6", + dq="AA10 AB9 AA9 AB8 AA8 AB7 AA7 AB5 Y7 W8 Y8 V9 V10 Y10 W10 V11", dqm="AA5 W7", + attrs=Attrs(io_standard="3.3-V LVTTL")), + ] + + # The connectors are named after the daughterboard, not the core board + # because on the different core boards the names vary, but on the + # daughterboard they stay the same, which we need to connect the + # daughterboard peripherals to the core board. + # On this board J2 is U7 and J3 is U8 + connectors = [ + Connector("J", 2, { + # odd row even row + "7": "R1", "8": "R2", + "9": "P1", "10": "P2", + "11": "N1", "12": "N2", + "13": "M1", "14": "M2", + "15": "J1", "16": "J2", + "17": "H1", "18": "H2", + "19": "F1", "20": "F2", + "21": "E1", "22": "D2", + "23": "C1", "24": "C2", + "25": "B1", "26": "B2", + "27": "B3", "28": "A3", + "29": "B4", "30": "A4", + "31": "C4", "32": "C3", + "33": "B5", "34": "A5", + "35": "B6", "36": "A6", + "37": "B7", "38": "A7", + "39": "B8", "40": "A8", + "41": "B9", "42": "A9", + "43": "B10", "44": "A10", + "45": "B13", "46": "A13", + "47": "B14", "48": "A14", + "49": "B15", "50": "A15", + "51": "B16", "52": "A16", + "53": "B17", "54": "A17", + "55": "B18", "56": "A18", + "57": "B19", "58": "A19", + "59": "B20", "60": "A20", + }), + Connector("J", 3, { + # odd row even row + "7": "AA13", "8": "AB13", + "9": "AA14", "10": "AB14", + "11": "AA15", "12": "AB15", + "13": "AA16", "14": "AB16", + "15": "AA17", "16": "AB17", + "17": "AA18", "18": "AB18", + "19": "AA19", "20": "AB19", + "21": "AA20", "22": "AB20", + "23": "Y22", "24": "Y21", + "25": "W22", "26": "W21", + "27": "V22", "28": "V21", + "29": "U22", "30": "U21", + "31": "R22", "32": "R21", + "33": "P22", "34": "P21", + "35": "N22", "36": "N21", + "37": "M22", "38": "M21", + "39": "L22", "40": "L21", + "41": "K22", "42": "K21", + "43": "J22", "44": "J21", + "45": "H22", "46": "H21", + "47": "F22", "48": "F21", + "49": "E22", "50": "E21", + "51": "D22", "52": "D21", + "53": "C22", "54": "C21", + "55": "B22", "56": "B21", + "57": "N20", "58": "N19", + "59": "M20", "60": "M19", + }) + ] + + def toolchain_program(self, products, name): + quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm") + with products.extract("{}.sof".format(name)) as bitstream_filename: + subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG", + "--operation", "P;" + bitstream_filename]) + +if __name__ == "__main__": + from nmigen_boards.test.blinky import Blinky + QMTechEP4CEPlatform(standalone=True).build(Blinky(), do_program=True) \ No newline at end of file diff --git a/nmigen_boards/qmtech_xc7a35t.py b/nmigen_boards/qmtech_xc7a35t.py new file mode 100644 index 00000000..e5d496e4 --- /dev/null +++ b/nmigen_boards/qmtech_xc7a35t.py @@ -0,0 +1,162 @@ +import os +import subprocess + +from nmigen.build import * +from nmigen.vendor.xilinx_7series import * +from nmigen_boards.resources import * +from nmigen_boards.qmtech_daughterboard import QMTechDaughterboard + +__all__ = ["QMTechXC7A35TCorePlatform"] + +class QMTechXC7A35TPlatform(Xilinx7SeriesPlatform): + device = "xc7a35t" + package = "ftg256" + speed = "1" + default_clk = "clk50" + default_rst = "rst" + + def __init__(self, standalone=True, toolchain="Vivado"): + if not standalone: + # D3 - we do not use LEDResources here, because there are five LEDs + # on the daughterboard and this will then clash with those + self.resources[2] = Resource("core_led", 0, PinsN("E6"), Attrs(IOSTANDARD="LVCMOS33")) + daughterboard = QMTechDaughterboard(Attrs(IOSTANDARD="LVCMOS33")) + self.connectors += daughterboard.connectors + self.resources += daughterboard.resources + + super().__init__(toolchain=toolchain) + + resources = [ + Resource("clk50", 0, Pins("N11", dir="i"), + Clock(50e6), Attrs(IOSTANDARD="LVCMOS33")), + + # SW2 + Resource("rst", 0, PinsN("K5", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), + + *LEDResources( + pins="E6", invert=True, + attrs=Attrs(IOSTANDARD="LVCMOS33")), + + # MT25QL128 + Resource("qspi_flash", 0, + Subsignal("cs", PinsN("L12")), + Subsignal("clk", Pins("E8")), + Subsignal("dq", Pins("J13 J14 K15 K16")), + Attrs(IOSTANDARD="LVCMOS33") + ), + + # MT41J128M16JT-125K + Resource("ddr3", 0, + Subsignal("rst", PinsN("E15", dir="o")), + Subsignal("clk", DiffPairs("B9", "A10", dir="o"), Attrs(IOSTANDARD="DIFF_SSTL135")), + Subsignal("clk_en", Pins("D13", dir="o")), + Subsignal("cs", PinsN("-", dir="o")), + Subsignal("we", PinsN("C12", dir="o")), + Subsignal("ras", PinsN("B16", dir="o")), + Subsignal("cas", PinsN("C11", dir="o")), + Subsignal("a", Pins("B14 C8 A14 C14 C9 B10 D9 A12 D8 A13 B12 A9 A8 B11", dir="o")), + Subsignal("ba", Pins("C16 A15 B15", dir="o")), + Subsignal("dqs", DiffPairs("D14 D15", "G14 F14", dir="io"), + Attrs(IOSTANDARD="DIFF_SSTL135")), + Subsignal("dq", Pins("F15 F13 E16 D11 E12 E13 D16 E11 G12 J16 G16 J15 H14 H12 H16 H13", dir="io"), + Attrs(IN_TERM="UNTUNED_SPLIT_40")), + Subsignal("dm", Pins("F12 H11", dir="o")), + Subsignal("odt", Pins("C13", dir="o")), + Attrs(IOSTANDARD="SSTL135", SLEW="FAST"), + ), + ] + + # The connectors are named after the daughterboard, not the core board + # because on the different core boards the names vary, but on the + # daughterboard they stay the same, which we need to connect the + # daughterboard peripherals to the core board. + # On this board J2 is U7 and J3 is U8 + connectors = [ + Connector("J", 2, { + # odd row even row + "7": "M12", "8": "N13", + "9": "N14", "10": "N16", + "11": "P15", "12": "P16", + "13": "R15", "14": "R16", + "15": "T14", "16": "T15", + "17": "P13", "18": "P14", + "19": "T13", "20": "R13", + "21": "T12", "22": "R12", + "23": "L13", "24": "N12", + "25": "K12", "26": "K13", + "27": "P10", "28": "P11", + "29": "N9", "30": "P9", + "31": "T10", "32": "R11", + "33": "T9", "34": "R10", + "35": "T8", "36": "R8", + "37": "T7", "38": "R7", + "39": "T5", "40": "R6", + "41": "P6", "42": "R5", + "43": "N6", "44": "M6", + "45": "L5", "46": "P5", + "47": "T4", "48": "T3", + "49": "R3", "50": "T2", + "51": "R2", "52": "R1", + "53": "M5", "54": "N4", + "55": "P4", "56": "P3", + "57": "N1", "58": "P1", + "59": "M2", "60": "M1", + }), + + Connector("J", 3, { + # odd row even row + "7": "B7", "8": "A7", + "9": "B6", "10": "B5", + "11": "E6", "12": "K5", + "13": "J5", "14": "J4", + "15": "G5", "16": "G4", + "17": "C7", "18": "C6", + "19": "D6", "20": "D5", + "21": "A5", "22": "A4", + "23": "B4", "24": "A3", + "25": "D4", "26": "C4", + "27": "C3", "28": "C2", + "29": "B2", "30": "A2", + "31": "C1", "32": "B1", + "33": "E2", "34": "D1", + "35": "E3", "36": "D3", + "37": "F5", "38": "E5", + "39": "F2", "40": "E1", + "41": "F4", "42": "F3", + "43": "G2", "44": "G1", + "45": "H2", "46": "H1", + "47": "K1", "48": "J1", + "49": "L3", "50": "L2", + "51": "H5", "52": "H4", + "53": "J3", "54": "H3", + "55": "K3", "56": "K2", + "57": "L4", "58": "M4", + "59": "N3", "60": "N2", + }) + ] + + def toolchain_prepare(self, fragment, name, **kwargs): + overrides = { + "script_before_bitstream": + "set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]", + "script_after_bitstream": + "write_cfgmem -force -format bin -interface spix4 -size 16 " + "-loadbit \"up 0x0 {name}.bit\" -file {name}.bin".format(name=name), + "add_constraints": + """ + set_property INTERNAL_VREF 0.675 [get_iobanks 15] + set_property CFGBVS VCCO [current_design] + set_property CONFIG_VOLTAGE 3.3 [current_design] + """ + } + return super().toolchain_prepare(fragment, name, **overrides, **kwargs) + + def toolchain_program(self, products, name): + loader = os.environ.get("OPENFPGALOADER", "openFPGALoader") + with products.extract("{}.bit".format(name)) as bitstream_filename: + subprocess.run([loader, "-v", "-c", "ft232", bitstream_filename], check=True) + + +if __name__ == "__main__": + from nmigen_boards.test.blinky import * + QMTechXC7A35TPlatform(standalone=True).build(Blinky(), do_program=True)