From 5733ca29c3a56c4cecfc98a020a194b388760d62 Mon Sep 17 00:00:00 2001 From: Giovanni Bruni Date: Wed, 11 Oct 2023 09:52:45 +0200 Subject: [PATCH] fix lattice programming and add nexus boards Fix to lattice programming: we considered a svf file generated by Lattice Radiant-Programmer and compared it with the current way lattice devices were programmed. There were few differences dealing with configuration reset and REFRESH. These fixes allow us to program an fpga when it is in a state of error (e.g. there's no bitstream in the SPI Flash). Lattice parts added: - CertusPro FPGA Nexus boards added: - Certus Versa Evaluation board - CertusPro Evaluation board - CertusPro Versa Evaluation board --- src/board.hpp | 5 ++++- src/lattice.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- src/part.hpp | 3 +++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/board.hpp b/src/board.hpp index 6a1e4d4..33de882 100644 --- a/src/board.hpp +++ b/src/board.hpp @@ -126,7 +126,10 @@ static std::map board_list = { JTAG_BOARD("colorlight-i5", "", "cmsisdap", 0, 0, CABLE_DEFAULT), JTAG_BOARD("colorlight-i9", "", "cmsisdap", 0, 0, CABLE_DEFAULT), JTAG_BOARD("colorlight-i9+", "xc7a50tfgg484", "", 0, 0, CABLE_DEFAULT), - JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("crosslinknx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certusnx_versa_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certuspronx_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), + JTAG_BOARD("certuspronx_versa_evn", "", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("cyc1000", "10cl025256", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("c10lp-refkit", "10cl055484", "ft2232", 0, 0, CABLE_DEFAULT), JTAG_BOARD("de0", "", "usb-blaster",0, 0, CABLE_DEFAULT), diff --git a/src/lattice.cpp b/src/lattice.cpp index c4a5570..ac86553 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -28,7 +28,7 @@ using namespace std; #define ISC_ENABLE 0xC6 /* ISC_ENABLE - Offline Mode */ # define ISC_ENABLE_FLASH_MODE (1 << 3) # define ISC_ENABLE_SRAM_MODE (0 << 3) -#define ISC_ENABLE_TRANSPARANT 0x74 /* This command is used to put the device in transparent mode */ +#define ISC_ENABLE_TRANSPARENT 0x74 /* ISC_ENABLE_X This command is used to put the device in transparent mode */ #define ISC_DISABLE 0x26 /* ISC_DISABLE */ #define READ_DEVICE_ID_CODE 0xE0 /* IDCODE_PUB */ #define FLASH_ERASE 0x0E /* ISC_ERASE */ @@ -133,6 +133,7 @@ using namespace std; #define PROG_ECDSA_PUBKEY3 0x63 /* This command is used to program the fourth 128 bits of the ECDSA Public Key. */ #define READ_ECDSA_PUBKEY3 0x64 /* This command is used to read the fourth 128 bits of the ECDSA Public Key. */ #define ISC_NOOP 0xff /* This command is no operation command (NOOP) or null operation. */ +#define LSC_DEVICE_CONTROL 0x7D /* Multiple commands. Bit 3: configuration reset */ #define PUBKEY_LENGTH_BYTES 64 /* length of the public key (MachXO3D) in bytes */ @@ -204,6 +205,8 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type, _fpga_family = NEXUS_FAMILY; } else if (family == "CertusNX") { _fpga_family = NEXUS_FAMILY; + } else if (family == "CertusProNX") { + _fpga_family = NEXUS_FAMILY; } else { printError("Unknown device family"); throw std::exception(); @@ -303,7 +306,17 @@ bool Lattice::program_mem() memset(tx_buf, 0xff, 26); wr_rd(0x1C, tx_buf, 26, NULL, 0); - wr_rd(0xFf, NULL, 0, NULL, 0); + /* SRAM TRANSPARENT mode ISC_ENABLE_X 0x74 */ + uint8_t tx_tmp[1] = {0x00}; + // wr_rd(ISC_ENABLE_TRANSPARENT, tx_tmp, 1, NULL, 0); + // _jtag->set_state(Jtag::RUN_TEST_IDLE); + // _jtag->toggleClk(1000); + + /* LSC_REFRESH 0x79 -- "Equivalent to toggle PROGRAMN pin" */ + wr_rd(REFRESH, NULL, 0, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + sleep(5); /* ISC Enable 0xC6 */ printInfo("Enable configuration: ", false); @@ -315,6 +328,25 @@ bool Lattice::program_mem() printSuccess("DONE"); } + /* LSC_DEVICE_CONTROL 0x7D -- configuration reset */ + tx_tmp[0] = 0x08; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } + + tx_tmp[0] = 0x00; + wr_rd(LSC_DEVICE_CONTROL, tx_tmp, 1, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + if(!pollBusyFlag()) { + printError("FAIL"); + return false; + } + /* ISC ERASE */ printInfo("SRAM erase: ", false); if (flashErase(FLASH_ERASE_SRAM) == false) { @@ -356,6 +388,9 @@ bool Lattice::program_mem() _jtag->shiftDR(tmp, NULL, size*8, next_state); } + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(1000); + uint32_t status_mask; if (_fpga_family == MACHXO3D_FAMILY) status_mask = REG_STATUS_MACHXO3D_CNF_CHK_MASK; @@ -1307,7 +1342,7 @@ uint16_t Lattice::getUFMStartPageFromJEDEC(JedParser *_jed, int id) addres. TODO: In any case, JEDEC files don't carry part information. Verify against IDCODE read previously? */ - + if(raw_page_offset > 9211) { return raw_page_offset - 9211 - 1; // 7000 } else if(raw_page_offset > 5758) { diff --git a/src/part.hpp b/src/part.hpp index 0c45448..34e20c7 100644 --- a/src/part.hpp +++ b/src/part.hpp @@ -212,6 +212,9 @@ static std::map fpga_list = { {0x310F0043, {"lattice", "CertusNX", "LFD2NX-17", 8}}, {0x310F1043, {"lattice", "CertusNX", "LFD2NX-40", 8}}, + /* Lattice CertusPro-NX */ + {0x010F4043, {"lattice", "CertusProNX", "LFCPNX-100", 8}}, + /**************************************************************************/ /* Gowin */ /**************************************************************************/