1. 概述
在 Xilinx FPGA 开发中,可以将多个 FPGA 配置文件(Bin 文件)存储到外部 Flash 存储器中,并 ICA动态重新配置自身。本文介绍如何使用 ICAP 方式在 Flash 中烧写多个 Bin 文件,并通过 JTAG2AXI 接口控制 ICAP 启动任意程序。这种方法适用于需要动态加载不同配置的应用场景。
本文将详细描述实现步骤,包括如何使用软件工具将 Bin 文件下载到 Flash,以及如何通过 JTAG2AXI 控制 ICAP 实现程序的动态加。
2. 实现步骤
2.1 使用软件将 Bin 文件下载到 Flash
- 准备多个 Bin 文件
本示例使用A7 100T板卡,winbond 32Mbit(4M) Flash- 生成多个不同的 Bit 文件(如
LED1.bin
,LED2.bin
),每个文件对应一个特定功能。 - 程序功能简单,bin文件相对较小,因此分配基地址如下
LED1.bin
存储于地址0x00000000
。LED2.bin
存储于地址0x01000000
。
- 如果flash足够大,可存放多个bin文件
- 生成多个不同的 Bit 文件(如
- 烧写程序
由于winbond(华邦)Flash不在Vivado列表中,我们使用SZ901下载器烧写工具分别固化程序-
LED1.bin文件的基地址为0x00000000,配置如下
-
LED2.bin文件的基地址为0x00100000,配置如下
-
2.2 使用 JTAG2AXI 控制 ICAP 启动程序
-
ICAP 模块概述
ICAP 是 Xilinx FPGA 提供的内部配置接口,我们使用的是A7系列,因此采用IACP2。 -
设计 JTAG2AXI 控制逻辑
JTAG2AXI 是一种将 JTAG 命令转换为 AXI 总线事务的接口,允许外部工具通过 JTAG 控制 FPGA 内部的 AXI 外设。实现步骤如下:- 在 Vivado 中添加 JTAG to AXI Master IP 核。
- 试验程序中将集成一个ICAP配置程序,通过JTAG接口配置AXI gpio控制
此为JTAG AXI简易界面(在原程序添加,多数功能与程序无关):
-
准备启动程序
我们采用一个简单程序验证启动,通过JTAG接口控制,程序中使用JTAG2AXI ip控制icap2启动,程序中地址已固定为0x00100000
ICAP2控制程序如下,集成到JTAG程序中,或者自定义控制方式
module icap (
input logic clk, // 系统时钟(例如 50 MHz)
input logic reset, // 高电平有效复位
input logic start_reconfig // 触发重新配置的信号
);
// ICAP 接口信号
logic [31:0] icap_data_in, icap_data_out;
logic icap_ce, icap_write;
// 状态机状态
localparam IDLE = 2'd0,
ICAP_CONFIG = 2'd1,
DONE = 2'd2;
logic [3:0] state, next_state;
// 上升沿检测
logic start_reconfig_prev; // 保存 start_reconfig 前一状态
logic start_reconfig_edge; // 上升沿检测信号
// ICAP 模块实例化
ICAPE2 #(
.DEVICE_ID(32'h0362D093), // XC7A100T 的 Device ID,参考 UG470
.ICAP_WIDTH("X32") // 32 位数据宽度
) icap_inst (
.CLK(clk), // ICAP 时钟
.CSIB(icap_ce), // 片选(低有效)
.RDWRB(icap_write), // 读/写控制(0=写,1=读)
.I(icap_data_in), // 输入数据
.O(icap_data_out) // 输出数据(未使用)
);
// 上升沿检测逻辑
always @(posedge clk or posedge reset) begin
if (reset)
start_reconfig_prev <= 1'b0;
else
start_reconfig_prev <= start_reconfig;
end
assign start_reconfig_edge = start_reconfig & ~start_reconfig_prev; // 检测上升沿
// 状态机:控制 ICAP 配置
always @(posedge clk or posedge reset) begin
if (reset)
state <= IDLE;
else
state <= next_state;
end
// 状态转换逻辑
always @(*) begin
next_state = state;
case (state)
IDLE: begin
if (start_reconfig_edge) // 仅在上升沿触发
next_state = ICAP_CONFIG;
end
ICAP_CONFIG: begin
if (icap_done)
next_state = DONE;
end
DONE: begin
next_state = DONE; // 保持完成状态
end
endcase
end
// ICAP 控制信号
reg icap_done;
reg [3:0] icap_cmd_count;
always @(posedge clk or posedge reset) begin
if (reset) begin
icap_ce <= 1'b1;
icap_write <= 1'b1;
icap_data_in <= 32'h0;
icap_cmd_count <= 0;
icap_done <= 1'b0;
end else if (state == ICAP_CONFIG) begin
icap_ce <= 1'b0; // 使能 ICAP
icap_write <= 1'b0; // 写模式
case (icap_cmd_count)
case (icap_cmd_count)
0: icap_data_in <= 32'hFFFFFFFF; // 0xFFFFFFFF
1: icap_data_in <= 32'h5599AA66; // 0xAA995566
2: icap_data_in <= 32'h08000000; // 0x20000000
3: icap_data_in <= 32'h0C400480; // 0x30022001
4: icap_data_in <= 32'h00080000; // Flash_Start_Address 0x00100000/
5: icap_data_in <= 32'h08000000; // 0x20000000
6: icap_data_in <= 32'h0C000180; // 0x30008001
7: icap_data_in <= 32'hB00000F0; // 0x0000000F
8: begin
icap_ce <= 1'b1; // 禁用 ICAP
icap_done <= 1'b1; // 配置完成
end
endcase
if (icap_cmd_count < 8)
icap_cmd_count <= icap_cmd_count + 1;
end else begin
icap_ce <= 1'b1;
icap_write <= 1'b1;
icap_data_in <= 32'h0;
icap_cmd_count <= 0;
end
end
endmodule
2.3 软件控制示例
-
控制原理
由于winbond flash中烧写的是bin文件,FPGA在上电启动时,自动加载0x00000000地址程序即LED1.bin。我们通过下载控制bit文件,通过外部命令触发ICAP2启动,使LED2程序加载,完成目标,此过程不需要重启电源。
-
控制命令
将bit文件下载到程序中,在Vivado tcl命令栏输入如下命令
命令如下create_hw_axi_txn wr_txn_lite [get_hw_axis hw_axi_3] -address 40000000 -data 00000001 -type write -force run_hw_axi wr_txn_lite
-
其它方式
- 可以将icap控制程序单独生成一个bin文件,存放在0x00000000,LED1和LED2 分别烧写在0x00100000,0x00200000地址
- 将icap控制程序分别集成到LED1,LED2中,通过设置起始地址启动加载程序
3. 技术优势
-
灵活性
使用 ICAP 和 JTAG2AXI 实现动态重配置,允许 FPGA 在运行时切换不同功能,无需重新上电或手动烧写,提高系统适应性。 -
高效性
通过 Flash 存储多个 Bin 文件并使用 ICAP 加载,减少外部存储器访问时间,提升配置切换速度。 -
可扩展性
该方案支持存储多个 Bin 文件,适用于需要频繁切换功能的应用场景,如通信协议切换、算法加速等。
4. 总结
本文JTAG to AXI只是外部控制的一种方式,用户可以通过串口,网口等其它方式配置icap,加载相应程序。