Administrator
发布于 2026-09-05 / 2 阅读
0
0

T20F256 JTAG-SPI Loader / Bridge 技术报告


T20F256 JTAG-SPI Loader / Bridge 技术报告

1. 报告目的

本文记录 T20F256 单 SPI Flash JTAG bridge 项目的创建、配置、构建、Flash profile 添加和硬件验证过程,便于后续复用、迁移到其他电脑或更换 Flash 器件时排查问题。

当前工程目录:

D:\dev26\EFI_T20F256\000_JTAG_SPI_LOADER\JTAG_SPI_LOADER

报告基准日期:2026-09-05

最终状态:

  • FPGA JTAG ID 0x00210A79 可正常识别。
  • jtag_spi_loader bridge bit 可通过 JTAG 下载到 FPGA。
  • SPI Flash 0x684015 可识别为 Boya BY25Q16BS,容量 2 MiB
  • 用户程序可擦除、写入、回读校验并正常运行。

2. 目标硬件和工具版本

项目 配置
FPGA 厂商/系列 Efinix Trion
FPGA 器件 T20F256
Timing Model C4
配置方式 Active SPI,x1
Efinity 2026.1.132.4.5
JTAG 工具 FT232H,日志中 SPI/JTAG URL 相同
JTAG bridge IP efx_jtag2spi_flash,IP version 3.2
外部 Flash Boya Microelectronics BY25Q16BSTIG / BY25Q16BS
Flash JEDEC ID 68 40 15,合并表示为 0x684015
Flash 实际容量 16 Mbit = 2 MiB

Flash 器件的型号和 JEDEC 表可参考:BY25Q16BSTIG 数据手册

3. 工程文件结构

工程中与 bridge 相关的主要文件如下:

JTAG_SPI_LOADER/
├─ JTAG_SPI_LOADER.xml                 Efinity 工程数据库入口
├─ JTAG_SPI_LOADER.sv                  顶层 Verilog/SystemVerilog
├─ JTAG_SPI_LOADER.isf                 Interface Designer 可重放配置脚本
├─ JTAG_SPI_LOADER.peri.xml            Interface Designer 生成的 periphery 数据库
├─ JTAG_SPI_LOADER.sdc                 时序约束
├─ pins.txt                            原始引脚要求
├─ ip/
│  └─ jtag_spi_loader/
│     ├─ settings.json                 IP 生成参数
│     ├─ jtag_spi_loader.sv             Efinity 生成的 bridge RTL
│     ├─ jtag_spi_loader_define.svh
│     └─ ipm/                           IP Manager 元数据
├─ work_syn/                           综合工作目录
├─ work_pnr/                           布局布线工作目录
└─ outflow/
   ├─ JTAG_SPI_LOADER.bit              FPGA bitstream
   ├─ JTAG_SPI_LOADER.hex              FPGA HEX 配置文件
   ├─ JTAG_SPI_LOADER.lpf              periphery/布局布线输入
   ├─ JTAG_SPI_LOADER.pinout.rpt       引脚报告
   ├─ JTAG_SPI_LOADER.timing.rpt       最终时序报告
   ├─ JTAG_SPI_LOADER.map.rpt          综合报告
   └─ JTAG_SPI_LOADER.pgm.out          bit/hex 生成日志

4. 创建 spiloader-bridge 项目的方法

4.1 创建 Efinity 工程

在 Efinity 中新建 Unified Flow 工程,选择:

Family       = Trion
Device       = T20F256
Timing Model = C4
Top Module   = JTAG_SPI_LOADER

工程配置使用 Active SPI x1。工程 XML 中的关键内容是:

<efx:family name="Trion" />
<efx:device name="T20F256" />
<efx:timing_model name="C4" />
<efx:top_module name="JTAG_SPI_LOADER" />
<efx:design_file name="JTAG_SPI_LOADER.sv" />
<efx:sdc_file name="JTAG_SPI_LOADER.sdc" />
<efx:isf_file name="JTAG_SPI_LOADER.isf" />

4.2 通过 IP Catalog 创建 JTAG-SPI bridge

在 IP Catalog/IP Manager 中选择:

Vendor  = efinixinc.com
Library = memory_controller
Name    = efx_jtag2spi_flash
Version = 3.2
Output  = ip/jtag_spi_loader

本工程只连接一颗 SPI Flash,因此必须关闭双 Flash:

