• 正文
  • 相关推荐
申请入驻 产业图谱

【ALINX 教程】FPGA Multiboot 功能实现——基于 ALINX Artix US+

01/06 08:54
321
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

教程目的

本教程介绍如何在 ALINX Artix US+ AXAU25 FPGA 开发板上,通过 Multiboot 实现多个 bitstream 的存储与动态切换,并在配置失败时自动回退至安全镜像(Golden Image)。

适用对象

已掌握 FPGA 基础开发(会写Verilog、会生成bitstream)

熟悉 Vivado 工程流程

对 FPGA 配置机制尚不深入,希望进入系统级设计阶段的学习者

Multiboot 功能概述

在基础实验中,FPGA 通常通过 JTAG 下载 bitstream,这种方式掉电后配置就丢失,亦无法实现远程升级。Multiboot 通过将多个配置镜像存储在外部 Flash 中,使 FPGA 能够在上电或运行过程中,从不同地址加载不同的 bitstream,并在异常情况下自动回退,保证系统可恢复。

Golden Image:固定存放在 Flash 的 0 地址,功能最小、稳定可靠,负责系统初始化与升级控制。

Multiboot Image:存放在 Flash 的其他地址,承载具体业务逻辑,可被升级或替换。

下图展示了 FPGA Multiboot 机制的整体配置与启动流程:FPGA 上电后默认从 Flash 0 地址加载 Golden Image,在满足触发条件后,通过 MultiBoot 机制尝试从 Upper Address 加载 MultiBoot Image。当配置成功时运行 MultiBoot Image;若配置失败,则触发 Fallback 机制,自动回退并重新加载 Golden Image,以保证系统仍可正常运行。

(Multiboot 运行流程示意图)

Multiboot 实现方式

AMD FPGA 支持两种 Multiboot 实现方式,一种是在生成 bitstream 时嵌入 IPROG,另一种是通过用户逻辑控制 ICAP 接口触发重配置,本教程采用 ICAP+IPROG 的动态方式,可在 FPGA 运行过程中灵活控制重配置行为,更符合实际工程需求。

Multiboot 实现方式

使用硬件

开发板:ALINX AXAU25

FPGA:AMD Artix UltraScale+(XCAU25P)

启动方式:SPI Flash(x4 模式)

该平台原生支持 MultiBoot 与 Fallback。

(ALINX基于Artix UltraScale+ FPGA开发板AXAU25)

工程实现

Golden Image 设计

