[Vivado 技巧]FPGA烧写多个bin文件,切换不同程序启动

1. 概述

在 Xilinx FPGA 开发中,可以将多个 FPGA 配置文件(Bin 文件)存储到外部 Flash 存储器中,并 ICA动态重新配置自身。本文介绍如何使用 ICAP 方式在 Flash 中烧写多个 Bin 文件,并通过 JTAG2AXI 接口控制 ICAP 启动任意程序。这种方法适用于需要动态加载不同配置的应用场景。

本文将详细描述实现步骤,包括如何使用软件工具将 Bin 文件下载到 Flash,以及如何通过 JTAG2AXI 控制 ICAP 实现程序的动态加。

2. 实现步骤

2.1 使用软件将 Bin 文件下载到 Flash

  1. 准备多个 Bin 文件
    本示例使用A7 100T板卡,winbond 32Mbit(4M) Flash
    • 生成多个不同的 Bit 文件(如 LED1.bin, LED2.bin),每个文件对应一个特定功能。
    • 程序功能简单,bin文件相对较小,因此分配基地址如下
      • LED1.bin 存储于地址 0x00000000
      • LED2.bin 存储于地址 0x01000000
    • 如果flash足够大,可存放多个bin文件
  2. 烧写程序
    由于winbond(华邦)Flash不在Vivado列表中,我们使用SZ901下载器烧写工具分别固化程序
    • LED1.bin文件的基地址为0x00000000,配置如下
      在这里插入图片描述

    • LED2.bin文件的基地址为0x00100000,配置如下
      在这里插入图片描述

2.2 使用 JTAG2AXI 控制 ICAP 启动程序

  1. ICAP 模块概述
    ICAP 是 Xilinx FPGA 提供的内部配置接口,我们使用的是A7系列,因此采用IACP2。

  2. 设计 JTAG2AXI 控制逻辑
    JTAG2AXI 是一种将 JTAG 命令转换为 AXI 总线事务的接口,允许外部工具通过 JTAG 控制 FPGA 内部的 AXI 外设。实现步骤如下:

    • 在 Vivado 中添加 JTAG to AXI Master IP 核。
    • 试验程序中将集成一个ICAP配置程序,通过JTAG接口配置AXI gpio控制

    此为JTAG AXI简易界面(在原程序添加,多数功能与程序无关):
    在这里插入图片描述

  3. 准备启动程序
    我们采用一个简单程序验证启动,通过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 软件控制示例

  1. 控制原理
    由于winbond flash中烧写的是bin文件,FPGA在上电启动时,自动加载0x00000000地址程序即LED1.bin。

    我们通过下载控制bit文件,通过外部命令触发ICAP2启动,使LED2程序加载,完成目标,此过程不需要重启电源。

  2. 控制命令
    将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
    
  3. 其它方式

    • 可以将icap控制程序单独生成一个bin文件,存放在0x00000000,LED1和LED2 分别烧写在0x00100000,0x00200000地址
    • 将icap控制程序分别集成到LED1,LED2中,通过设置起始地址启动加载程序

3. 技术优势

  1. 灵活性
    使用 ICAP 和 JTAG2AXI 实现动态重配置,允许 FPGA 在运行时切换不同功能,无需重新上电或手动烧写,提高系统适应性。

  2. 高效性
    通过 Flash 存储多个 Bin 文件并使用 ICAP 加载,减少外部存储器访问时间,提升配置切换速度。

  3. 可扩展性
    该方案支持存储多个 Bin 文件,适用于需要频繁切换功能的应用场景,如通信协议切换、算法加速等。

4. 总结

本文JTAG to AXI只是外部控制的一种方式,用户可以通过串口,网口等其它方式配置icap,加载相应程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值