basic PDI prog for Spartan Ultrascale+

This commit is contained in:
Andrew E Wilson 2025-10-13 23:14:26 -06:00 committed by Gwenhael Goavec-Merou
parent 03be134cdd
commit 648a4a833a
4 changed files with 79 additions and 35 deletions

View File

@ -329,6 +329,13 @@ Xilinx:
Memory: 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
Model:
- xc3s200

View File

@ -125,6 +125,9 @@ static std::map <uint32_t, fpga_model> fpga_list = {
{0x04b31093, {"xilinx", "virtexusp", "xcvu9p", 18}},
{0x14b79093, {"xilinx", "virtexusp", "xcvu37p", 18}},
/* Xilinx Ultrascale+ / Spartan */
{0x04e80093, {"xilinx", "spartanusp", "xcsu35p", 6}},
/* Xilinx Ultrascale+ / ZynqMP */
/* When powering a zynq ultrascale+ MPSoC, PL Tap and ARM dap
* are disabled and only PS tap with a specific IDCODE is seen.

View File

@ -150,6 +150,7 @@ static std::map<std::string, std::map<std::string, std::vector<uint8_t>>>
{ "JSHUTDOWN", {0x0D} },
{ "ISC_PROGRAM", {0x11} },
{ "ISC_DISABLE", {0x16} },
{ "STATUS", {0x1F} },
{ "BYPASS", {0xff} },
}
},
@ -294,6 +295,8 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_mode = Device::SPI_MODE;
} else if (_file_extension == "jed") {
_mode = Device::FLASH_MODE;
} else if (_file_extension == "pdi") {
_mode = Device::MEM_MODE;
} else {
_mode = Device::SPI_MODE;
}
@ -358,6 +361,14 @@ Xilinx::Xilinx(Jtag *jtag, const std::string &filename,
_fpga_family = KINTEXUSP_FAMILY;
} else if (family == "artixusp") {
_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") {
_fpga_family = VIRTEXUS_FAMILY;
} else if (family == "virtexusp") {
@ -609,6 +620,9 @@ void Xilinx::program(unsigned int offset, bool unprotect_flash)
if (_mode == Device::MEM_MODE || _fpga_family == XCF_FAMILY)
reverse = true;
if (_file_extension == "pdi")
reverse = false;
try {
if (_flash_chips & PRIMARY_FLASH) {
open_bitfile(_filename, _file_extension, &bit, reverse, _verbose);
@ -849,6 +863,24 @@ void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
* 16: Move into RTI state. X 0 1
*/
_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
* 18: Move to the SHIFT-IR state. X 0 2
@ -886,6 +918,7 @@ void Xilinx::program_mem(ConfigBitstreamParser *bitfile)
read_register("STAT");
}
}
}
static uint32_t char_array_to_word(uint8_t *in)
{

View File

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