{
  "args": [
    "-o", "jtag_spi_loader",
    "--base_path", "ip",
    "--vlnv", {
      "vendor": "efinixinc.com",
      "library": "memory_controller",
      "name": "efx_jtag2spi_flash",
      "version": "3.2"
    }
  ],
  "conf": {
    "EN_DUAL_FLASH": "1'b0"
  }
}

IP 生成后,顶层 bridge 模块的接口包括:

input        i_spi_clk;
output       o_spi_clk;
output       oe_spi_clk;
output       o_spi0_cs;
output       oe_spi0_cs;
input  [3:0] i_spi0_io;
output [3:0] o_spi0_io;
output [3:0] oe_spi0_io;

input  jtag_inst1_CAPTURE;
input  jtag_inst1_DRCK;
input  jtag_inst1_RESET;
input  jtag_inst1_RUNTEST;
input  jtag_inst1_SEL;
input  jtag_inst1_SHIFT;
input  jtag_inst1_TCK;
input  jtag_inst1_TDI;
input  jtag_inst1_TMS;
input  jtag_inst1_UPDATE;
output jtag_inst1_TDO;

其中 spi0 是第一颗 Flash,当前工程没有连接 spi1。JTAG 资源采用 JTAG_USER1,由 Interface Designer 生成 jtag_inst1_* 信号。

4.3 顶层 Verilog 实例化

Efinity Unified Flow 对双向管脚使用 core-side 的输入、输出和输出使能三组信号。因此顶层没有直接声明 inout FLASH_DATA[3:0],而是声明:

input  wire [3:0] FLASH_DATA_IN;
output wire [3:0] FLASH_DATA_OUT;
output wire [3:0] FLASH_DATA_OE;

input  wire       FLASH_CLK_IN;
output wire       FLASH_CLK_OUT;
output wire       FLASH_CLK_OE;

input  wire       FLASH_CS_IN;
output wire       FLASH_CS_OUT;
output wire       FLASH_CS_OE;

实际 bridge 实例化位于 JTAG_SPI_LOADER.sv

jtag_spi_loader u_jtag_spi_loader (
    .i_spi_clk          (FLASH_CLK_IN),
    .o_spi_clk          (FLASH_CLK_OUT),
    .oe_spi_clk         (FLASH_CLK_OE),
    .o_spi0_cs          (FLASH_CS_OUT),
    .oe_spi0_cs         (FLASH_CS_OE),
    .i_spi0_io          (FLASH_DATA_IN),
    .o_spi0_io          (FLASH_DATA_OUT),
    .oe_spi0_io         (FLASH_DATA_OE),
    .jtag_inst1_CAPTURE (jtag_inst1_CAPTURE),
    .jtag_inst1_DRCK    (jtag_inst1_DRCK),
    .jtag_inst1_RESET   (jtag_inst1_RESET),
    .jtag_inst1_RUNTEST (jtag_inst1_RUNTEST),
    .jtag_inst1_SEL     (jtag_inst1_SEL),
    .jtag_inst1_SHIFT   (jtag_inst1_SHIFT),
    .jtag_inst1_TCK     (jtag_inst1_TCK),
    .jtag_inst1_TDI     (jtag_inst1_TDI),
    .jtag_inst1_TMS     (jtag_inst1_TMS),
    .jtag_inst1_UPDATE  (jtag_inst1_UPDATE),
    .jtag_inst1_TDO     (jtag_inst1_TDO)
);

4.4 顶层附加逻辑

为便于确认用户 bitstream 已经运行,顶层加入了一个不参与 Flash 数据路径的心跳计数器:

reg [24:0] heartbeat_counter = 25'd0;

always @(posedge clk_25m) begin
    heartbeat_counter <= heartbeat_counter + 1'b1;
end

assign led[0]   = heartbeat_counter[24];
assign led[6:1] = 6'b0;
assign led[7]   = ~FLASH_CS_IN;
assign uart_tx  = 1'b1;

含义如下:

  • led[0]:约 25 MHz / 2^25 = 0.745 Hz 的低频心跳翻转,用于确认用户逻辑运行。
  • led[7]:Flash CS 为低有效,bridge 访问 Flash 时点亮或翻转。
  • led[1]led[6]:当前保持关闭。
  • uart_tx:保持 UART 空闲高电平。
  • pll0_in1_25muart_rx:保留为顶层真实端口并接入约束,但当前 bridge 不使用。

