fix(spiOverJtag): package-specific FGG676 bitstream build for QMTech XC7A100T
- Makefile: add xc7a100tfgg676 target - build.py: parse device+package form (e.g. xc7a100tfgg676), stop aliasing a package-specific bitstream to other packages via symlink - constr_xc7a_fgg676.xdc: set BITSTREAM.STARTUP.STARTUPCLK JtagClk (camelCase; all-caps JTAGCLK is silently rejected and falls back to Cclk, leaving EOS=0 over JTAG), correct SPI pins to LVCMOS33 per QMTech schematic - README.md: document package-specific bitstream build - remove stale spiOverJtag_xc7a100tfgg676.bit.gz (rebuilt by above)
This commit is contained in:
parent
ed6025645f
commit
6df17fddd8
|
|
@ -3,7 +3,7 @@ XILINX_PARTS := xc3s500evq100 \
|
||||||
xc6slx16ftg256 xc6slx16csg324 xc6slx25csg324 xc6slx45csg324 xc6slx100fgg484 \
|
xc6slx16ftg256 xc6slx16csg324 xc6slx25csg324 xc6slx45csg324 xc6slx100fgg484 \
|
||||||
xc6slx25tcsg324 xc6slx45tfgg484 xc6slx150tfgg484 xc6slx150tcsg484 \
|
xc6slx25tcsg324 xc6slx45tfgg484 xc6slx150tfgg484 xc6slx150tcsg484 \
|
||||||
xc6vlx130tff784 \
|
xc6vlx130tff784 \
|
||||||
xc7a12t xc7a15t xc7a25t xc7a35t xc7a50t xc7a75t xc7a100t xc7a200t \
|
xc7a12t xc7a15t xc7a25t xc7a35t xc7a50t xc7a75t xc7a100t xc7a100tfgg676 xc7a200t \
|
||||||
xc7s6 xc7s15 xc7s25 xc7s50 xc7s75 xc7s100 \
|
xc7s6 xc7s15 xc7s25 xc7s50 xc7s75 xc7s100 \
|
||||||
xc7k70tfbg484 xc7k70tfbg676 \
|
xc7k70tfbg484 xc7k70tfbg676 \
|
||||||
xc7k160tffg676 \
|
xc7k160tffg676 \
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,24 @@ Clean temporary/build files:
|
||||||
make clean
|
make clean
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Package-specific bitstreams
|
||||||
|
|
||||||
|
Some boards within the same FPGA family/size use different SPI flash pin
|
||||||
|
mappings depending on the device package. When the SPI pins differ between
|
||||||
|
packages, `build.py` must produce a distinct bitstream per package rather
|
||||||
|
than aliasing one build to every package via symlinks.
|
||||||
|
|
||||||
|
To build a package-specific bitstream, pass the full device name
|
||||||
|
(device + package) to `make`. Example for the QMTech XC7A100T (FGG676)
|
||||||
|
core board:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make spiOverJtag_xc7a100tfgg676.bit.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
This consumes `constr_xc7a_fgg676.xdc` and produces a bitstream wired to
|
||||||
|
the FGG676 SPI dedicated configuration pins (C8/B19/A18/B18/A19).
|
||||||
|
|
||||||
## Add support for a new device
|
## Add support for a new device
|
||||||
|
|
||||||
### 1. Register the part in `Makefile`
|
### 1. Register the part in `Makefile`
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,21 @@ else:
|
||||||
os.sys.exit()
|
os.sys.exit()
|
||||||
|
|
||||||
if model in ["xc7a", "xc7s"]:
|
if model in ["xc7a", "xc7s"]:
|
||||||
pkg = packages[family][part][0]
|
# Accept either a bare device (e.g. "xc7a100t" -> first package) or a
|
||||||
|
# device suffixed with a package (e.g. "xc7a100tfgg676" -> "fgg676").
|
||||||
|
if part in packages[family]:
|
||||||
|
pkg = packages[family][part][0]
|
||||||
|
device = part
|
||||||
|
else:
|
||||||
|
m = re.match(r"(xc7[as]\d+t?)([a-z]+\d+)", part)
|
||||||
|
if not m or m.group(1) not in packages[family]:
|
||||||
|
print(f"Error: cannot parse part/package from '{part}'")
|
||||||
|
os.sys.exit()
|
||||||
|
device = m.group(1)
|
||||||
|
pkg = m.group(2)
|
||||||
|
if pkg not in packages[family][device]:
|
||||||
|
print(f"Error: package '{pkg}' not listed for device '{device}'")
|
||||||
|
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)
|
||||||
|
|
@ -193,7 +207,7 @@ if tool in ["ise", "vivado"]:
|
||||||
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"{part}{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'}
|
||||||
|
|
@ -285,10 +299,17 @@ if tool in ["vivado", "ise"]:
|
||||||
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.
|
# Create Symbolic links for all supported packages — only when building
|
||||||
if family in ["Artix", "Spartan 7"]:
|
# the bare device target (e.g. "xc7a100t"). When the explicit
|
||||||
|
# device+package form is used (e.g. "xc7a100tfgg676"), the bitstream is
|
||||||
|
# package-specific and must not be aliased to other packages.
|
||||||
|
if family in ["Artix", "Spartan 7"] and part in packages[family]:
|
||||||
in_file = f"{flash_type}OverJtag_{part}.bit.gz"
|
in_file = f"{flash_type}OverJtag_{part}.bit.gz"
|
||||||
for pkg in packages[family][part]:
|
for pkg in packages[family][part]:
|
||||||
out_file = f"{flash_type}OverJtag_{part}{pkg}.bit.gz"
|
out_file = f"{flash_type}OverJtag_{part}{pkg}.bit.gz"
|
||||||
if not os.path.exists(out_file):
|
# Don't overwrite a package-specific bitstream with a symlink to
|
||||||
|
# the first-package build (this was the original bug).
|
||||||
|
if os.path.islink(out_file) or not os.path.exists(out_file):
|
||||||
|
if os.path.islink(out_file):
|
||||||
|
os.unlink(out_file)
|
||||||
subprocess.run(["ln", "-s", in_file, out_file])
|
subprocess.run(["ln", "-s", in_file, out_file])
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,27 @@ set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH {4} [current_design]
|
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH {4} [current_design]
|
||||||
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
|
||||||
|
|
||||||
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVTTL} [get_ports {csn}]
|
# Drive the startup sequencer from JTAG TCK so the bitstream reaches EOS
|
||||||
set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVTTL} [get_ports {sdi_dq0}]
|
# (End-Of-Startup, i.e. DONE=HIGH) when loaded over JTAG via DLC10.
|
||||||
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVTTL} [get_ports {sdo_dq1}]
|
# Without this Vivado defaults to Cclk (CCLK) — but CCLK is only driven
|
||||||
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVTTL} [get_ports {wpn_dq2}]
|
# during SelectMAP/SPI configuration, not during JTAG. The result is a
|
||||||
set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVTTL} [get_ports {hldn_dq3}]
|
# bitstream whose COR0 register has STARTUPCLK=00 (Cclk); we verified the
|
||||||
|
# previous CI build had COR0=0x02003fe5 (bits[27:26]=00). UG470 §6.3
|
||||||
|
# Table 6-3 lists the valid Vivado literal as `JtagClk` (camelCase) —
|
||||||
|
# all-caps `JTAGCLK` is silently rejected and Vivado falls back to Cclk.
|
||||||
|
set_property BITSTREAM.STARTUP.STARTUPCLK JtagClk [current_design]
|
||||||
|
|
||||||
|
# XC7A75T/100T/200T-FGG676 SPI flash pins on QMTech XC7A100T-2FGG676I core board.
|
||||||
|
# Verified against QMTECH_XC7A75T_100T_200T-CORE-BOARD-V01-20210109.pdf schematic
|
||||||
|
# (https://github.com/ChinaQMTECH/QMTECH_XC7A75T-100T-200T_Core_Board).
|
||||||
|
# These are Bank 14 dual-purpose user IO pins (D00..D03, FCS_B) wired to the
|
||||||
|
# on-board N25Q064A SPI flash (JEDEC 0x20BA17). CCLK is driven internally via
|
||||||
|
# the STARTUPE2 primitive instantiated in xilinx_spiOverJtag.v.
|
||||||
|
set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {csn}]
|
||||||
|
set_property -dict {PACKAGE_PIN R14 IOSTANDARD LVCMOS33} [get_ports {sdi_dq0}]
|
||||||
|
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVCMOS33} [get_ports {sdo_dq1}]
|
||||||
|
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {wpn_dq2}]
|
||||||
|
set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVCMOS33} [get_ports {hldn_dq3}]
|
||||||
|
|
||||||
create_clock -period 33.000 -name jtag_tck -waveform {0.000 16.500} [get_pins {bscane2_inst/DRCK}]
|
create_clock -period 33.000 -name jtag_tck -waveform {0.000 16.500} [get_pins {bscane2_inst/DRCK}]
|
||||||
create_clock -period 33.000 -name vers_tck -waveform {0.000 16.500} [get_pins {bscane2_version/DRCK}]
|
create_clock -period 33.000 -name vers_tck -waveform {0.000 16.500} [get_pins {bscane2_version/DRCK}]
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue