Compare commits

...

19 Commits

Author SHA1 Message Date
Gwenhael Goavec-Merou b76840b20d doc/FPGAs.yml: added Kintex UltraScale+ reference 2025-11-05 18:43:38 +01:00
Gwenhael Goavec-Merou 530b7a9993
Merge pull request #593 from AEW2015/master
basic PDI prog for Spartan Ultrascale+
2025-10-23 06:50:14 +02:00
Andrew E Wilson 648a4a833a basic PDI prog for Spartan Ultrascale+ 2025-10-23 06:44:19 +02:00
Gwenhael Goavec-Merou 03be134cdd
Merge pull request #591 from hennomann/patch-1
Update part.hpp to support Lattice LFE3-150EA device
2025-10-02 12:02:15 +02:00
hennomann 617cd29dff
Update part.hpp to support Lattice LFE3-150EA device
This PR adds device ID support for the Lattice ECP3 LFE3-150EA.
Previously, only the LFE3-70E was supported.

We've tested the implementation and confirmed it works as expected.
We're happy to contribute to expanding ECP3 device support!
2025-10-02 11:32:19 +02:00
Gwenhael Goavec-Merou 205e6f9ea5 spiOverJtag/build.py: fixed model value for kintex7 with ISE 2025-09-25 17:09:38 +02:00
Gwenhael Goavec-Merou f8ae76e771 spiOverJtag/build.py: added default value for pkg variable 2025-09-25 15:47:48 +02:00
Gwenhael Goavec-Merou 8694b3c295 board: added HyVision PCIe OPT01 rev.F (Kintex7 xc7k70tfbg676) 2025-09-24 16:56:46 +02:00
Gwenhael Goavec-Merou a7b72321fe spiOverJtag: added xc7k70tfbg676 variant 2025-09-24 16:48:02 +02:00
Gwenhael Goavec-Merou 8e6eb1085c spiOverJtag/build.py: simplify Kintex7 uses 2025-09-24 16:46:57 +02:00
Gwenhael Goavec-Merou 13cf0c59b9 xilinx: load_bridge: uses configBitstreamParser getFilename to print real name instead of theorical (with or without .gz) 2025-09-24 08:07:27 +02:00
Gwenhael Goavec-Merou 6935936a92 configBitstreamParser: added filename getter 2025-09-24 08:06:28 +02:00
Gwenhael Goavec-Merou 39b3ca5871 spiInterface: all methods: added a \n after command displayed (avoids unclear message when calee methods uses printxxx) 2025-09-24 08:06:06 +02:00
Gwenhael Goavec-Merou fdc9edc6cb spiOverJtag/xilinx_spiOverJtag.v: spartan3e: spi_drck -> drck 2025-09-22 10:18:24 +02:00
Gwenhael Goavec-Merou 29a5bc3515 spiOverJtag/xilinx_spiOverJtag.v: fixed code for virtex6 targets 2025-09-20 18:05:55 +02:00
Gwenhael Goavec-Merou 6df4bce1fd xilinx: allows Flash write for Xilinx Spartan3 targets 2025-09-20 17:31:32 +02:00
Gwenhael Goavec-Merou 1ccc2a0d5b spiOverJtag/xilinx_spiOverJtag.v: can't declare spi_clk for spartan3e device. Fixed sck assign for spartan3e 2025-09-20 17:30:10 +02:00
Gwenhael Goavec-Merou 5e67fee9f5 spiOverJtag/build.py: gzip file must be produces for all Xilinx devices 2025-09-17 20:16:03 +02:00
Gwenhael Goavec-Merou 06b4e2f143 spiOverJtag/xilinx_spiOverJtag.v: don't redeclares tdo for spartan3e 2025-09-17 11:55:52 +02:00
11 changed files with 198 additions and 67 deletions

View File

