modules/fpga/ holds an fpga_target struct (IDCODE/mask, family, IR length and private opcodes, proxy bitstream path, quirks) and a compile-time registry. Initial entry: Xilinx Kintex UltraScale+ XCKU15P, populated from bsdl_files/xcku15p_ffve1517.bsd (IDCODE 0x04A56093, IR 6, USER1=0x02, CFG_IN=0x05, JPROGRAM=0x0B, JSTART=0x0C, JSHUTDOWN=0x0D, ISC_DISABLE=0x16, quirk CCLK_VIA_STARTUP). Two new script commands: - fpga_list: enumerate the registry - fpga_info: match each device on the JTAG chain against the registry and surface known quirks Adding another FPGA = one entry in fpga_registry[] + its .bsd in bsdl_files/. Proxy .bit will be wired in phase 2.5 (bscan_spi/). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
65 lines
1.8 KiB
C
65 lines
1.8 KiB
C
#include <stddef.h>
|
|
|
|
#include "fpga.h"
|
|
|
|
static const fpga_target fpga_registry[] = {
|
|
/* Xilinx Kintex UltraScale+ XCKU15P
|
|
* IDCODE_REGISTER and INSTRUCTION_OPCODE values come from
|
|
* bsdl_files/xcku15p_ffve1517.bsd
|
|
* IR length 6 bits, version nibble (bits 31:28) ignored. */
|
|
{
|
|
.name = "Xilinx Kintex UltraScale+ XCKU15P",
|
|
.idcode = 0x04A56093,
|
|
.idcode_mask = 0x0FFFFFFF,
|
|
.family = FPGA_FAMILY_XILINX_USP,
|
|
.bsdl_filename = "xcku15p_ffve1517.bsd",
|
|
.ir_length = 6,
|
|
.ir_cfg_in = 0x05,
|
|
.ir_user1 = 0x02,
|
|
.ir_jprogram = 0x0B,
|
|
.ir_jstart = 0x0C,
|
|
.ir_jshutdown = 0x0D,
|
|
.ir_isc_disable = 0x16,
|
|
.proxy_bitstream = NULL, /* TODO Phase 2.5: bscan_spi_xcku15p.bit */
|
|
.quirks = FPGA_QUIRK_CCLK_VIA_STARTUP,
|
|
},
|
|
};
|
|
|
|
#define FPGA_REGISTRY_LEN ((int)(sizeof(fpga_registry) / sizeof(fpga_registry[0])))
|
|
|
|
int fpga_get_target_count(void)
|
|
{
|
|
return FPGA_REGISTRY_LEN;
|
|
}
|
|
|
|
const fpga_target *fpga_get_target_by_index(int index)
|
|
{
|
|
if (index < 0 || index >= FPGA_REGISTRY_LEN) {
|
|
return NULL;
|
|
}
|
|
return &fpga_registry[index];
|
|
}
|
|
|
|
const fpga_target *fpga_lookup_by_idcode(unsigned long idcode)
|
|
{
|
|
int i;
|
|
for (i = 0; i < FPGA_REGISTRY_LEN; i++) {
|
|
const fpga_target *t = &fpga_registry[i];
|
|
if ((idcode & t->idcode_mask) == (t->idcode & t->idcode_mask)) {
|
|
return t;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const char *fpga_family_name(fpga_family f)
|
|
{
|
|
switch (f) {
|
|
case FPGA_FAMILY_XILINX_7: return "Xilinx 7-Series";
|
|
case FPGA_FAMILY_XILINX_US: return "Xilinx UltraScale";
|
|
case FPGA_FAMILY_XILINX_USP: return "Xilinx UltraScale+";
|
|
case FPGA_FAMILY_UNKNOWN:
|
|
default: return "Unknown";
|
|
}
|
|
}
|