Merge pull request #676 from boondocklabs/master

Add support for alibaba cloud xcku3p card
This commit is contained in:
Gwenhael Goavec-Merou 2026-06-25 15:30:24 +02:00 committed by GitHub
commit d90fa0ca85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 140 additions and 111 deletions

View File

@ -13,6 +13,13 @@
Memory: OK Memory: OK
Flash: OK Flash: OK
- ID: alibaba_u3p
Description: AS02MC04 (Alibaba Cloud) Kintex UltraScale+ NIC
URL: https://www.controlpaths.com/2026/01/18/as02mc04-kintex-ultrascale-plus/
FPGA: Kintex UltraScale+ xcku3p-ffvb676
Memory: OK
Flash: OK
- ID: alinx_ax7201 - ID: alinx_ax7201
Description: AX7201 FPGA Dev Board & Kit with AMD Artix 7 Description: AX7201 FPGA Dev Board & Kit with AMD Artix 7
URL: https://www.en.alinx.com/Product/FPGA-Development-Boards/Artix-7/AX7201.html URL: https://www.en.alinx.com/Product/FPGA-Development-Boards/Artix-7/AX7201.html

View File

@ -10,6 +10,7 @@ XILINX_PARTS := xc3s500evq100 \
xc7k325tfbg900 xc7k325tffg676 xc7k325tffg900 \ xc7k325tfbg900 xc7k325tffg676 xc7k325tffg900 \
xc7k420tffg901 \ xc7k420tffg901 \
xcku3p-ffva676 \ xcku3p-ffva676 \
xcku3p-ffvb676 \
xc7vx330tffg1157 \ xc7vx330tffg1157 \
xcku040-ffva1156 xcku060-ffva1156 \ xcku040-ffva1156 xcku060-ffva1156 \
xcku5p-ffvb676 \ xcku5p-ffvb676 \

View File