@ -308,6 +308,14 @@ Xilinx:
Memory: OK Memory: OK
Flash: OK (primary) Flash: OK (primary)
- Description: Kintex UltraScale+
Model:
- xcku3p
- xcku5p
URL: https://www.xilinx.com/products/silicon-devices/fpga/kintex-ultrascale-plus.html#productTable
Memory: OK
Flash: OK
- Description: Virtex 6 - Description: Virtex 6
Model: Model:
- xc6vlx130t - xc6vlx130t
@ -329,6 +337,13 @@ Xilinx:
Memory: OK Memory: OK
Flash: OK Flash: OK
- Description: Spartan UltraScale+
Model:
- xcsu35p
URL: https://www.amd.com/en/products/adaptive-socs-and-fpgas/fpga/spartan-ultrascale-plus.html#productTable
Memory: OK
Flash: TBD
- Description: Spartan 3 - Description: Spartan 3
Model: Model:
- xc3s200 - xc3s200

View File

@ -401,6 +401,13 @@
Memory: OK Memory: OK
Flash: NA Flash: NA
- ID: hyvision_opt01
Description: HyVision PCIe OPT01 rev.F
URL: NA
FPGA: Kintex7 xc7k70tfbg676
Memory: OK
Flash: OK
- ID: honeycomb - ID: honeycomb
Description: honeycomb Description: honeycomb
URL: https://github.com/Disasm/honeycomb-pcb URL: https://github.com/Disasm/honeycomb-pcb

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import re
from edalize.edatool import get_edatool from edalize.edatool import get_edatool
@ -15,6 +16,17 @@ packages = {
"xc7a100t" : ["csg324", "ftg256", "fgg484", "fgg676"], "xc7a100t" : ["csg324", "ftg256", "fgg484", "fgg676"],
"xc7a200t" : ["sbg484", "fbg484", "fbg676", "ffg1156"], "xc7a200t" : ["sbg484", "fbg484", "fbg676", "ffg1156"],
}, },
# Added but seems not possible to use same bitstream
# for all Kintex with the same size but different package.
"Kintex 7": {
"xc7k70t" : ["fbg484", "fbg676"],
"xc7k160t" : ["fbg484", "fbg676", "ffg676"],
"xc7k325t" : ["fbg676", "ffg676", "fbg900", "ffg900"],
"xc7k355t" : ["ffg901"],
"xc7k410t" : ["fbg676", "ffg676", "fbg900", "ffg900"],
"xc7k420t" : ["ffg901", "ffg1156"],
"xc7k480t" : ["ffg901", "ffg1156"],
},
"Spartan 7": { "Spartan 7": {
"xc7s6" : ["ftgb196", "cpga196", "csga225"], "xc7s6" : ["ftgb196", "cpga196", "csga225"],
"xc7s15" : ["ftgb196", "cpga196", "csga225"], "xc7s15" : ["ftgb196", "cpga196", "csga225"],
@ -43,6 +55,7 @@ currDir = os.path.abspath(os.path.curdir) + '/'
files = [] files = []
parameters = {} parameters = {}
pkg_name = None pkg_name = None
pkg = None
model = "" model = ""
subpart = part[0:4].lower() subpart = part[0:4].lower()
@ -78,6 +91,7 @@ elif subpart == "xc7k":
family = "Kintex7" family = "Kintex7"
tool = "ise" tool = "ise"
speed = -2 speed = -2
model = subpart
elif subpart == "xc7s": elif subpart == "xc7s":
family = "Spartan 7" family = "Spartan 7"
tool = "vivado" tool = "vivado"
@ -104,6 +118,12 @@ else:
if model in ["xc7a", "xc7s"]: if model in ["xc7a", "xc7s"]:
pkg = packages[family][part][0] pkg = packages[family][part][0]
pkg_name = f"{model}_{pkg}" pkg_name = f"{model}_{pkg}"
if model in ["xc7k"]:
m = re.match(r"(xc7k\d+t)(\w+)", part)
pkg = m.group(2)
pkg_name = f"{model}_{pkg}"
if tool == "ise":
model = m.group(1)
if tool in ["ise", "vivado"]: if tool in ["ise", "vivado"]:
pkg_name = { pkg_name = {
@ -120,12 +140,6 @@ if tool in ["ise", "vivado"]:
"xc6slx150tcsg484" : "xc6s_csg484", "xc6slx150tcsg484" : "xc6s_csg484",
"xc6slx150tfgg484" : "xc6s_t_fgg484", "xc6slx150tfgg484" : "xc6s_t_fgg484",
"xc6vlx130tff784" : "xc6v_ff784", "xc6vlx130tff784" : "xc6v_ff784",
"xc7k70tfbg484" : "xc7k_fbg484",
"xc7k70tfbg676" : "xc7k_fbg676",
"xc7k160tffg676" : "xc7k_ffg676",
"xc7k325tffg676" : "xc7k_ffg676",
"xc7k325tffg900" : "xc7k_ffg900",
"xc7k420tffg901" : "xc7k_ffg901",
"xc7vx330tffg1157" : "xc7v_ffg1157", "xc7vx330tffg1157" : "xc7v_ffg1157",
"xcku040-ffva1156" : "xcku040_ffva1156", "xcku040-ffva1156" : "xcku040_ffva1156",
"xcku060-ffva1156" : "xcku060_ffva1156", "xcku060-ffva1156" : "xcku060_ffva1156",
@ -152,10 +166,7 @@ if tool in ["ise", "vivado"]:
"xc6slx150tcsg484": "xc6slx150t", "xc6slx150tcsg484": "xc6slx150t",
"xc6slx150tfgg484": "xc6slx150t", "xc6slx150tfgg484": "xc6slx150t",
"xc6vlx130tff784": "xc6vlx130t", "xc6vlx130tff784": "xc6vlx130t",
"xc7k325tffg676": "xc7k325t", }.get(part, model),
"xc7k325tffg900": "xc7k325t",
"xc7k420tffg901": "xc7k420t",
}[part],
'package': { 'package': {
"xc3s500evq100": "vq100", "xc3s500evq100": "vq100",
"xc6slx9tqg144": "tqg144", "xc6slx9tqg144": "tqg144",
@ -170,10 +181,7 @@ if tool in ["ise", "vivado"]:
"xc6slx150tcsg484": "csg484", "xc6slx150tcsg484": "csg484",
"xc6slx150tfgg484": "fgg484", "xc6slx150tfgg484": "fgg484",
"xc6vlx130tff784": "ff784", "xc6vlx130tff784": "ff784",
"xc7k325tffg676": "ffg676", }.get(part, pkg),
"xc7k325tffg900": "ffg900",
"xc7k420tffg901": "ffg901",
}[part],
'speed' : speed 'speed' : speed
} }
else: else:
@ -254,7 +262,7 @@ backend = get_edatool(tool)(edam=edam, work_root=build_dir)
backend.configure() backend.configure()
backend.build() backend.build()
if tool == "vivado": if tool in ["vivado", "ise"]:
import shutil import shutil
import subprocess import subprocess
import gzip import gzip