//===========================================================================
// Module name: led_test.v
//===========================================================================
`timescale 1ns / 1ps

module multiboot_top
(             
input  sys_clk_p,      // Difference system clock 200Mhz input on board
input  sys_clk_n,  
output reg  led            // LED,use for control the LED signal on board

 );
             
//define the time counter
reg [31:0]   timer;      
wire [31:0]   WBSTAR;      


//===========================================================================
//Differentia system clock to single end clock
//===========================================================================
wire        rst_n;
wire        sys_clk_buf;
wire        sys_clk;
wire        switch;
wire        switch_d0;
wire        switch_d1;
 IBUFGDS u_ibufg_sys_clk   //????????????????
     (
      .I  (sys_clk_p),
      .IB (sys_clk_n),
      .O  (sys_clk_buf  )
      ); 

  clk_wiz_0 syspll
   (
    // Clock out ports
    .clk_out1(sys_clk),     // output clk_out1
    // Status and control signals
    .locked(rst_n),       // output locked
   // Clock in ports
    .clk_in1(sys_clk_buf));               
    
    

vio_0 uu (
  .clk(sys_clk),                // input wire clk
  .probe_out0(switch),  // output wire [0 : 0] probe_out0
  .probe_out1(WBSTAR)  // output wire [31 : 0] probe_out1
);
//===========================================================================

//===========================================================================
  always @(posedge sys_clk)
    begin
      if (~rst_n)
          timer <= 32'd0;                     // when the reset signal valid,time counter clearing
      else if (timer == 32'd99_999_999)    //1 seconds count(200M-1=199999999) ?????200Mhz??????5ns??????0-199_999_999,??2*10^8??????
          timer <= 32'd0;                       //count done,clearing the time counter
      else
                    timer <= timer + 1'b1;            //timer counter = timer counter + 1????????????????
    end

//===========================================================================
// LED control
//===========================================================================
  always @(posedge sys_clk)
    begin
      if (~rst_n)
          led <= 0;                  //when the reset signal active
      else if (timer == 32'd99_999_999)   //time counter count to 1 sec,LED4 lighten
          led <= ~led;
    end

(* MARK_DEBUG="true" *)reg  ce ;
(* MARK_DEBUG="true" *)reg  write ;
(* MARK_DEBUG="true" *)reg [31:0]  icap_in ;
(* MARK_DEBUG="true" *)wire [31:0]  icap_in_wire ;

   ICAPE3 #(
      .DEVICE_ID(32'h04A64093),     // Specifies the pre-programmed Device ID value to be used for simulation
                                    // purposes.
      .ICAP_AUTO_SWITCH("DISABLE"), // Enable switch ICAP using sync word.
      .SIM_CFG_FILE_NAME("NONE")    // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation
                                    // model.
   )
   ICAPE3_inst (
      .AVAIL(),     // 1-bit output: Availability status of ICAP.
      .O(O),             // 32-bit output: Configuration data output bus.
      .PRDONE(),   // 1-bit output: Indicates completion of Partial Reconfiguration.
      .PRERROR(), // 1-bit output: Indicates error during Partial Reconfiguration.
      .CLK(sys_clk),         // 1-bit input: Clock input.
      .CSIB(ce),       // 1-bit input: Active-Low ICAP enable.
      .I(icap_in_wire),             // 32-bit input: Configuration data input bus.
      .RDWRB(write)      // 1-bit input: Read/Write Select input.
   );

localparam        [31:0]        DUMMY_WORD                = 32'hFFFFFFFF;
localparam        [31:0]        SYNC_WORD            = 32'hAA995566;
localparam        [31:0]        TYPE1_NOOP                = 32'h20000000;
localparam        [31:0]        TYPE1_WBSTAR        = 32'h30020001;
localparam        [31:0]        TYPE1_CMD                  = 32'h30008001;
localparam        [31:0]        IPROG_CMD                  = 32'h0000000F;

// localparam  [31:0]  WBSTAR        = 32'h04000000;

(* MARK_DEBUG="true" *)reg [3:0]  state ;


assign icap_in_wire = {icap_in[3*8+0],icap_in[3*8+1],icap_in[3*8+2],icap_in[3*8+3],icap_in[3*8+4],icap_in[3*8+5],icap_in[3*8+6],icap_in[3*8+7],
                      icap_in[2*8+0],icap_in[2*8+1],icap_in[2*8+2],icap_in[2*8+3],icap_in[2*8+4],icap_in[2*8+5],icap_in[2*8+6],icap_in[2*8+7],
                      icap_in[1*8+0],icap_in[1*8+1],icap_in[1*8+2],icap_in[1*8+3],icap_in[1*8+4],icap_in[1*8+5],icap_in[1*8+6],icap_in[1*8+7],
                      icap_in[0*8+0],icap_in[0*8+1],icap_in[0*8+2],icap_in[0*8+3],icap_in[0*8+4],icap_in[0*8+5],icap_in[0*8+6],icap_in[0*8+7]};


always @(posedge sys_clk ) begin
  if (~rst_n)  begin
    state <= 0 ;
    ce <= 0 ;
    write <= 0 ;
    icap_in <= DUMMY_WORD ;
  end
  else begin
    case (state)
      0: begin
        if (switch) begin
          state <= 1 ;
          icap_in <= DUMMY_WORD ;   //Dummy word
          write <= 0 ;
          ce <= 0 ;
        end
      end
      1: begin
        state <= 2 ;
        icap_in <= SYNC_WORD ;   //sync word
      end
      2: begin
        state <= 3 ;
        icap_in <= TYPE1_NOOP ;   //Type 1 NOOP
      end
      3: begin
        state <= 4 ;
        icap_in <= TYPE1_WBSTAR ;   //Type 1 Write 1 words to WBSTAR
      end
      4: begin
        state <= 5 ;
        icap_in <= WBSTAR ;   //Warm boot start address (Load the desired address)
      end
      5: begin
        state <= 6 ;
        icap_in <= TYPE1_CMD ;   //Type 1 Write 1 words to CMD
      end
      6: begin
        state <= 7 ;
        icap_in <= IPROG_CMD ;   //IPROG command
      end
      7: begin
        state <= 8 ;
        icap_in <= TYPE1_NOOP ;   //Type 1 NOOP
      end
      8: begin
        state <= 8 ;
        write <= 1 ;
        ce <= 1 ;
        icap_in <= 0 ;
      end
      default: begin
        state <= 0 ;
        ce <= 1 ;
        write <= 1 ;
        icap_in <= DUMMY_WORD ;
      end
    endcase
  end
end

    
endmodule

XDC 约束
############## clock define##################
create_clock -period 5.000 [get_ports sys_clk_p]
set_property PACKAGE_PIN T24 [get_ports sys_clk_p]
set_property PACKAGE_PIN U24 [get_ports sys_clk_n]
set_property IOSTANDARD DIFF_SSTL18_I [get_ports sys_clk_n]



##############LED define##################
set_property PACKAGE_PIN W21 [get_ports led]
set_property IOSTANDARD LVCMOS18 [get_ports led]


set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]

set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
Multiboot Image 设计

`timescale 1ns / 1ps 
module multiboot(
//Differential system clock
    input sys_clk_p,
    input sys_clk_n,
    input rst_n,
(* MARK_DEBUG="true" *)    output reg [1:0] led
    );