@ -37,7 +37,7 @@ packages = {
}, },
} }
if len(os.sys.argv) != 3 : if len(os.sys.argv) != 3:
print("missing board flash type params") print("missing board flash type params")
os.sys.exit() os.sys.exit()
part = os.sys.argv[1] part = os.sys.argv[1]
@ -46,16 +46,16 @@ flash_type = os.sys.argv[2]
# Check file type keyword # Check file type keyword
assert flash_type in ["spi", "bpi"] assert flash_type in ["spi", "bpi"]
build_dir="tmp_" + part build_dir = "tmp_" + part
if not os.path.isdir(build_dir): if not os.path.isdir(build_dir):
try: try:
os.mkdir(build_dir) os.mkdir(build_dir)
except OSError: except OSError:
print ("Creation of the directory %s failed" % build_dir) print("Creation of the directory %s failed" % build_dir)
else: else:
print ("Successfully created the directory %s " % build_dir) print("Successfully created the directory %s " % build_dir)
currDir = os.path.abspath(os.path.curdir) + '/' currDir = os.path.abspath(os.path.curdir) + "/"
files = [] files = []
parameters = {} parameters = {}
pkg_name = None pkg_name = None
@ -63,22 +63,22 @@ pkg = None
model = "" model = ""
subpart = part[0:4].lower() subpart = part[0:4].lower()
if subpart == '10cl': if subpart == "10cl":
family = "Cyclone 10 LP" family = "Cyclone 10 LP"
tool = "quartus" tool = "quartus"
elif subpart == 'ep4c': elif subpart == "ep4c":
family = "Cyclone IV E" family = "Cyclone IV E"
tool = "quartus" tool = "quartus"
elif subpart[0:2] == '5c': elif subpart[0:2] == "5c":
family = "Cyclone V" family = "Cyclone V"
tool = "quartus" tool = "quartus"
files.append({'name': currDir + 'constr_cycloneV.tcl', files.append({"name": currDir + "constr_cycloneV.tcl",
'file_type': 'tclSource'}) "file_type": "tclSource"})
elif subpart[0:2] == '5s': elif subpart[0:2] == "5s":
family = "Stratix V" family = "Stratix V"
tool = "quartus" tool = "quartus"
files.append({'name': currDir + 'constr_cycloneV.tcl', files.append({"name": currDir + "constr_cycloneV.tcl",
'file_type': 'tclSource'}) "file_type": "tclSource"})
elif subpart == "xc7a": elif subpart == "xc7a":
family = "Artix" family = "Artix"
tool = "vivado" tool = "vivado"
@ -87,7 +87,7 @@ elif subpart == "xc7v":
family = "Virtex 7" family = "Virtex 7"
tool = "vivado" tool = "vivado"
elif subpart == "xc7k": elif subpart == "xc7k":
device_size = int(part.split('k')[1].split('t')[0]) device_size = int(part.split("k")[1].split("t")[0])
if flash_type == "bpi" or device_size <= 160: if flash_type == "bpi" or device_size <= 160:
family = "Kintex 7" family = "Kintex 7"
tool = "vivado" tool = "vivado"
@ -137,8 +137,8 @@ if model in ["xc7a", "xc7s"]:
os.sys.exit() os.sys.exit()
pkg_name = f"{model}_{pkg}" pkg_name = f"{model}_{pkg}"
if model in ["xc7k"]: if model in ["xc7k"]:
m = re.match(r"(xc7k\d+t)(\w+)", part) m = re.match(r"(xc7k\d+t)(\w+)", part)
pkg = m.group(2) pkg = m.group(2)
pkg_name = f"{model}_{pkg}" pkg_name = f"{model}_{pkg}"
if tool == "ise": if tool == "ise":
model = m.group(1) model = m.group(1)
@ -164,125 +164,136 @@ if tool in ["ise", "vivado"]:
"xcvu9p-flga2104" : "xcvu9p_flga2104", "xcvu9p-flga2104" : "xcvu9p_flga2104",
"xcvu37p-fsvh2892" : "xcvu37p_fsvh2892", "xcvu37p-fsvh2892" : "xcvu37p_fsvh2892",
"xcku3p-ffva676" : "xcku3p_ffva676", "xcku3p-ffva676" : "xcku3p_ffva676",
"xcku3p-ffvb676" : "xcku3p_ffvb676",
"xcku5p-ffvb676" : "xcku5p_ffvb676", "xcku5p-ffvb676" : "xcku5p_ffvb676",
"xcau10p-ffvb676" : "xcau10p_ffvb676", "xcau10p-ffvb676" : "xcau10p_ffvb676",
"xcau15p-ffvb676" : "xcau15p_ffvb676", "xcau15p-ffvb676" : "xcau15p_ffvb676",
}.get(part, pkg_name) }.get(part, pkg_name)
if tool == "ise": if tool == "ise":
cst_type = "UCF" cst_type = "UCF"
tool_options = {'family': family, tool_options = {
'device': { "family": family,
"xc3s500evq100": "xc3s500e", "device": {
"xc6slx9tqg144": "xc6slx9", "xc3s500evq100" : "xc3s500e",
"xc6slx9csg324": "xc6slx9", "xc6slx9tqg144" : "xc6slx9",
"xc6slx16ftg256": "xc6slx16", "xc6slx9csg324" : "xc6slx9",
"xc6slx16csg324": "xc6slx16", "xc6slx16ftg256" : "xc6slx16",
"xc6slx25csg324": "xc6slx25", "xc6slx16csg324" : "xc6slx16",
"xc6slx25tcsg324": "xc6slx25t", "xc6slx25csg324" : "xc6slx25",
"xc6slx45csg324": "xc6slx45", "xc6slx25tcsg324" : "xc6slx25t",
"xc6slx45tfgg484": "xc6slx45t", "xc6slx45csg324" : "xc6slx45",
"xc6slx100fgg484": "xc6slx100", "xc6slx45tfgg484" : "xc6slx45t",
"xc6slx150tcsg484": "xc6slx150t", "xc6slx100fgg484" : "xc6slx100",
"xc6slx150tfgg484": "xc6slx150t", "xc6slx150tcsg484" : "xc6slx150t",
"xc6vlx130tff784": "xc6vlx130t", "xc6slx150tfgg484" : "xc6slx150t",
}.get(part, model), "xc6vlx130tff784" : "xc6vlx130t",
'package': { }.get(part, model),
"xc3s500evq100": "vq100", "package": {
"xc6slx9tqg144": "tqg144", "xc3s500evq100" : "vq100",
"xc6slx9csg324": "csg324", "xc6slx9tqg144" : "tqg144",
"xc6slx16ftg256": "ftg256", "xc6slx9csg324" : "csg324",
"xc6slx16csg324": "csg324", "xc6slx16ftg256" : "ftg256",
"xc6slx25csg324": "csg324", "xc6slx16csg324" : "csg324",
"xc6slx25tcsg324": "csg324", "xc6slx25csg324" : "csg324",
"xc6slx45csg324": "csg324", "xc6slx25tcsg324" : "csg324",
"xc6slx45tfgg484": "fgg484", "xc6slx45csg324" : "csg324",
"xc6slx100fgg484": "fgg484", "xc6slx45tfgg484" : "fgg484",
"xc6slx150tcsg484": "csg484", "xc6slx100fgg484" : "fgg484",
"xc6slx150tfgg484": "fgg484", "xc6slx150tcsg484" : "csg484",
"xc6vlx130tff784": "ff784", "xc6slx150tfgg484" : "fgg484",
}.get(part, pkg), "xc6vlx130tff784" : "ff784",
'speed' : speed }.get(part, pkg),
} "speed" : speed,
}
else: else:
cst_type = "xdc" cst_type = "xdc"
# Artix/Spartan 7 Specific use case: # Artix/Spartan 7 Specific use case:
if family in ["Artix", "Spartan 7"]: if family in ["Artix", "Spartan 7"]:
tool_options = {'part': f"{device}{pkg}-1"} tool_options = {"part": f"{device}{pkg}-1"}
elif family == "Xilinx UltraScale": elif family == "Xilinx UltraScale":
if part in ["xcvu9p-flga2104", "xcku5p-ffvb676"]: if part in ["xcvu9p-flga2104", "xcku5p-ffvb676"]:
tool_options = {'part': part + '-1-e'} tool_options = {"part": part + "-1-e"}
parameters["secondaryflash"]= { parameters["secondaryflash"] = {
'datatype': 'int', "datatype": "int",
'paramtype': 'vlogdefine', "paramtype": "vlogdefine",
'description': 'secondary flash', "description": "secondary flash",
'default': 1} "default": 1,
}
elif part == "xcku3p-ffva676": elif part == "xcku3p-ffva676":
tool_options = {'part': part + '-2-e'} tool_options = {"part": part + "-2-e"}
elif part == "xcku3p-ffvb676":
tool_options = {"part": part + "-2-e"}
elif part == "xcvu37p-fsvh2892": elif part == "xcvu37p-fsvh2892":
tool_options = {'part': part + '-2L-e'} tool_options = {"part": part + "-2L-e"}
elif part in ["xcku040-ffva1156", "xcku060-ffva1156"]: elif part in ["xcku040-ffva1156", "xcku060-ffva1156"]:
tool_options = {'part': part + '-2-e'} tool_options = {"part": part + "-2-e"}
parameters["secondaryflash"]= { parameters["secondaryflash"] = {
'datatype': 'int', "datatype" : "int",
'paramtype': 'vlogdefine', "paramtype" : "vlogdefine",
'description': 'secondary flash', "description" : "secondary flash",
'default': 1} "default" : 1,
}
elif part == "xcau10p-ffvb676": elif part == "xcau10p-ffvb676":
tool_options = {'part': part + '-1-e'} tool_options = {"part": part + "-1-e"}
elif part == "xcau15p-ffvb676": elif part == "xcau15p-ffvb676":
tool_options = {'part': part + '-2-e'} tool_options = {"part": part + "-2-e"}
else: else:
tool_options = {'part': part + '-1'} tool_options = {"part": part + "-1"}
cst_file = currDir + "constr_" + pkg_name + "." + cst_type.lower() cst_file = currDir + "constr_" + pkg_name + "." + cst_type.lower()
files.append({'name': os.path.join(currDir, f"xilinx_{flash_type}OverJtag.v"), files.append({"name": os.path.join(currDir, f"xilinx_{flash_type}OverJtag.v"),
'file_type': 'verilogSource'}) "file_type": "verilogSource"})
files.append({'name': cst_file, 'file_type': cst_type}) files.append({"name": cst_file, "file_type": cst_type})
else: else:
# Altera only support SPI mode. # Altera only support SPI mode.
assert flash_type in ["spi"] assert flash_type in ["spi"]
full_part = { full_part = {
"10cl016484" : "10CL016YU484C8G", "10cl016484" : "10CL016YU484C8G",
"10cl025256" : "10CL025YU256C8G", "10cl025256" : "10CL025YU256C8G",
"10cl055484" : "10CL055YU484C8G", "10cl055484" : "10CL055YU484C8G",
"10cl006144" : "10CL006YE144C8G", "10cl006144" : "10CL006YE144C8G",
"ep4cgx15027": "EP4CGX150DF27I7", "ep4cgx15027" : "EP4CGX150DF27I7",
"ep4ce11523" : "EP4CE115F23C7", "ep4ce11523" : "EP4CE115F23C7",
"ep4ce2217" : "EP4CE22F17C6", "ep4ce2217" : "EP4CE22F17C6",
"ep4ce1523" : "EP4CE15F23C8", "ep4ce1523" : "EP4CE15F23C8",
"ep4ce1017" : "EP4CE10F17C8", "ep4ce1017" : "EP4CE10F17C8",
"ep4ce622" : "EP4CE6E22C8", "ep4ce622" : "EP4CE6E22C8",
"5ce215" : "5CEBA2U15C8", "5ce215" : "5CEBA2U15C8",
"5ce223" : "5CEFA2F23I7", "5ce223" : "5CEFA2F23I7",
"5ce523" : "5CEFA5F23I7", "5ce523" : "5CEFA5F23I7",
"5ce423" : "5CEBA4F23C8", "5ce423" : "5CEBA4F23C8",
"5ce927" : "5CEBA9F27C7", "5ce927" : "5CEBA9F27C7",
"5cse423" : "5CSEMA4U23C6", "5cse423" : "5CSEMA4U23C6",
"5cse623" : "5CSEBA6U23I7", "5cse623" : "5CSEBA6U23I7",
"5sgsd5" : "5SGSMD5K2F40I3"}[part] "5sgsd5" : "5SGSMD5K2F40I3",
files.append({'name': currDir + 'altera_spiOverJtag.v', }[part]
'file_type': 'verilogSource'}) files.append({"name": currDir + "altera_spiOverJtag.v",
files.append({'name': currDir + 'altclkctrl_inst.v', "file_type": "verilogSource"})
'file_type': 'verilogSource'}) files.append({"name": currDir + "altclkctrl_inst.v",
files.append({'name': currDir + 'altera_spiOverJtag.sdc', "file_type": "verilogSource"})
'file_type': 'SDC'}) files.append({"name": currDir + "altera_spiOverJtag.sdc",
tool_options = {'device': full_part, 'family':family} "file_type": "SDC"})
tool_options = {"device": full_part, "family": family}
files.append({'name': os.path.join(currDir, f"{flash_type}OverJtag_core.v"), files.append({
'file_type': 'verilogSource'}) "name" : os.path.join(currDir, f"{flash_type}OverJtag_core.v"),
"file_type" : "verilogSource",
})
parameters[family.lower().replace(' ', '')]= { parameters[family.lower().replace(" ", "")] = {
'datatype': 'int', "datatype": "int",
'paramtype': 'vlogdefine', "paramtype": "vlogdefine",
'description': 'fpga family', "description": "fpga family",
'default': 1} "default": 1
}
edam = {'name' : f"{flash_type}OverJtag", edam = {
'files': files, "name" : f"{flash_type}OverJtag",
'tool_options': {tool: tool_options}, "files" : files,
'parameters': parameters, "tool_options" : {tool: tool_options},
'toplevel' : f"{flash_type}OverJtag", "parameters" : parameters,
"toplevel" : f"{flash_type}OverJtag",
} }
backend = get_edatool(tool)(edam=edam, work_root=build_dir) backend = get_edatool(tool)(edam=edam, work_root=build_dir)
@ -290,13 +301,13 @@ backend.configure()
backend.build() backend.build()
if tool in ["vivado", "ise"]: if tool in ["vivado", "ise"]:
import gzip
import shutil import shutil
import subprocess import subprocess
import gzip
# Compress bitstream. # Compress bitstream.
with open(f"tmp_{part}/{flash_type}OverJtag.bit", 'rb') as bit: with open(f"tmp_{part}/{flash_type}OverJtag.bit", "rb") as bit:
with gzip.open(f"{flash_type}OverJtag_{part}.bit.gz", 'wb', compresslevel=9) as bit_gz: with gzip.open(f"{flash_type}OverJtag_{part}.bit.gz", "wb", compresslevel=9) as bit_gz:
shutil.copyfileobj(bit, bit_gz) shutil.copyfileobj(bit, bit_gz)
# Create Symbolic links for all supported packages — only when building # Create Symbolic links for all supported packages — only when building