Binary file not shown.

View File

@ -10,10 +10,14 @@ module spiOverJtag
`ifdef spartan3e `ifdef spartan3e
output wire sck, output wire sck,
`endif `endif
`ifdef virtex6
output wire sdi_dq0
`else
output wire sdi_dq0, output wire sdi_dq0,
input wire sdo_dq1, input wire sdo_dq1,
output wire wpn_dq2, output wire wpn_dq2,
output wire hldn_dq3 output wire hldn_dq3
`endif
`endif // xilinxultrascale `endif // xilinxultrascale
`ifdef secondaryflash `ifdef secondaryflash
@ -27,11 +31,12 @@ module spiOverJtag
wire capture, drck, sel, update, shift; wire capture, drck, sel, update, shift;
wire tdi, tdo; wire tdi, tdo;
wire spi_clk;
`ifndef spartan3e `ifndef spartan3e
`ifndef virtex6
/* Version Interface. */ /* Version Interface. */
wire ver_sel, ver_cap, ver_shift, ver_drck, ver_tdi, ver_tdo; wire ver_sel, ver_cap, ver_shift, ver_drck, ver_tdi, ver_tdo;
wire spi_clk;
spiOverJtag_core spiOverJtag_core_prim ( spiOverJtag_core spiOverJtag_core_prim (
/* JTAG state/controls */ /* JTAG state/controls */
@ -59,13 +64,14 @@ module spiOverJtag
.wpn_dq2(wpn_dq2), .wpn_dq2(wpn_dq2),
.hldn_dq3(hldn_dq3) .hldn_dq3(hldn_dq3)
); );
`endif `endif /* !virtex6 */
`endif /* !spartan3e */
`ifdef spartan6 `ifdef spartan6
assign sck = spi_clk; assign sck = spi_clk;
`else // !spartan6 `else // !spartan6
`ifdef spartan3e `ifdef spartan3e
assign sck = spi_clk; assign sck = drck;
`else // !spartan6 && !spartan3e `else // !spartan6 && !spartan3e
`ifdef xilinxultrascale `ifdef xilinxultrascale
assign sck = drck; assign sck = drck;
@ -100,7 +106,52 @@ module spiOverJtag
.USRDONEO (1'b1), // 1-bit input: User DONE pin output control. .USRDONEO (1'b1), // 1-bit input: User DONE pin output control.
.USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output. .USRDONETS(1'b1) // 1-bit input: User DONE 3-state enable output.
); );
`else // !spartan6 && !spartan3e && !xilinxultrascale `elsif virtex6 // !spartan6 && !spartan3e && !xilinxultrascale
wire di;
wire runtest;
reg fsm_csn;
// jtag -> spi flash
assign sdi_dq0 = tdi;
assign tdo = (sel) ? di : tdi;
assign csn = fsm_csn;
wire tmp_cap_s = capture && sel;
wire tmp_up_s = update && sel;
always @(posedge drck, posedge runtest) begin
if (runtest) begin
fsm_csn <= 1'b1;
end else begin
if (tmp_cap_s) begin
fsm_csn <= 1'b0;
end else if (tmp_up_s) begin
fsm_csn <= 1'b1;
end else begin
fsm_csn <= fsm_csn;
end
end
end
STARTUP_VIRTEX6 #(
.PROG_USR("FALSE")
) startup_virtex6_inst (
.CFGCLK(), // unused
.CFGMCLK(), // unused
.CLK(1'b0), // unused
.DINSPI(di), // data from SPI flash
.EOS(),
.GSR(1'b0), // unused
.GTS(1'b0), // unused
.KEYCLEARB(1'b0), // not used
.PACK(1'b1), // tied low for 'safe' operations
.PREQ(), // unused
.TCKSPI(), // echo of CCLK from TCK pin
.USRCCLKO (drck), // user FPGA -> CCLK pin
.USRCCLKTS(1'b0), // drive CCLK not in high-Z
.USRDONEO (1'b1), // why both USRDONE are high?
.USRDONETS(1'b1) // ??
);
`else // !spartan6 && !spartan3e && !xilinxultrascale && !virtex6
STARTUPE2 #( STARTUPE2 #(
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams. .PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation. .SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation.
@ -130,7 +181,7 @@ module spiOverJtag
assign hldn_dq3 = 1'b1; assign hldn_dq3 = 1'b1;
// jtag -> spi flash // jtag -> spi flash
assign sdi_dq0 = tdi; assign sdi_dq0 = tdi;
wire tdo = (sel) ? sdo_dq1 : tdi; assign tdo = (sel) ? sdo_dq1 : tdi;
assign csn = fsm_csn; assign csn = fsm_csn;
wire tmp_cap_s = capture && sel; wire tmp_cap_s = capture && sel;
@ -169,7 +220,9 @@ module spiOverJtag
.TDO2 () // 1-bit input: USER2 function .TDO2 () // 1-bit input: USER2 function
); );
`else `else
`ifdef spartan6 `ifdef virtex6
BSCAN_VIRTEX6 #(
`elsif spartan6
BSCAN_SPARTAN6 #( BSCAN_SPARTAN6 #(
`else `else
BSCANE2 #( BSCANE2 #(
@ -181,8 +234,12 @@ module spiOverJtag
// is asserted, DRCK toggles when // is asserted, DRCK toggles when
// CAPTURE or SHIFT are asserted. // CAPTURE or SHIFT are asserted.
.RESET (), // 1-bit output: Reset output for TAP controller. .RESET (), // 1-bit output: Reset output for TAP controller.
`ifdef virtex6
.RUNTEST(runtest),
`else
.RUNTEST(), // 1-bit output: Output asserted when TAP .RUNTEST(), // 1-bit output: Output asserted when TAP
// controller is in Run Test/Idle state. // controller is in Run Test/Idle state.
`endif
.SEL (sel), // 1-bit output: USER instruction active output. .SEL (sel), // 1-bit output: USER instruction active output.
.SHIFT (shift), // 1-bit output: SHIFT output from TAP controller. .SHIFT (shift), // 1-bit output: SHIFT output from TAP controller.
.TCK (), // 1-bit output: Test Clock output. .TCK (), // 1-bit output: Test Clock output.
@ -197,6 +254,7 @@ module spiOverJtag
); );
/* BSCAN for Version Interface. */ /* BSCAN for Version Interface. */
`ifndef virtex6
`ifdef spartan6 `ifdef spartan6
BSCAN_SPARTAN6 #( BSCAN_SPARTAN6 #(
`else `else
@ -217,6 +275,7 @@ module spiOverJtag
.TDO (ver_tdo) .TDO (ver_tdo)
); );
`endif `endif
`endif /* !virtex6 */
`ifdef secondaryflash `ifdef secondaryflash
wire drck_sec; wire drck_sec;

View File

@ -179,6 +179,7 @@ static std::map <std::string, target_board_t> board_list = {
JTAG_BOARD("genesys2", "xc7k325tffg900", "digilent_b", 0, 0, CABLE_DEFAULT), JTAG_BOARD("genesys2", "xc7k325tffg900", "digilent_b", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("gr740-mini", "", "ft4232hp_b", 0, 0, CABLE_MHZ(1)), JTAG_BOARD("gr740-mini", "", "ft4232hp_b", 0, 0, CABLE_MHZ(1)),
JTAG_BOARD("hseda-xc6slx16", "xc6slx16ftg256", "", 0, 0, CABLE_DEFAULT), JTAG_BOARD("hseda-xc6slx16", "xc6slx16ftg256", "", 0, 0, CABLE_DEFAULT),
JTAG_BOARD("hyvision_opt01", "xc7k70tfbg676", "", 0, 0, CABLE_DEFAULT),
/* most ice40 boards uses the same pinout */ /* most ice40 boards uses the same pinout */
SPI_BOARD("ice40_generic", "lattice", "ice40", "ft2232", SPI_BOARD("ice40_generic", "lattice", "ice40", "ft2232",
DBUS7, DBUS6, 0, DBUS7, DBUS6, 0,

View File

@ -23,6 +23,11 @@ class ConfigBitstreamParser {
const uint8_t *getData() const {return _bit_data.data();} const uint8_t *getData() const {return _bit_data.data();}
int getLength() {return _bit_length;} int getLength() {return _bit_length;}
/**
* \brief return bitstream file name
*/
std::string getFilename() const {return _filename;}
/** /**
* \brief display header informations * \brief display header informations
*/ */

View File

@ -125,6 +125,9 @@ static std::map <uint32_t, fpga_model> fpga_list = {
{0x04b31093, {"xilinx", "virtexusp", "xcvu9p", 18}}, {0x04b31093, {"xilinx", "virtexusp", "xcvu9p", 18}},
{0x14b79093, {"xilinx", "virtexusp", "xcvu37p", 18}}, {0x14b79093, {"xilinx", "virtexusp", "xcvu37p", 18}},
/* Xilinx Ultrascale+ / Spartan */
{0x04e80093, {"xilinx", "spartanusp", "xcsu35p", 6}},
/* Xilinx Ultrascale+ / ZynqMP */ /* Xilinx Ultrascale+ / ZynqMP */
/* When powering a zynq ultrascale+ MPSoC, PL Tap and ARM dap /* When powering a zynq ultrascale+ MPSoC, PL Tap and ARM dap
* are disabled and only PS tap with a specific IDCODE is seen. * are disabled and only PS tap with a specific IDCODE is seen.
@ -301,6 +304,7 @@ static std::map <uint32_t, fpga_model> fpga_list = {
/* Lattice ECP3 */ /* Lattice ECP3 */
{0x01014043, {"lattice", "ECP3", "LFE3-70E", 8}}, {0x01014043, {"lattice", "ECP3", "LFE3-70E", 8}},
{0x01015043, {"lattice", "ECP3", "LFE3-150EA", 8}},
/* Lattice ECP5 */ /* Lattice ECP5 */
{0x21111043, {"lattice", "ECP5", "LFE5U-12", 8}}, {0x21111043, {"lattice", "ECP5", "LFE5U-12", 8}},

View File

@ -26,7 +26,8 @@ SPIInterface::SPIInterface(const std::string &filename, int8_t verbose,
bool SPIInterface::detect_flash() bool SPIInterface::detect_flash()
{ {
bool ret = true; bool ret = true;
printInfo("protect_flash: ", false);
printInfo("Detect flash:");
/* move device to spi access */ /* move device to spi access */
if (!prepare_flash_access()) { if (!prepare_flash_access()) {
@ -55,7 +56,7 @@ bool SPIInterface::detect_flash()
bool SPIInterface::protect_flash(uint32_t len) bool SPIInterface::protect_flash(uint32_t len)
{ {
bool ret = true; bool ret = true;
printInfo("protect_flash: ", false); printInfo("protect_flash:");
/* move device to spi access */ /* move device to spi access */
if (!prepare_flash_access()) { if (!prepare_flash_access()) {
@ -98,7 +99,7 @@ bool SPIInterface::unprotect_flash()
SPIFlash flash(this, false, _spif_verbose); SPIFlash flash(this, false, _spif_verbose);
/* configure flash protection */ /* configure flash protection */
printInfo("unprotect_flash: ", false); printInfo("unprotect_flash:");
ret = (flash.disable_protection() == 0); ret = (flash.disable_protection() == 0);
if (!ret) if (!ret)
printError("Fail"); printError("Fail");
@ -129,7 +130,7 @@ bool SPIInterface::set_quad_bit(bool set_quad)
SPIFlash flash(this, false, _spif_verbose); SPIFlash flash(this, false, _spif_verbose);
/* configure flash protection */ /* configure flash protection */
printInfo("set_quad_bit: ", false); printInfo("set_quad_bit:");
ret = flash.set_quad_bit(set_quad); ret = flash.set_quad_bit(set_quad);
if (!ret) if (!ret)
printError("Fail"); printError("Fail");
@ -148,7 +149,7 @@ bool SPIInterface::set_quad_bit(bool set_quad)
bool SPIInterface::bulk_erase_flash() bool SPIInterface::bulk_erase_flash()
{ {
bool ret = true; bool ret = true;
printInfo("bulk_erase: ", false); printInfo("bulk_erase:");
/* move device to spi access */ /* move device to spi access */
if (!prepare_flash_access()) { if (!prepare_flash_access()) {

View File

@ -150,6 +150,7 @@ static std::map<std::string, std::map<std::string, std::vector<uint8_t>>>
{ "JSHUTDOWN", {0x0D} }, { "JSHUTDOWN", {0x0D} },
{ "ISC_PROGRAM", {0x11} }, { "ISC_PROGRAM", {0x11} },
{ "ISC_DISABLE", {0x16} }, { "ISC_DISABLE", {0x16} },
{ "STATUS", {0x1F} },
{ "BYPASS", {0xff} }, { "BYPASS", {0xff} },
} }
}, },
@ -294,6 +295,8 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_mode = Device::SPI_MODE; _mode = Device::SPI_MODE;
} else if (_file_extension == "jed") { } else if (_file_extension == "jed") {
_mode = Device::FLASH_MODE; _mode = Device::FLASH_MODE;
} else if (_file_extension == "pdi") {
_mode = Device::MEM_MODE;
} else { } else {
_mode = Device::SPI_MODE; _mode = Device::SPI_MODE;
} }
@ -358,6 +361,14 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_fpga_family = KINTEXUSP_FAMILY; _fpga_family = KINTEXUSP_FAMILY;
} else if (family == "artixusp") { } else if (family == "artixusp") {
_fpga_family = ARTIXUSP_FAMILY; _fpga_family = ARTIXUSP_FAMILY;
} else if (family == "spartanusp") {
if (_file_extension != "pdi") {
char mess[256];
snprintf(mess, 256, "Error: only volatile PDI programing for "
"Spartan Ultrascale+ devices\n");
throw std::runtime_error(mess);
}
_fpga_family = SPARTANUSP_FAMILY;
} else if (family == "virtexus") { } else if (family == "virtexus") {
_fpga_family = VIRTEXUS_FAMILY; _fpga_family = VIRTEXUS_FAMILY;
} else if (family == "virtexusp") { } else if (family == "virtexusp") {
@ -365,9 +376,6 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_ircode_map = ircode_mapping.at("virtexusp"); _ircode_map = ircode_mapping.at("virtexusp");
} else if (family.substr(0, 8) == "spartan3") { } else if (family.substr(0, 8) == "spartan3") {
_fpga_family = SPARTAN3_FAMILY; _fpga_family = SPARTAN3_FAMILY;
if (_mode != Device::MEM_MODE) {
throw std::runtime_error("Error: Only load to mem is supported");
}
} else if (family == "xcf") { } else if (family == "xcf") {
_fpga_family = XCF_FAMILY; _fpga_family = XCF_FAMILY;
if (_mode == Device::MEM_MODE) { if (_mode == Device::MEM_MODE) {
@ -612,6 +620,9 @@ void Xilinx::program(unsigned int offset, bool unprotect_flash)
if (_mode == Device::MEM_MODE || _fpga_family == XCF_FAMILY) if (_mode == Device::MEM_MODE || _fpga_family == XCF_FAMILY)
reverse = true; reverse = true;
if (_file_extension == "pdi")
reverse = false;
try { try {
if (_flash_chips & PRIMARY_FLASH) { if (_flash_chips & PRIMARY_FLASH) {
open_bitfile(_filename, _file_extension, &bit, reverse, _verbose); open_bitfile(_filename, _file_extension, &bit, reverse, _verbose);
@ -715,11 +726,11 @@ bool Xilinx::load_bridge()
bitname = PathHelper::absolutePath(bitname); bitname = PathHelper::absolutePath(bitname);
#endif #endif
std::cout << "use: " << bitname << std::endl;
/* first: load spi over jtag */ /* first: load spi over jtag */
try { try {
BitParser bridge(bitname, true, _verbose); BitParser bridge(bitname, true, _verbose);
printSuccess("Use: " + bridge.getFilename());
bridge.parse(); bridge.parse();
if (_fpga_family == SPARTAN3_FAMILY) if (_fpga_family == SPARTAN3_FAMILY)
xc3s_flow_program(&bridge); xc3s_flow_program(&bridge);
@ -852,6 +863,24 @@ void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
* 16: Move into RTI state. X 0 1 * 16: Move into RTI state. X 0 1
*/ */
_jtag->set_state(Jtag::RUN_TEST_IDLE); _jtag->set_state(Jtag::RUN_TEST_IDLE);
if (_file_extension == "pdi") {
_jtag->toggleClk(2000);
/*
* 17: For PDI devices, use the STATUS instruction
* to verify successful configuration.
*/
unsigned char tx_data[6]= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char rx_data[6];
_jtag->shiftIR(get_ircode(_ircode_map, "STATUS"), NULL, _irlen);
_jtag->shiftDR(tx_data, rx_data, 48);
if ((rx_data[4] & 0x04) != 0x04) {
printError("PDI programing failed");
} else {
printSuccess("PDI programing success");
}
}
else {
/* /*
* 17: Enter the SELECT-IR state. X 1 2 * 17: Enter the SELECT-IR state. X 1 2
* 18: Move to the SHIFT-IR state. X 0 2 * 18: Move to the SHIFT-IR state. X 0 2
@ -888,6 +917,7 @@ void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
if (!done) { if (!done) {
read_register("STAT"); read_register("STAT");
} }
}
} }
static uint32_t char_array_to_word(uint8_t *in) static uint32_t char_array_to_word(uint8_t *in)

View File

@ -198,6 +198,7 @@ class Xilinx: public Device, SPIInterface {
ZYNQMP_FAMILY, ZYNQMP_FAMILY,
XCF_FAMILY, XCF_FAMILY,
ARTIXUSP_FAMILY, ARTIXUSP_FAMILY,
SPARTANUSP_FAMILY,
VIRTEXUS_FAMILY, VIRTEXUS_FAMILY,
VIRTEXUSP_FAMILY, VIRTEXUSP_FAMILY,
UNKNOWN_FAMILY = 999 UNKNOWN_FAMILY = 999