(* MARK_DEBUG="true" *)reg[31:0] timer_cnt;
wire sys_clk ;

IBUFDS IBUFDS_inst (
      .O(sys_clk),   // 1-bit output: Buffer output
      .I(sys_clk_p),   // 1-bit input: Diff_p buffer input (connect directly to top-level port)
      .IB(sys_clk_n)  // 1-bit input: Diff_n buffer input (connect directly to top-level port)
   );

always@(posedge sys_clk)
begin
    if (!rst_n)
    begin
      led <= 2'b0 ;
    end
    else if(timer_cnt <= 32'd100_000_000)
    begin
        led <= 2'b10;
    end
    else begin
         led <= 2'b01;
    end
end

always@(posedge sys_clk)begin
    if(!rst_n)begin
        timer_cnt <= 32'b0;
    end
    else if(timer_cnt >= 32'd199_999_999)   //1 second counter, 200M-1=199_999_999
    begin
        timer_cnt <= 32'd0;
    end
    else begin
        timer_cnt <= timer_cnt + 1;
    end
end


endmodule
xdc约束
set_property PACKAGE_PIN T24 [get_ports sys_clk_p]
set_property PACKAGE_PIN N26 [get_ports rst_n]
set_property PACKAGE_PIN W21 [get_ports led]
set_property IOSTANDARD LVCMOS18 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports rst_n]
set_property IOSTANDARD DIFF_SSTL18_I [get_ports sys_clk_p]

set_property PACKAGE_PIN AC16 [get_ports {led[0]}]
set_property PACKAGE_PIN W21 [get_ports {led[1]}]

create_clock -period 5.000 -name sys_clk_p -waveform {0.000 2.500} [get_ports sys_clk_p]

set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
设备的 ID 是固定按照提供资料查询相关操作设备 ID

下方列表是通过 ICAP 接口进行 IPROG 中需要执行的命令

通过 Vivado 将需要固化的两个 bit 文件合成一个烧写文件,烧写完成断电重新上电即可。

实验结果

默认加载 Golden Image,LED 1闪烁

通过 VIO 设置

switch=1,WBSTAR=0x0080_0000(我们在 Flash 中存放的第二个 Multiboot Image 的初始地址),等待一段时间,LED 1、LED 2 交替闪烁,MultiBoot Image 切换成功。

参考文档

UltraScale Architecture Configuration User Guide (UG570)

Vivado Design Suite 用户指南: 编程和调试 (UG908)

欢迎您联系我们,一起交流技术。

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

芯驿电子自 2012 年成立以来,旗下 AUMO 与 ALINX 两大品牌,在智能车载与 FPGA 行业解决方案领域持续深耕。 ALINX 聚焦 FPGA 解决方案高端产品市场,并积极参与 FPGA 国产化应用发展。至今已推出 100 多款 FPGA SoM 模组和配套板卡,基本完成对 AMD FPGA 产品、紫光同创 FPGA 产品的全系列覆盖,产品远销海外 40 多个国家。 AUMO 专注智能车载,为自动驾驶技术开发破题。至今已推出车载仿真测试系统、视频数据采集、视频数据旁路采集分流、视频数据注入、车载摄像头、车载后视镜等产品线,满足车企和汽车产业链的车载产品开发需求。

微信公众号