View File

@ -0,0 +1,7 @@
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
# Table 1-2 from UG570
set_property CFGBVS GND [current_design]
# Primary QSPI flash
# Connection done through the STARTUPE3 block

Binary file not shown.

View File

@ -73,11 +73,13 @@ module spiOverJtag
`ifdef spartan3e `ifdef spartan3e
assign sck = drck; assign sck = drck;
`else // !spartan6 && !spartan3e `else // !spartan6 && !spartan3e
`ifdef xilinxultrascale `ifdef xilinxultrascale
assign sck = drck; assign sck = drck;
wire [3:0] di; wire [3:0] di;
assign sdo_dq1 = di[1]; assign sdo_dq1 = di[1];
wire [3:0] do = {hldn_dq3, wpn_dq2, 1'b0, sdi_dq0};
wire [3:0] do = {hldn_dq3, wpn_dq2, 1'b0, sdi_dq0};
wire [3:0] dts = 4'b0010; wire [3:0] dts = 4'b0010;
// secondary BSCANE3 signals // secondary BSCANE3 signals
wire sel_sec, spi_clk_sec; wire sel_sec, spi_clk_sec;

View File

@ -118,6 +118,7 @@ static std::map <std::string, target_board_t> board_list = {
JTAG_BOARD("litex-acorn-baseboard-mini", "xc7a200tsbg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("litex-acorn-baseboard-mini", "xc7a200tsbg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alchitry_au", "xc7a35tftg256", "ft2232", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("alchitry_au", "xc7a35tftg256", "ft2232", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alchitry_au_plus","xc7a100tftg256", "ft2232", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("alchitry_au_plus","xc7a100tftg256", "ft2232", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alibaba_u3p", "xcku3p-ffvb676", "", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alinx_ax516", "xc6slx16csg324", "", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("alinx_ax516", "xc6slx16csg324", "", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alinx_ax7101", "xc7a100tfgg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("alinx_ax7101", "xc7a100tfgg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT),
JTAG_BOARD("alinx_ax7102", "xc7a100tfgg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT), JTAG_BOARD("alinx_ax7102", "xc7a100tfgg484", "", SPI_FLASH, 0, 0, CABLE_DEFAULT),