5. 根据 pins.txt 完成引脚和 Interface Designer 配置

5.1 原始引脚表

功能 顶层信号 封装引脚 方向 说明
25 MHz 时钟 clk_25m H4 Input bridge 用户侧保留时钟/心跳时钟
PLL 输入 pll0_in1_25m E8 Input 保留端口
LED0 led[0] N8 Output 心跳
LED1 led[1] R6 Output 当前关闭
LED2 led[2] N9 Output 当前关闭
LED3 led[3] P9 Output 当前关闭
LED4 led[4] M10 Output 当前关闭
LED5 led[5] N10 Output 当前关闭
LED6 led[6] A15 Output 当前关闭
LED7 led[7] B15 Output Flash CS 状态
UART TX uart_tx P4 Output 空闲高
UART RX uart_rx M7 Input 弱上拉
Flash IO0 FLASH_DATA[0] L3 Bidirectional SPI IO0/MOSI
Flash IO1 FLASH_DATA[1] N1 Bidirectional SPI IO1/MISO
Flash IO2 FLASH_DATA[2] K4 Bidirectional Quad/dual 扩展线
Flash IO3 FLASH_DATA[3] L2 Bidirectional Quad/dual 扩展线
Flash CLK FLASH_CLK M3 Bidirectional SPI 时钟
Flash CS FLASH_CS P3 Bidirectional Flash 低有效片选

5.2 Interface Designer 资源

JTAG_SPI_LOADER.isf 中完成了以下配置:

design.set_property("jtag_inst1","RESOURCE","JTAG_USER1","JTAG")
design.assign_resource("jtag_inst1","JTAG_USER1","JTAG")

Flash 相关物理 GPIO 按 inout 配置。Interface Designer 会把:

FLASH_DATA[0..3]  -> FLASH_DATA_IN[0..3]
                   -> FLASH_DATA_OUT[0..3]
                   -> FLASH_DATA_OE[0..3]
FLASH_CLK         -> FLASH_CLK_IN / FLASH_CLK_OUT / FLASH_CLK_OE
FLASH_CS          -> FLASH_CS_IN  / FLASH_CS_OUT  / FLASH_CS_OE

分别接到物理三态 I/O。所有使用的 I/O Bank 设置为 3.3 V,UART RX 配置为 WEAK_PULLUP

JTAG_SPI_LOADER.peri.xml 是 Interface Designer 生成的持久化数据库,不建议直接手工修改。需要改变管脚或 JTAG 资源时,应修改 .isf 或在 Interface Designer 中修改后重新生成 periphery 数据库。

6. 时序约束

JTAG_SPI_LOADER.sdc 的主要约束:

create_clock -name clk_25m \
    -period 40.0000 [get_ports {clk_25m}]

create_clock -name pll0_in1_25m \
    -period 40.0000 [get_ports {pll0_in1_25m}]

create_clock -name jtag_inst1_TCK \
    -period 25.0000 [get_ports {jtag_inst1_TCK}]

set_false_path -from [get_ports {jtag_inst1_RESET}]

说明:

  • clk_25m 约束为 25 MHz。
  • jtag_inst1_TCK 按 40 MHz 约束,实际用户日志中的 JTAG 访问频率为 6 MHz,低于该约束。
  • jtag_inst1_RESET 是 bridge 状态机的异步复位,设置为 false path。

7. 构建和 bitstream 生成流程

7.1 GUI 流程

在 Efinity 中打开 JTAG_SPI_LOADER.xml,按以下顺序执行:

  1. 确认 IP 文件已经加入工程,settings.jsonEN_DUAL_FLASH=1'b0
  2. 运行 Interface Designer,加载 JTAG_SPI_LOADER.isf,确认 JTAG_USER1、Flash I/O 和封装管脚。
  3. 运行 Synthesis/Map。
  4. 运行 Periphery/Unified Timing。
  5. 运行 Place and Route。
  6. 检查 JTAG_SPI_LOADER.timing.rptJTAG_SPI_LOADER.pinout.rpt
  7. 运行 Bitstream Generation,得到 outflow/JTAG_SPI_LOADER.bitoutflow/JTAG_SPI_LOADER.hex

7.2 日志中实际执行的阶段

Efinity 日志显示实际执行了以下阶段:

