re-bba-rb/re-bba/ReBba/amaranth_boards/arty_s7.py

236 lines
9.2 KiB
Python
Raw Normal View History

2022-01-07 23:15:38 +01:00
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)