import os import textwrap import subprocess from amaranth.build import * from amaranth.vendor.xilinx_7series import * from .resources import * __all__ = ["ArtyS7_25Platform", "ArtyS7_50Platform"] class _ArtyS7Platform(Xilinx7SeriesPlatform): package = "csga324" speed = "1" default_clk = "clk100" default_rst = "rst" resources = [ Resource("clk100", 0, Pins("R2", dir="i"), Clock(100e6), Attrs(IOSTANDARD="SSTL135")), Resource("rst", 0, PinsN("C18", dir="i"), Attrs(IOSTANDARD="LVCMOS33")), *LEDResources(pins="E18 F13 E13 H15", attrs=Attrs(IOSTANDARD="LVCMOS33")), RGBLEDResource(0, r="J15", g="G17", b="F15", attrs=Attrs(IOSTANDARD="LVCMOS33")), RGBLEDResource(1, r="E15", g="F18", b="E14", attrs=Attrs(IOSTANDARD="LVCMOS33")), *ButtonResources(pins="G15 K16 J16 H13", attrs=Attrs(IOSTANDARD="LVCMOS33")), *SwitchResources(pins="H14 H18 G18 M5", attrs=Attrs(IOSTANDARD="LVCMOS33")), UARTResource(0, rx="V12", tx="R12", attrs=Attrs(IOSTANDARD="LVCMOS33") ), SPIResource(0, cs_n="H16", clk="G16", copi="H17", cipo="K14", attrs=Attrs(IOSTANDARD="LVCMOS33") ), I2CResource(0, scl="J14", sda="J13", attrs=Attrs(IOSTANDARD="LVCMOS33") ), *SPIFlashResources(0, cs_n="M13", clk="D11", copi="K17", cipo="K18", wp_n="L14", hold_n="M15", attrs=Attrs(IOSTANDARD="LVCMOS33") ), Resource("ddr3", 0, Subsignal("rst", PinsN("J6", dir="o")), Subsignal("clk", DiffPairs("R5", "T4", dir="o"), Attrs(IOSTANDARD="DIFF_SSTL135")), Subsignal("clk_en", Pins("T2", dir="o")), Subsignal("cs", PinsN("R3", dir="o")), Subsignal("we", PinsN("P7", dir="o")), Subsignal("ras", PinsN("U1", dir="o")), Subsignal("cas", PinsN("V3", dir="o")), Subsignal("a", Pins("U2 R4 V2 V4 T3 R7 V6 T6 U7 V7 P6 T5 R6 U6", dir="o")), Subsignal("ba", Pins("V5 T1 U3", dir="o")), Subsignal("dqs", DiffPairs("K1 N3", "L1 N2", dir="io"), Attrs(IOSTANDARD="DIFF_SSTL135")), Subsignal("dq", Pins("K2 K3 L4 M6 K6 M4 L5 L6 N4 R1 N1 N5 M2 P1 M1 P2", dir="io"), Attrs(IN_TERM="UNTUNED_SPLIT_40")), Subsignal("dm", Pins("K4 M3", dir="o")), Subsignal("odt", Pins("P5", dir="o")), Attrs(IOSTANDARD="SSTL135", SLEW="FAST"), ), ] connectors = [ Connector("pmod", 0, "L17 L18 M14 N14 - - M16 M17 M18 N18 - -"), # JA Connector("pmod", 1, "P17 P18 R18 T18 - - P14 P15 N15 P16 - -"), # JB Connector("pmod", 2, "U15 V16 U17 U18 - - U16 P13 R13 V14 - -"), # JC Connector("pmod", 3, "V15 U12 V13 T12 - - T13 R11 T11 U11 - -"), # JD Connector("ck_io", 0, { # Outer Digital Header "io0": "L13", "io1": "N13", "io2": "L16", "io3": "R14", "io4": "T14", "io5": "R16", "io6": "R17", "io7": "V17", "io8": "R15", "io9": "T15", "io10": "H16", "io11": "H17", "io12": "K14", "io13": "G16", # Inner Digital Header "io26": "U11", "io27": "T11", "io28": "R11", "io29": "T13", "io30": "T12", "io31": "V13", "io32": "U12", "io33": "V15", "io34": "V14", "io35": "R13", "io36": "P13", "io37": "U16", "io38": "U18", "io39": "U17", "io40": "V16", "io41": "U15", # Outer Analog Header as Digital IO "a0": "G13", "a1": "B16", "a2": "A16", "a3": "C13", "a4": "C14", "a5": "D18", # Inner Analog Header as Digital IO "io20": "B14", "io21": "A14", "io22": "D16", "io23": "D17", "io24": "D14", "io25": "D15" }), Connector("xadc", 0, { # Outer Analog Header "vaux0_p": "B13", "vaux0_n": "A13", "vaux1_p": "B15", "vaux1_n": "A15", "vaux9_p": "E12", "vaux9_n": "D12", "vaux2_p": "B17", "vaux2_n": "A17", "vaux10_p": "C17", "vaux10_n": "B18", "vaux11_p": "E16", "vaux11_n": "E17", # Inner Analog Header "vaux8_p": "B14", "vaux8_n": "A14", "vaux3_p": "D16", "vaux3_n": "D17", }) ] 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 mcs -interface spix4 -size 16 " "-loadbit \"up 0x0 {name}.bit\" -file {name}.mcs".format(name=name), "add_constraints": "set_property INTERNAL_VREF 0.675 [get_iobanks 34]" } return super().toolchain_prepare(fragment, name, **overrides, **kwargs) def toolchain_program(self, product, name, *, programmer="vivado", flash=True): assert programmer in ("vivado", "openocd") if programmer == "vivado": if flash: # It does not appear possible to reset the FPGA via TCL after # flash programming. with product.extract("{}.bin".format(name)) as bitstream_filename: cmd = textwrap.dedent(""" open_hw_manager connect_hw_server open_hw_target current_hw_device [lindex [get_hw_devices] 0] create_hw_cfgmem -hw_device [current_hw_device] s25fl128sxxxxxx0-spi-x1_x2_x4 set_property PROGRAM.FILES {{{}}} [current_hw_cfgmem] set_property PROGRAM.ADDRESS_RANGE {{use_file}} [current_hw_cfgmem] set_property PROGRAM.BLANK_CHECK 1 [current_hw_cfgmem] set_property PROGRAM.ERASE 1 [current_hw_cfgmem] set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem] set_property PROGRAM.VERIFY 1 [current_hw_cfgmem] create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]] program_hw_devices program_hw_cfgmem close_hw_manager puts "Vivado TCL cannot reset boards. Reset or power-cycle your board now." """).format(bitstream_filename).encode("utf-8") subprocess.run(["vivado", "-nolog", "-nojournal", "-mode", "tcl"], input=cmd, check=True) else: with product.extract("{}.bit".format(name)) as bitstream_filename: cmd = textwrap.dedent(""" open_hw_manager connect_hw_server open_hw_target current_hw_device [lindex [get_hw_devices] 0] set_property PROGRAM.FILE {{{}}} [current_hw_device] program_hw_devices close_hw_manager """).format(bitstream_filename).encode("utf-8") subprocess.run(["vivado", "-nolog", "-nojournal", "-mode", "tcl"], input=cmd, check=True) else: openocd = os.environ.get("OPENOCD", "openocd") # In order, OpenOCD searches these directories for files: # * $HOME/.openocd if $HOME exists (*nix) # * Path pointed to by $OPENOCD_SCRIPTS if $OPENOCD_SCRIPTS exists # * $APPDATA/OpenOCD on Windows # Place the bscan_spi_xc7s50.bit proxy bitstream under a directory # named "proxy" in one of the above directories so OpenOCD finds it. if flash: with product.extract("{}.bin".format(name)) as fn: subprocess.check_call([openocd, "-f", "board/arty_s7.cfg", "-c", """init; jtagspi_init 0 [find proxy/bscan_spi_xc7s50.bit]; jtagspi_program {} 0; xc7_program xc7.tap; shutdown""".format(fn)]) else: with product.extract("{}.bit".format(name)) as fn: subprocess.check_call(["openocd", "-f", "board/arty_s7.cfg", "-c", """init; pld load 0 {}; shutdown""".format(fn)]) class ArtyS7_50Platform(_ArtyS7Platform): device = "xc7s50" class ArtyS7_25Platform(_ArtyS7Platform): device = "xc7s25" if __name__ == "__main__": from .test.blinky import * ArtyS7_25Platform().build(Blinky(), do_program=True)