efx_run_map.py
efx_run_pt_unified.py
efx_run_pnr.py
efx_run_pgm.py

其中最终 bitstream 生成阶段使用的关键选项为:

mode=active
width=1
enable_roms=smart
spi_low_power_mode=on
io_weak_pullup=on
oscillator_clock_divider=DIV8
bitstream_compression=off
enable_external_master_clock=off
active_capture_clk_edge=posedge
jtag_usercode=0xFFFFFFFF
release_tri_then_reset=on
four_byte_addressing=off

four_byte_addressing=off 对本工程是合理的,因为 FPGA 配置 Flash 是 2 MiB,地址空间没有超过 3-byte addressing 的 16 MiB 边界。

7.3 构建结果

根据 outflow 报告:

检查项 结果
Verilog 分析/综合 完成
Placement 成功,1066 cells are placed
Routing 完成
Bitstream Generation 完成
FPGA bitstream outflow/JTAG_SPI_LOADER.bit
FPGA HEX outflow/JTAG_SPI_LOADER.hex
Bit 文件大小 2,035,950 bytes
Hex 文件大小 2,035,950 bytes

资源使用摘要:

资源 使用量 器件总量 使用率
Inputs 15 438 3.42%
Outputs 22 1001 2.20%
Clocks 2 16 12.50%
Logic Elements 1066 19728 5.40%
LUTs/Adders 882 19728 4.47%
Registers 526 13920 3.78%
Memory Blocks 0 204 0.00%
Multipliers 0 36 0.00%

最终时序摘要:

时钟 约束频率 分析最大频率 最差 Setup Slack 最差 Hold Slack
clk_25m 25 MHz 391.696 MHz 37.447 ns 0.361 ns
jtag_inst1_TCK 40 MHz 96.946 MHz 8.114 ns 0.307 ns

结论:当前约束下没有时序负裕量,且 bridge 的实际 JTAG 工作频率为 6 MHz。

8. JTAG-SPI bridge 的工作原理

8.1 两层下载过程

整个刷写动作不是直接把用户 HEX 通过 JTAG 写入 Flash,而是分成两层:

PC / FT232H
    │ JTAG
    ▼
临时运行在 FPGA 中的 JTAG_SPI_LOADER.bit
    │ SPI,由 bridge 产生 CLK/CS/DATA/OE
    ▼
板上的 BY25Q16BS Flash
    │ 上电后的 FPGA 配置读取
    ▼
用户程序逻辑

因此:

  • outflow/JTAG_SPI_LOADER.bit 是通过 JTAG 下载到 FPGA 的 bridge 固件。
  • led_counter.hex 等用户程序文件是通过 bridge 转换成 SPI 操作后写入外部 Flash 的数据。
  • 用户日志中的 Programming ... JTAG_SPI_LOADER.bit via JTAG 表示 bridge 下载阶段。
  • 后续 Writing ... to flash 表示用户程序数据真正写入 SPI Flash。

8.2 JTAG USER1 协议

生成 IP 的 jtag_spi_loader.sv 中定义了 JTAG bridge 的内部协议:

Data register width = 64 bits
Command width       = 6 bits
Register width      = 32 bits

主要 command:

命令 作用
JTAG2SPI_CMD_NONE 0 空操作
JTAG2SPI_CMD_RESET 1 bridge 状态复位
JTAG2SPI_CMD_REGREAD 2 读内部寄存器
JTAG2SPI_CMD_REGWRITE 3 写内部寄存器
JTAG2SPI_CMD_BRIDGE 4 发送 SPI bridge 数据
JTAG2SPI_CMD_CRC 5 读数据 CRC
JTAG2SPI_CMD_EXIT 32 退出当前状态

常用内部寄存器包括:

寄存器 索引 作用
INTREG_VERSION 0 bridge 版本
INTREG_STATE 1 bridge 状态
INTREG_FLASH_SELECT 2 选择 Flash
INTREG_CLK_OE_MAP 3 SPI CLK 输出使能
INTREG_OE_MAP 4 SPI DATA 输出使能
INTREG_ADDRESS 5 当前 Flash 地址
INTREG_LENGTH 6 当前传输长度
INTREG_OUTPUT_REG0..7 7..14 通用输出寄存器

当前工程只选 Flash 0,IP 通过 FLASH_DATA_OUT/OEFLASH_CLK_OUT/OEFLASH_CS_OUT/OE 控制物理 Flash。

