This is an automated email from Gerrit.

"Daniel Anselmi <danse...@gmx.ch>" just uploaded a new patch set to Gerrit, 
which you can find at https://review.openocd.org/c/openocd/+/7368

-- gerrit

commit 7c9832aed407eee8acf1427fbe45f94da7ee05cb
Author: Daniel Anselmi <danse...@gmx.ch>
Date:   Fri Oct 14 00:57:12 2022 +0200

    pld: add support for gowin devices
    
    Change-Id: Idd1a09514bbbbe0a7b54d69010f6c2f91215fd1d
    Signed-off-by: Daniel Anselmi <danse...@gmx.ch>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 1a2b4cbb5a..f1081d51fc 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -8606,6 +8606,16 @@ With a value of -1 for @var{pos} the check will be 
omitted.
 @end deffn
 @end deffn
 
+@deffn {FPGA Driver} {gowin}
+This driver can be used to load the bitstream into FPGAs form Gowin.
+It is possible to program the SRAM. Programming the flash is not supported.
+
+@example
+openocd -f board/gowin_runber.cfg  -c "init" \
+       -c "pld load 0 impl/pnr/gw1n_blinker.fs"
+@end example
+@end deffn
+
 
 @node General Commands
 @chapter General Commands
diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am
index a42ed827d3..9bd1cf7f42 100644
--- a/src/pld/Makefile.am
+++ b/src/pld/Makefile.am
@@ -13,6 +13,7 @@ noinst_LTLIBRARIES += %D%/libpld.la
        %D%/certus.c \
        %D%/efinix.c \
        %D%/intel.c \
+       %D%/gowin.c \
        %D%/pld.h \
        %D%/xilinx_bit.h \
        %D%/virtex2.h \
