同步了 fpga_flash, vivado-prj-create 两个skill

This commit is contained in:
Myfro9
2026-05-09 01:37:44 -05:00
parent 9e700d10b7
commit 17fb1b213d
13 changed files with 4467 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
"""
Step 1: Check and update Vivado Flash device CSV to include w25q128bv.
Checks whether 'w25q128bv-spi-x1_x2_x4' is present in Vivado's
xicom_cfgmem_part_table.csv. If not, appends the correct row.
Usage:
python check_flash_csv.py --vivado-dir "D:/Xilinx/Vivado/2018.1"
Exit codes:
0 = device already present (no changes made)
2 = device was successfully added (Vivado restart required)
1 = error (CSV not found or write failure)
"""
import argparse
import os
import sys
DEVICE_NAME = "w25q128bv-spi-x1_x2_x4"
# Fields: NAME, MEM_DEVICE, MEM_TYPE, MEM_DENSITY, DATA_WIDTH,
# MEM_MANUFACTURER, NUM_CFG_FILES, MEM_DEVICE_ALIAS, MEM_FAMILY
NEW_ROW = "w25q128bv-spi-x1_x2_x4,w25q128bv,spi,128,x1_x2_x4,Winbond,1,w25q128b,w25q"
def main():
parser = argparse.ArgumentParser(
description="Check/update Vivado Flash CSV for w25q128bv"
)
parser.add_argument(
"--vivado-dir",
required=True,
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
)
args = parser.parse_args()
csv_path = os.path.join(
args.vivado_dir, "data", "xicom", "xicom_cfgmem_part_table.csv"
)
csv_path = csv_path.replace("\\", "/")
if not os.path.isfile(csv_path):
print(f"ERROR: CSV not found at: {csv_path}", file=sys.stderr)
print(
" Please verify --vivado-dir points to a valid Vivado installation.",
file=sys.stderr,
)
sys.exit(1)
with open(csv_path, "r", encoding="utf-8") as f:
content = f.read()
if DEVICE_NAME in content:
print(f"[check_flash_csv] '{DEVICE_NAME}' already present. No changes needed.")
sys.exit(0)
# Append the new row (ensure trailing newline before adding)
if not content.endswith("\n"):
content += "\n"
content += NEW_ROW + "\n"
try:
with open(csv_path, "w", encoding="utf-8") as f:
f.write(content)
except PermissionError:
print(
f"ERROR: Cannot write to {csv_path}. Try running as Administrator.",
file=sys.stderr,
)
sys.exit(1)
print(f"[check_flash_csv] Added '{DEVICE_NAME}' to:")
print(f" {csv_path}")
print()
print("NOTE: You must restart Vivado for the new Flash device to be recognized.")
sys.exit(2)
if __name__ == "__main__":
main()
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""
Step 3: Generate .mcs configuration memory file using Vivado batch mode.
Calls Vivado with step3_write_mcs.tcl (located in the same scripts/ directory)
via -tclargs so no temporary script files are created.
Usage:
python gen_mcs.py \
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
--bit-file "E:/project/RU_golden/RU_golden.runs/impl_1/RU_golden_top.bit" \
--mcs-file "E:/project/RU_golden/RU_golden.runs/impl_1/RU_golden_smod.mcs"
Exit codes:
0 = success ("write_cfgmem completed successfully" in output)
1 = failure
"""
import argparse
import os
import subprocess
import sys
def norm(path: str) -> str:
"""Normalize path to forward slashes (Vivado on Windows accepts both)."""
return path.replace("\\", "/")
def main():
parser = argparse.ArgumentParser(
description="Generate .mcs from .bit via Vivado write_cfgmem"
)
parser.add_argument(
"--vivado-dir",
required=True,
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
)
parser.add_argument(
"--bit-file",
required=True,
help="Full path to the .bit file",
)
parser.add_argument(
"--mcs-file",
required=True,
help="Full path for the output .mcs file",
)
args = parser.parse_args()
vivado_dir = norm(args.vivado_dir)
bit_file = norm(args.bit_file)
mcs_file = norm(args.mcs_file)
# Locate the TCL template alongside this script
scripts_dir = os.path.dirname(os.path.abspath(__file__))
tcl_template = os.path.join(scripts_dir, "step3_write_mcs.tcl").replace("\\", "/")
# Validate inputs
vivado_exe = os.path.join(vivado_dir, "bin", "vivado.bat")
if not os.path.isfile(vivado_exe):
print(f"ERROR: Vivado not found: {vivado_exe}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(bit_file):
print(f"ERROR: .bit file not found: {bit_file}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(tcl_template):
print(f"ERROR: TCL template not found: {tcl_template}", file=sys.stderr)
sys.exit(1)
cmd = [
vivado_exe,
"-mode", "batch",
"-source", tcl_template,
"-tclargs", bit_file, mcs_file,
]
print(f"[gen_mcs] Vivado: {vivado_exe}")
print(f"[gen_mcs] bit : {bit_file}")
print(f"[gen_mcs] mcs : {mcs_file}")
print()
result = subprocess.run(cmd)
sys.exit(result.returncode)
if __name__ == "__main__":
main()
+118
View File
@@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""
Steps 4+5: Connect hardware target, configure cfgmem device, and program Flash.
Calls Vivado with step4_5_program.tcl (located in the same scripts/ directory)
via -tclargs so no temporary script files are created.
Usage:
python program_flash.py \
--vivado-dir "D:/Xilinx/Vivado/2018.1" \
--flash-part "w25q128bv-spi-x1_x2_x4" \
--bit-file "E:/project/impl_1/RU_golden_top.bit" \
--mcs-file "E:/project/impl_1/RU_golden_smod.mcs" \
[--ltx-file "E:/project/impl_1/RU_golden_top.ltx"]
If the design has no ILA (no .ltx file), omit --ltx-file or pass an
empty string; the TCL template will skip the PROBES.FILE settings.
Supported flash parts:
Micron : mt25ql128-spi-x1_x2_x4
Winbond : w25q128bv-spi-x1_x2_x4
Exit codes:
0 = success ("End of startup status: HIGH" in output)
1 = failure
"""
import argparse
import os
import subprocess
import sys
def norm(path: str) -> str:
"""Normalize path to forward slashes (Vivado on Windows accepts both)."""
return path.replace("\\", "/")
def main():
parser = argparse.ArgumentParser(
description="Program FPGA SPI Flash via Vivado Hardware Manager"
)
parser.add_argument(
"--vivado-dir",
required=True,
help="Vivado install root, e.g. D:/Xilinx/Vivado/2018.1",
)
parser.add_argument(
"--flash-part",
required=True,
help="Vivado Flash part name, e.g. w25q128bv-spi-x1_x2_x4",
)
parser.add_argument(
"--bit-file",
required=True,
help="Full path to the .bit file",
)
parser.add_argument(
"--mcs-file",
required=True,
help="Full path to the .mcs file (from Step 3)",
)
parser.add_argument(
"--ltx-file",
default="",
help="Full path to the .ltx probes file (optional; omit if no ILA)",
)
args = parser.parse_args()
vivado_dir = norm(args.vivado_dir)
bit_file = norm(args.bit_file)
mcs_file = norm(args.mcs_file)
ltx_file = norm(args.ltx_file) if args.ltx_file else ""
# Locate the TCL template alongside this script
scripts_dir = os.path.dirname(os.path.abspath(__file__))
tcl_template = os.path.join(scripts_dir, "step4_5_program.tcl").replace("\\", "/")
# Validate inputs
vivado_exe = os.path.join(vivado_dir, "bin", "vivado.bat")
if not os.path.isfile(vivado_exe):
print(f"ERROR: Vivado not found: {vivado_exe}", file=sys.stderr)
sys.exit(1)
for label, path in [("bit", bit_file), ("mcs", mcs_file)]:
if not os.path.isfile(path):
print(f"ERROR: .{label} file not found: {path}", file=sys.stderr)
sys.exit(1)
if ltx_file and not os.path.isfile(ltx_file):
print(f"ERROR: .ltx file not found: {ltx_file}", file=sys.stderr)
sys.exit(1)
if not os.path.isfile(tcl_template):
print(f"ERROR: TCL template not found: {tcl_template}", file=sys.stderr)
sys.exit(1)
cmd = [
vivado_exe,
"-mode", "batch",
"-source", tcl_template,
"-tclargs", args.flash_part, bit_file, mcs_file, ltx_file,
]
print(f"[program_flash] Vivado : {vivado_exe}")
print(f"[program_flash] Flash part: {args.flash_part}")
print(f"[program_flash] bit : {bit_file}")
print(f"[program_flash] mcs : {mcs_file}")
if ltx_file:
print(f"[program_flash] ltx : {ltx_file}")
else:
print(f"[program_flash] ltx : (none - no ILA)")
print()
result = subprocess.run(cmd)
sys.exit(result.returncode)
if __name__ == "__main__":
main()
+16
View File
@@ -0,0 +1,16 @@
# Template: Step 3 - Generate .mcs configuration memory file
# Called by gen_mcs.py via: vivado -mode batch -source step3_write_mcs.tcl -tclargs <bit_file> <mcs_file>
#
# Arguments (passed via -tclargs):
# argv[0] = BIT_FILE_PATH - Full path to the .bit file (forward slashes)
# argv[1] = MCS_FILE_PATH - Full path for the output .mcs file (forward slashes)
#
# Success indicator: output contains "write_cfgmem completed successfully" and "0 Errors"
set bit_file [lindex $argv 0]
set mcs_file [lindex $argv 1]
write_cfgmem -format mcs -size 16 -interface SPIx1 \
-loadbit [list up 0x00000000 $bit_file] \
-checksum -force \
-file $mcs_file
+47
View File
@@ -0,0 +1,47 @@
# Template: Steps 4+5 - Connect hardware, configure cfgmem, and program Flash
# Called by program_flash.py via: vivado -mode batch -source step4_5_program.tcl -tclargs <flash_part> <bit_file> <mcs_file> <ltx_file>
#
# Arguments (passed via -tclargs):
# argv[0] = FLASH_PART - Flash part name, e.g. w25q128bv-spi-x1_x2_x4
# argv[1] = BIT_FILE_PATH - Full path to the .bit file
# argv[2] = MCS_FILE_PATH - Full path to the .mcs file
# argv[3] = LTX_FILE_PATH - Full path to .ltx file, or empty string "" if no ILA
#
# Success indicator: output contains "End of startup status: HIGH" and no ERROR lines
set flash_part [lindex $argv 0]
set bit_file [lindex $argv 1]
set mcs_file [lindex $argv 2]
set ltx_file [lindex $argv 3]
set has_ltx [expr {$ltx_file ne ""}]
open_hw
connect_hw_server
open_hw_target
set_property PROGRAM.FILE $bit_file [get_hw_devices xc7a200t_0]
if {$has_ltx} {
set_property PROBES.FILE $ltx_file [get_hw_devices xc7a200t_0]
set_property FULL_PROBES.FILE $ltx_file [get_hw_devices xc7a200t_0]
}
current_hw_device [get_hw_devices xc7a200t_0]
refresh_hw_device [lindex [get_hw_devices xc7a200t_0] 0]
create_hw_cfgmem -hw_device [lindex [get_hw_devices xc7a200t_0] 0] \
[lindex [get_cfgmem_parts $flash_part] 0]
set_property PROGRAM.BLANK_CHECK 0 [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
set_property PROGRAM.ERASE 1 [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
set_property PROGRAM.CFG_PROGRAM 1 [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
set_property PROGRAM.VERIFY 1 [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
set_property PROGRAM.CHECKSUM 0 [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
set_property PROGRAM.FILES [list $mcs_file] \
[get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a200t_0] 0]]
refresh_hw_device [lindex [get_hw_devices xc7a200t_0] 0]
if {$has_ltx} {
set_property PROBES.FILE $ltx_file [get_hw_devices xc7a200t_0]
set_property FULL_PROBES.FILE $ltx_file [get_hw_devices xc7a200t_0]
}
set_property PROGRAM.FILE $bit_file [get_hw_devices xc7a200t_0]
program_hw_devices [get_hw_devices xc7a200t_0]
refresh_hw_device [lindex [get_hw_devices xc7a200t_0] 0]