8.3 Flash SPI 操作序列

BY25Q16BS,profile 使用标准 Gen25 SPI NOR 操作模型,典型序列如下:

  1. 发送 9Fh,读取三个 JEDEC 字节 68h 40h 15h
  2. 发送 05h 读取状态寄存器 SR1。
  3. 发送 06h 置位 WEL(Write Enable Latch)。
  4. 按需要发送 01h 写状态寄存器,清除保护位。
  5. 擦除:
    • 20h + 24-bit address:4 KiB。
    • 52h + 24-bit address:32 KiB。
    • D8h + 24-bit address:64 KiB。
    • C7h:整片擦除。
  6. 每条擦除/写状态命令后,通过 05h 轮询 SR1 的 WIP bit0,直到为 0。
  7. 编程:发送 06h,再发送 02h + 24-bit address + data,每页最多 256 bytes。
  8. 读取校验:发送 03h + 24-bit address,回读并比较数据。

9. Flash JEDEC ID 和 profile

9.1 JEDEC ID 分解

0x684015 应拆分为三个字节,而不是把它当成一个普通容量数:

字节 数值 含义
Manufacturer ID 0x68 Boya
Memory Type / Device ID 0x40 BY25Q16BS 系列匹配字段
Capacity ID 0x15 16 Mbit 密度码

容量换算:

16 Mbit / 8 = 2 MiB

profile 中的:

"densities": {
  "0x15": [2, 20]
}

按 Efinity JSON matcher 的计算方式表示为:

2 << 20 = 2,097,152 bytes = 2 MiB

9.2 profile 的安装位置

本次添加的是 Efinity 用户级 Flash 数据库文件:

C:\Users\Administrator\.efinity\pgm\flash_db\68_40_BY25Q16BS.json

用户目录配置文件:

C:\Users\Administrator\AppData\Local\efinity\user_dir.ini

内容为:

[General]
EFINITY_USER_DIR=C:\\Users\\Administrator\\.efinity

Efinity jtag2SpiJsonFlash.py 的查找顺序是:

  1. $EFINITY_USER_DIR/pgm/flash_db
  2. $EFXPGM_HOME/bin/flash_db

针对本次 JEDEC ID,程序首先匹配文件名模式:

68_40_*.json

因此文件名中的 68_40 不能省略或写错。

9.3 完整 Flash profile

当前实际使用的 profile 如下:

{
  "name": "Boya BY25Q16BS",
  "mfg_name": "Boya",
  "match": {
    "model": "gen25",
    "mfg_id": "0x68",
    "dev_id": {
      "0x40": "BY25Q16BS"
    },
    "densities": {
      "0x15": [
        2,
        20
      ]
    }
  },
  "max_spi_frequency": 55,
  "write": {
    "model": "gen25",
    "size": 256,
    "cmd": "0x02",
    "4byte_cmd": "0x12",
    "timing": [
      0.0015,
      0.003
    ]
  },
  "read": {
    "model": "gen25"
  },
  "erase": {
    "model": "gen25",
    "sizes": [
      {
        "size": 65536,
        "cmd": "0xD8",
        "4byte_cmd": null,
        "timing": [
          0.15,
          1.0
        ]
      },
      {
        "size": 32768,
        "cmd": "0x52",
        "4byte_cmd": null,
        "timing": [
          0.15,
          1.0
        ]
      },
      {
        "size": 4096,
        "cmd": "0x20",
        "4byte_cmd": null,
        "timing": [
          0.05,
          0.5
        ]
      },
      {
        "size": -1,
        "cmd": "0xC7",
        "4byte_cmd": null,
        "timing": [
          15.0,
          30.0
        ]
      }
    ]
  },
  "lock": {
    "model": "gen25",
    "read_cmd": "0x05",
    "write_cmd": "0x01",
    "and_mask": "0x43",
    "or_mask": "0x00",
    "status2_cmd": "0x35",
    "timing": [
      0.05,
      0.1
    ]
  },
  "addr_modes": [],
  "io_modes": [
    {
      "model": "dspi"
    }
  ],
  "write_status": {
    "model": "gen25"
  },
  "poll": {
    "model": "gen25"
  }
}

9.4 profile 字段说明