diff --git a/src/pld/gowin.c b/src/pld/gowin.c
new file mode 100644
index 0000000000..4b140f7563
--- /dev/null
+++ b/src/pld/gowin.c
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   Copyright (C) 2022 by Daniel Anselmi                                  *
+ *   danse...@gmx.ch                                                       *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/jtag.h>
+#include <jtag/adapter.h>
+#include <sys/stat.h>
+#include "pld.h"
+
+#define NO_OP                       0x02
+#define ERASE_SRAM                  0x05
+#define SRAM_ERASE_DONE             0x09
+#define IDCODE                      0x11
+#define ADDRESS_INITIALIZATION      0x12
+#define READ_USERCODE               0x13
+#define CONFIG_ENABLE               0x15
+#define TRANSFER_CONFIGURATION_DATA 0x17
+#define CONFIG_DISABLE              0x3A
+#define RELOAD                      0x3C
+#define STATUS_REGISTER             0x41
+#define ERASE_FLASH                 0x75
+#define ENABLE_2ND_FLASH            0x78
+
+#define STAUS_MASK_MEMORY_ERASE        (0x00000001 <<  5)
+#define STAUS_MASK_SYSTEM_EDIT_MODE    (0x00000001 <<  7)
+
+#define GW1N  1 /* GW1N(R)-1/2/4 */
+#define GW1NS 2 /* GW1NS-2 and GW1NS(R)-2C */
+#define GW1NZ 3 /* GW1N(R)-6/9 and GW1NZ-1 */
+#define GW2A  4 /* GW2A-18/55 */
+
+struct gowin_pld_device {
+       struct jtag_tap *tap;
+};
+
+struct gowin_bit_file {
+       size_t length;
+       size_t capacity;
+       uint8_t *data;
+       uint32_t id;
+       uint16_t stored_checksum;
+       int compressed;
+       int crc_en;
+       uint16_t checksum;
+       uint8_t replace8x;
+       uint8_t replace4x;
+       uint8_t replace2x;
+};
+
+static int gowin_read_bin_file(struct gowin_bit_file *bit_file,
+                                                       const char *filename)
+{
+       FILE *input_file = fopen(filename, "rb");
+
+       if (!input_file) {
+               LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       fseek(input_file, 0, SEEK_END);
+       long length = ftell(input_file);
+       fseek(input_file, 0, SEEK_SET);
+
+       if (length < 0) {
+               fclose(input_file);
+               LOG_ERROR("Failed to get length from file %s: %s", filename, 
strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       bit_file->length = (uint32_t)length;
+
+       bit_file->data = (uint8_t *)malloc(bit_file->length);
+       if (!bit_file->data) {
+               fclose(input_file);
+               LOG_ERROR("Unable to allocate memory for the bitstream");
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       long read_count = fread(bit_file->data, sizeof(char), bit_file->length, 
input_file);
+       fclose(input_file);
+       if (read_count != (long)bit_file->length)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+
+       return ERROR_OK;
+}
+
+static uint64_t gowin_read_fs_file_bitsequence(const char *bits, int length)
+{
+       uint64_t res = 0;
+       for (int i = 0; i < length; i++)
+               res = (res << 1) | (*bits++ == '1' ? 1 : 0);
+       return res;
+}
+
+static int gowin_add_byte_to_bit_file(struct gowin_bit_file *bit_file, uint8_t 
byte)
+{
+       if (bit_file->length + 1 > bit_file->capacity) {
+               uint8_t *buffer;
+               if (bit_file->data)
+                       buffer = realloc(bit_file->data, bit_file->capacity + 
8192);
+               else
+                       buffer = malloc(8192);
+               if (!buffer)
+                       return ERROR_FAIL;
+               bit_file->data = buffer;
+               bit_file->capacity += 8192;
+       }
+
+       bit_file->data[bit_file->length++] = byte;
+
+       return ERROR_OK;
+}
+
+static int gowin_read_fs_file_header(struct gowin_bit_file *bit_file, FILE 
*stream)
+{
+       if (!bit_file)
+               return ERROR_FAIL;
+
+       int end_of_header = 0;
+       while (!end_of_header) {
+               char buffer[256];
+               char *line = fgets(buffer, 256, stream);
+               if (!line || feof(stream) || ferror(stream))
+                       return ERROR_FAIL;
+
+               if (line[0] == '/')
+                       continue;
+
+               size_t line_length = strlen(line);
+               if (line[line_length - 1] != '\n')
+                       return ERROR_FAIL;
+               line_length--;
+
+               for (unsigned int i = 0; i < line_length; i += 8) {
+                       uint8_t byte = gowin_read_fs_file_bitsequence(line + i, 
8);
+                       int retval = gowin_add_byte_to_bit_file(bit_file, byte);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+
+               uint8_t key = gowin_read_fs_file_bitsequence(line, 8);
+               line += 8;
+               uint64_t value = gowin_read_fs_file_bitsequence(line, 
line_length - 8);
+
+               if (key == 0x06) {
+                       bit_file->id = value & 0xffffffff;
+               } else if (key == 0x3B) {
+                       end_of_header = 1;
+                       bit_file->crc_en = (value & (0x1 << 23)) ? 1 : 0;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int gowin_read_fs_file(struct gowin_bit_file *bit_file,
+                                                       const char *filename)
+{
+       FILE *input_file = fopen(filename, "r");
+
+       if (!input_file) {
+               LOG_ERROR("Couldn't open %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       int retval = gowin_read_fs_file_header(bit_file, input_file);
+       if (retval != ERROR_OK) {
+               free(bit_file->data);
+               return retval;
+       }
+
+       char digits_buffer[9]; /* 8 + 1 trailing zero */
+       do {
+               char *digits = fgets(digits_buffer, 9, input_file);
+               if (feof(input_file))
+                       break;
+               if (!digits || ferror(input_file)) {
+                       free(bit_file->data);
+                       return ERROR_FAIL;
+               }
+               if (digits[0] == '\n')
+                       continue;
+
+               if (strlen(digits) != 8) {
+                       free(bit_file->data);
+                       return ERROR_FAIL;
+               }
+               uint8_t byte = gowin_read_fs_file_bitsequence(digits, 8);
+               retval = gowin_add_byte_to_bit_file(bit_file, byte);
+               if (retval != ERROR_OK) {
+                       free(bit_file->data);
+                       return ERROR_FAIL;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+static int gowin_read_file(struct gowin_bit_file *bit_file,
+                                               const char *filename, bool 
*is_fs)
+{
+       memset(bit_file, 0, sizeof(struct gowin_bit_file));
+
+       if (!filename || !bit_file)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       struct stat input_stat;
+       if (stat(filename, &input_stat) == -1) {
+               LOG_ERROR("couldn't stat() %s: %s", filename,
+                                       strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if (S_ISDIR(input_stat.st_mode)) {
+               LOG_ERROR("%s is a directory", filename);
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if (input_stat.st_size == 0) {
+               LOG_ERROR("Empty file %s", filename);
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       /* check if binary .bin or ascii .bit/.hex */
+       const char *file_suffix_pos = strrchr(filename, '.');
+       if (!file_suffix_pos) {
+               LOG_ERROR("Unable to detect filename suffix");
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if (strcasecmp(file_suffix_pos, ".bin") == 0) {
+               *is_fs = false;
+               return gowin_read_bin_file(bit_file, filename);
+       } else if (strcasecmp(file_suffix_pos, ".fs") == 0) {
+               *is_fs = true;
+               return gowin_read_fs_file(bit_file, filename);
+       }
+
+       LOG_ERROR("Filetype not supported");
+       return ERROR_PLD_FILE_LOAD_FAILED;
+}
+
+static void gowin_set_instr(struct jtag_tap *tap,
+                                               uint32_t new_instr)
+{
+       struct scan_field field;
+
+       field.num_bits = tap->ir_length;
+
+       void *t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1);
+       field.out_value = t;
+       buf_set_u32(t, 0, field.num_bits, new_instr);
+       field.in_value = NULL;
+
+       jtag_add_ir_scan(tap, &field, TAP_IDLE);
+       jtag_add_runtest(3, TAP_IDLE);
+
+       free(t);
+}
+
+static int gowin_read_register(struct jtag_tap *tap, uint32_t reg, uint32_t 
*result)
+{
+       struct scan_field field;
+
+       gowin_set_instr(tap, reg);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       field.check_mask = NULL;
+       field.check_value = NULL;
+       field.num_bits = 32;
+       field.out_value = (uint8_t *)result;
+       field.in_value = (uint8_t *)result;
+
+       jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
+       return jtag_execute_queue();
+}
+
+static int gowin_check_status_flag(struct jtag_tap *tap, uint32_t mask, 
uint32_t flag)
+{
+       uint32_t status = 0;
+
+       int retries = 0;
+       do {
+               int retval = gowin_read_register(tap, STATUS_REGISTER, &status);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (retries++ == 100000)
+                       return ERROR_FAIL;
+       } while ((status & mask) != flag);
+
+       return ERROR_OK;
+}
+
+static int gowin_enable_config(struct jtag_tap *tap)
+{
+       gowin_set_instr(tap, CONFIG_ENABLE);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE,
+                                                               
STAUS_MASK_SYSTEM_EDIT_MODE);
+}
+
+static int gowin_disable_config(struct jtag_tap *tap)
+{
+       gowin_set_instr(tap, CONFIG_DISABLE);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       return gowin_check_status_flag(tap, STAUS_MASK_SYSTEM_EDIT_MODE,
+                                                               0);
+}
+
+static int gowin_reload(struct jtag_tap *tap)
+{
+       gowin_set_instr(tap, RELOAD);
+       gowin_set_instr(tap, NO_OP);
+       return jtag_execute_queue();
+}
+
+static int gowin_runtest_idle(struct jtag_tap *tap, unsigned int frac_sec)
+{
+       int speed = adapter_get_speed_khz() * 1000;
+       int cycles = DIV_ROUND_UP(speed, frac_sec);
+       jtag_add_runtest(cycles, TAP_IDLE);
+       return jtag_execute_queue();
+}
+
+static int gowin_erase_sram(struct jtag_tap *tap, bool tx_erase_done)
+{
+       /* config is already enabled */
+       gowin_set_instr(tap, ERASE_SRAM);
+       gowin_set_instr(tap, NO_OP);
+
+       /* Delay or Run Test 2~10ms */
+       /* 10 ms is worst case for GW2A-55 */
+       jtag_add_sleep(10000);
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = gowin_check_status_flag(tap, STAUS_MASK_MEMORY_ERASE,
+                                                                       
STAUS_MASK_MEMORY_ERASE);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (tx_erase_done) {
+               gowin_set_instr(tap, SRAM_ERASE_DONE);
+               gowin_set_instr(tap, NO_OP);
+               retval = jtag_execute_queue();
+               if (retval != ERROR_OK)
+                       return retval;
+               /* gen clock cycles in RUN/IDLE for 500us -> 1/500us = 2000/s */
+               retval = gowin_runtest_idle(tap, 2000);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       gowin_set_instr(tap, NO_OP);
+       return jtag_execute_queue();
+}
+
+static int gowin_load_to_sram(struct pld_device *pld_device, const char 
*filename)
+{
+       if (!pld_device)
+               return ERROR_FAIL;
+
+       struct gowin_pld_device *gowin_info = pld_device->driver_priv;
+
+       if (!gowin_info || !gowin_info->tap)
+               return ERROR_FAIL;
+       struct jtag_tap *tap = gowin_info->tap;
+
+       bool is_fs = false;
+       struct gowin_bit_file bit_file;
+       int retval = gowin_read_file(&bit_file, filename, &is_fs);
+       if (retval != ERROR_OK)
+               return retval;
+
+       for (unsigned int i = 0; i < bit_file.length; i++)
+               bit_file.data[i] = flip_u32(bit_file.data[i], 8);
+
+       uint32_t id;
+       retval = gowin_read_register(tap, IDCODE, &id);
+       if (retval != ERROR_OK) {
+               free(bit_file.data);
+               return retval;
+       }
+
+       if (is_fs && id != bit_file.id) {
+               free(bit_file.data);
+               LOG_ERROR("id in file: 0x%8.8" PRIx32 " and id on device: 
0x%8.8" PRIx32 "", bit_file.id, id);
+               return ERROR_FAIL;
+       }
+
+       retval = gowin_enable_config(tap);
+       if (retval != ERROR_OK) {
+               free(bit_file.data);
+               return retval;
+       }
+
+       retval = gowin_erase_sram(tap, false);
+       if (retval != ERROR_OK) {
+               free(bit_file.data);
+               return retval;
+       }
+
+       gowin_set_instr(tap, ADDRESS_INITIALIZATION);
+       gowin_set_instr(tap, TRANSFER_CONFIGURATION_DATA);
+
+       /* scan out the bitstream */
+       struct scan_field field;
+       field.num_bits = bit_file.length * 8;
+       field.out_value = bit_file.data;
+       field.in_value = bit_file.data;
+       jtag_add_dr_scan(gowin_info->tap, 1, &field, TAP_IDLE);
+       jtag_add_runtest(3, TAP_IDLE);
+
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK) {
+               free(bit_file.data);
+               return retval;
+       }
+
+       retval = gowin_disable_config(tap);
+       free(bit_file.data);
+       if (retval != ERROR_OK)
+               return retval;
+
+       gowin_set_instr(gowin_info->tap, NO_OP);
+
+       retval = jtag_execute_queue();
+
+       return retval;
+}
+
+static int gowin_read_register_command(struct pld_device *pld_device, uint32_t 
cmd, uint32_t *value)
+{
+       if (!pld_device)
+               return ERROR_FAIL;
+
+       struct gowin_pld_device *gowin_info = pld_device->driver_priv;
+
+       if (!gowin_info || !gowin_info->tap)
+               return ERROR_FAIL;
+
+       return gowin_read_register(gowin_info->tap, cmd, value);
+}
+
+static int gowin_reload_command(struct pld_device *pld_device)
+{
+       if (!pld_device)
+               return ERROR_FAIL;
+
+       struct gowin_pld_device *gowin_info = pld_device->driver_priv;
+
+       if (!gowin_info || !gowin_info->tap)
+               return ERROR_FAIL;
+
+       return gowin_reload(gowin_info->tap);
+}
+
+COMMAND_HANDLER(gowin_read_status_command_handler)
+{
+       int dev_id;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
+       struct pld_device *device = get_pld_device_by_num(dev_id);
+       if (!device) {
+               command_print(CMD, "pld device '#%s' is out of bounds", 
CMD_ARGV[0]);
+               return ERROR_FAIL;
+       }
+
+       uint32_t status = 0;
+       int retval = gowin_read_register_command(device, STATUS_REGISTER, 
&status);
+
+       if (retval == ERROR_OK)
+               command_print(CMD, "0x%8.8" PRIx32 "", status);
+
+       return retval;
+}
+
+COMMAND_HANDLER(gowin_read_user_register_command_handler)
+{
+       int dev_id;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
+       struct pld_device *device = get_pld_device_by_num(dev_id);
+       if (!device) {
+               command_print(CMD, "pld device '#%s' is out of bounds", 
CMD_ARGV[0]);
+               return ERROR_FAIL;
+       }
+
+       uint32_t user_reg = 0;
+       int retval = gowin_read_register_command(device, READ_USERCODE, 
&user_reg);
+
+       if (retval == ERROR_OK)
+               command_print(CMD, "0x%8.8" PRIx32 "", user_reg);
+
+       return retval;
+}
+
+COMMAND_HANDLER(gowin_reload_command_handler)
+{
+       int dev_id;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], dev_id);
+       struct pld_device *device = get_pld_device_by_num(dev_id);
+       if (!device) {
+               command_print(CMD, "pld device '#%s' is out of bounds", 
CMD_ARGV[0]);
+               return ERROR_FAIL;
+       }
+
+       return gowin_reload_command(device);
+}
+
+static const struct command_registration gowin_exec_command_handlers[] = {
+       {
+               .name = "read_status",
+               .mode = COMMAND_EXEC,
+               .handler = gowin_read_status_command_handler,
+               .help = "reading status register from FPGA",
+               .usage = "num_pld [GW2A] [verbose]",
+               .chain = NULL,
+       }, {
+               .name = "read_user",
+               .mode = COMMAND_EXEC,
+               .handler = gowin_read_user_register_command_handler,
+               .help = "reading user register from FPGA",
+               .usage = "num_pld",
+               .chain = NULL,
+       }, {
+               .name = "reload",
+               .mode = COMMAND_EXEC,
+               .handler = gowin_reload_command_handler,
+               .help = "reloading bitstream from flash to SRAM",
+               .usage = "num_pld",
+               .chain = NULL,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration gowin_command_handler[] = {
+       {
+               .name = "gowin",
+               .mode = COMMAND_ANY,
+               .handler = NULL,
+               .help = "gowin specific commands",
+               .usage = "",
+               .chain = gowin_exec_command_handlers
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+PLD_DEVICE_COMMAND_HANDLER(gowin_pld_device_command)
+{
+       struct jtag_tap *tap;
+
+       struct gowin_pld_device *gowin_info;
+
+       if (CMD_ARGC != 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       tap = jtag_tap_by_string(CMD_ARGV[1]);
+       if (!tap) {
+               command_print(CMD, "Tap: %s does not exist", CMD_ARGV[1]);
+               return ERROR_FAIL;
+       }
+
+       gowin_info = malloc(sizeof(struct gowin_pld_device));
+       if (!gowin_info) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+       gowin_info->tap = tap;
+
+       pld->driver_priv = gowin_info;
+
+       return ERROR_OK;
+}
+
+struct pld_driver gowin_pld = {
+       .name = "gowin",
+       .commands = gowin_command_handler,
+       .pld_device_command = &gowin_pld_device_command,
+       .load = &gowin_load_to_sram,
+};
diff --git a/src/pld/pld.c b/src/pld/pld.c
index fd2a770204..5c2bb91d78 100644
--- a/src/pld/pld.c
+++ b/src/pld/pld.c
@@ -23,11 +23,13 @@ extern struct pld_driver ecp5_pld;
 extern struct pld_driver trion_pld;
 extern struct pld_driver certus_pld;
 extern struct pld_driver intel_pld;
+extern struct pld_driver gowin_pld;
 
 static struct pld_driver *pld_drivers[] = {
        &certus_pld,
        &ecp2_3_pld,
        &ecp5_pld,
+       &gowin_pld,
        &intel_pld,
        &trion_pld,
        &virtex2_pld,
diff --git a/tcl/board/gowin_runber.cfg b/tcl/board/gowin_runber.cfg
new file mode 100644
index 0000000000..41406a827d
--- /dev/null
+++ b/tcl/board/gowin_runber.cfg
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Gowin RUNBER FPGA Development Board
+# https://www.seeedstudio.com/Gowin-RUNBER-Development-Board-p-4779.html
+
+adapter driver ftdi
+ftdi vid_pid 0x0403 0x6010
+
+ftdi channel 0
+ftdi layout_init 0x0008 0x008b
+reset_config none
+transport select jtag
+adapter speed 6000
+
+source [find fpga/gowin_gw1n.cfg]
+
+
+#openocd -f board/gowin_runber.cfg  -c "init" -c "pld load 0 
impl/pnr/gw1n_blinker.fs"
+#ipdbg -start -tap gw1n.tap -hub 0x42 -port 5555 -tool 0 -idle 3
diff --git a/tcl/fpga/gowin_gw1n.cfg b/tcl/fpga/gowin_gw1n.cfg
new file mode 100644
index 0000000000..d522376fd4
--- /dev/null
+++ b/tcl/fpga/gowin_gw1n.cfg
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# efinix trion
+# https://www.efinixinc.com/docs/an021-jtag-bst-trion-v1.0.pdf
+
+if { [info exists CHIPNAME] } {
+       set _CHIPNAME $CHIPNAME
+} else {
+       set _CHIPNAME gw1n
+}
+
+jtag newtap $_CHIPNAME tap -irlen 8 -ignore-version \
+       -expected-id 0x0900281B \
+       -expected-id 0x0900381B \
+       -expected-id 0x0100681B \
+       -expected-id 0x0300081B \
+       -expected-id 0x0300181B \
+       -expected-id 0x0120681B \
+       -expected-id 0x0100381B \
+       -expected-id 0x1100381B \
+       -expected-id 0x0100981B \
+       -expected-id 0x1100581B \
+       -expected-id 0x1100481B \
+       -expected-id 0x0000081B \
+       -expected-id 0x0000281B
+
+pld device gowin $_CHIPNAME.tap

-- 

Reply via email to