字段 配置 技术意义
match.model gen25 使用通用 25 系列 SPI NOR matcher/操作模型
mfg_id 0x68 匹配 Boya 厂商 ID
dev_id 0x40 匹配 BY25Q16BS 器件字段
densities 0x15: [2,20] 将容量识别为 2 MiB
max_spi_frequency 55 MHz profile 允许的最大 SPI 频率;本次实际 JTAG bridge 为 6 MHz
write.size 256 Flash 页编程大小
write.cmd 0x02 普通 SPI Page Program
write.timing 1.5/3 ms 页编程典型/最大等待时间
64 KiB erase 0xD8 大块擦除
32 KiB erase 0x52 中块擦除
4 KiB erase 0x20 最小擦除单位
chip erase 0xC7 整片擦除
lock.read_cmd 0x05 读取 SR1
lock.write_cmd 0x01 写 SR1/SR2 状态寄存器
lock.and_mask 0x43 清除保护相关 BP/SRP 位,同时保留 WEL/WIP 等必要位
status2_cmd 0x35 读取并保留 SR2,配合 0x01 联合写状态
poll gen25 使用 SR1 bit0 WIP 轮询忙闲
addr_modes 不进入 4-byte address mode
io_modes dspi 声明 dual-SPI 能力;没有添加 qspi,不会主动配置 QE 位

10. 原始报错的技术原理

10.1 原始错误日志的关键点

原始日志中有三组重要信息:

Valid device ID found: 0x00210A79
...
... finished with JTAG programming
...
Flash device: Unknown Unknown 16 MiB (JEDEC ID: 0x684015)
...
Command timout (1 cycles), aborting flash operation

这说明:

  1. FPGA JTAG TAP 正常,0x00210A79 已读出。
  2. bridge bit 已经成功通过 JTAG 下载,JTAG 到 FPGA 的路径正常。
  3. bridge 已经能通过 SPI 读到 Flash 的 0x684015,所以 CLK、CS、IO0/IO1 的基本连接和方向也正常。
  4. 失败发生在 Flash 数据库匹配后的擦除/状态轮询阶段,不是 FPGA JTAG ID 错误,也不是 bridge bit 没下载进去。

10.2 为什么显示 Unknown Unknown 16 MiB

0x684015 没有对应的 JSON profile 时,Efinity 能读取原始 JEDEC 字节,但无法得到:

  • 厂商名称;
  • 器件名称;
  • 正确容量;
  • 页编程大小;
  • 擦除命令和擦除粒度;
  • 状态寄存器读写命令;
  • WIP/WEL/保护位位置;
  • 擦除、写入和状态写入的等待时间。

于是日志只能打印 Unknown Unknown,并继续使用通用/未知器件路径尝试操作。这个路径不能保证与 BY25Q16BS 的状态寄存器和擦除时序完全匹配;其中显示的 16 MiB 也不能作为该 Flash 的实际容量判断依据。

10.3 Command timout (1 cycles) 的本质

擦除不是发送完命令就立即完成。典型过程是:

WREN(06h)
    ↓
ERASE(20h/52h/D8h + address)
    ↓
Flash 内部擦除,SR1.WIP = 1
    ↓
反复发送 RDSR(05h),直到 SR1.WIP = 0

Efinity bridge 通过 JTAG 发出 RDSR,再把 Flash 返回的数据通过 JTAG 读回 PC。日志中的 Command timout 是主机侧等待/轮询超时,含义是工具在预期的操作时间内没有得到“Flash ready”的状态,不是 JTAG 频率本身超时。

本次 profile 修复了三个关键问题:

  1. 68/40/15 进行精确器件匹配,容量从未知值改为 2 MiB
  2. 告诉工具使用 BY25Q16BS 兼容的 gen25 擦除、写入和状态寄存器模型。
  3. 给出正确的 4 KiB/32 KiB/64 KiB 擦除命令、写状态命令和等待时间,使 WIP 轮询能够结束。

11. 硬件刷写验证

添加 profile 后,实际刷写日志为:

Flash device: Boya BY25Q16BS 2 MiB (JEDEC ID: 0x684015) @ JTAG freq 6.0 MHz
Unlock all sectors for write.
Erasing 664 KiB from flash @ 0x00000000 (may take a while...)
Finished erase in 2 seconds
Writing 662 KiB to flash @ 0x00000000 ...
Finished write in 7 seconds
Reading 662 KiB from flash @ 0x00000000 ...
Finished read in 0 seconds
Flash verify successful
Flash programming...done
Programming operation completed.

验证结论:

  • Flash 识别结果与器件实际型号一致。
  • 664 KiB 擦除完成。
  • 662 KiB 用户程序写入完成。
  • 回读数据校验成功。
  • 用户程序已经正常运行。

12. 构建警告和解释

当前综合报告存在若干 warning,但没有阻止生成 bitstream,也没有影响实际刷写:

intreg_version is never assigned
expression size ... truncated
i_spi1_io[...] does not have a driver
spi1_io[...] does not have a driver
Removing redundant signal ...
Re-wiring to GND non-driven net/port ...

这些 warning 主要来自:

  • IP 的通用生成代码保留了双 Flash/多 IO/内部寄存器接口;
  • 本工程配置 EN_DUAL_FLASH=1'b0,所以未使用的 Flash1 通道被综合优化或接地;
  • JTAG_USER1 中部分 TAP 辅助信号在当前实现中不直接参与数据路径;
  • 顶层保留了 pll0_in1_25muart_rx 等板级端口,但当前逻辑没有使用它们。

需要扩展为双 Flash、QSPI 或使用 UART 调试时,应重新检查这些 warning,不能简单套用当前结论。

13. 交付物和校验值

以下 SHA-256 用于确认工程和 bitstream 没有被意外替换:

文件 大小 SHA-256
JTAG_SPI_LOADER.sv 4,029 B b8da680750bb8f2f1ab5d9554c6231f6b05cb8819c8e348717018569b2ed2fa7
JTAG_SPI_LOADER.xml 6,871 B ce665e808fc786c3c06269b1545b5a78ad0b6fd3c13567ca47809511fc9b756d
JTAG_SPI_LOADER.isf 3,227 B 66091628e8d9a4a9d54b0fdef6d983ad51159647c3e7c02dc3b1c790c7e90bcf
JTAG_SPI_LOADER.sdc 418 B b21676337f00483621b465479659cc7db6d90b1cdb4324ab2c5cee98d4714f79
pins.txt 856 B 4049385ed29a953a50e3132618a50666b0e9cc64c2dfc99e9d199b62f2df5684
ip/jtag_spi_loader/settings.json 726 B cd2fb50f7e3de2fbbc64592d9da109a11a670fd9ec988fe972a4fa7ed6cac83d
outflow/JTAG_SPI_LOADER.bit 2,035,950 B b16ff0c28162fb6230f23bc7e7a596400da37397457c4c5a535753c3dc7e2170
outflow/JTAG_SPI_LOADER.hex 2,035,950 B 99e40da654e2f7723c262c9c4c3eeafa40439449e6a792225ca4a58f033ce147
C:\Users\Administrator\.efinity\pgm\flash_db\68_40_BY25Q16BS.json 1,471 B de4f148bff3815139948ae2793e28576059d91038def6e5dcff1bd89b468c3a4

14. 后续迁移/复用清单

在另一台电脑或另一块相同硬件上复用时,需要同时保留:

  1. 整个 JTAG_SPI_LOADER 工程目录,尤其是 JTAG_SPI_LOADER.xmlJTAG_SPI_LOADER.isfJTAG_SPI_LOADER.sdcip/jtag_spi_loader

  2. outflow/JTAG_SPI_LOADER.bit,用于临时把 bridge 下载到 FPGA。

  3. 用户目录下的 Flash profile:

    C:\Users\<用户名>\.efinity\pgm\flash_db\68_40_BY25Q16BS.json
    
  4. 确认目标电脑的 EFINITY_USER_DIR 指向包含 pgm/flash_db 的用户目录。

  5. 确认 FT232H 驱动、JTAG/SPI 通道和板上 Flash 电平为 3.3 V。

  6. 刷写时首先观察 JTAG ID,然后确认日志出现:

    Flash device: Boya BY25Q16BS 2 MiB (JEDEC ID: 0x684015)
    

如果再次看到 Unknown Unknown,应优先检查 profile 路径、文件名 68_40_*.json、JSON 格式和 Efinity 用户目录环境变量,而不是先修改 FPGA bridge RTL。


报告对应工程版本:Efinity 2026.1.132.4.5,Trion T20F256/C4,单 Flash bridge,最终硬件回读校验成功。



评论