找回密码
 立即注册
首页 业界区 安全 FPGA使用镜像加载技术来切换运行中的比特流文件 ...

FPGA使用镜像加载技术来切换运行中的比特流文件

事值 昨天 15:40
补档声明

由于我的博客服务器和备案到期,所以选择转移到博客园平台来进行保存和记录。以后也有可能会在上面不定期更新一些技术类博客。
1.png

前言

这是一种无需重新烧录比特就能切换FPGA正在运行的比特的方法。
分为两种,一种是全局可重构,也可以叫做启动镜像切换,本质上是将两份或多份比特流同时固化到FLASH中,在运行过程实时中切换使用哪一份比特,这是基于NOR FLASH的片上执行特性(暂且这么称呼,本质上是因为NOR只需要给地址就能出数据,没有译码转址这一过程) 。所以对于配置了NOR FLASH的FPGA板卡,我们可以通过ICAP原语来给出比特流加载的同步字,然后送入加载基地址,并给出加载命令,来进行当前执行比特流的切换。
另一种是部分可重构,这种要更复杂一点,但是本质上只不过是把重加载全局比特变成了重加载部分模块的比特,所以会有个画pblock的过程,相比于全局可重构,流程会复杂许多,而且如果是中间模块的替换,由于输入输出端口的变化,会造成一些时序约束的问题,且无法直接使用OOC IP核,只能把IP核做成网表再调用,在我自己的工程上对于资源利用率的降低作用不显著。本文就只着眼全局可重构。
全局可重构我目前探索出来的路径有两条,一条已经实现,就是后文的合并bit到一个mcs文件中,然后使用icape原语启动。另外的一条路是上位机通过pcie的dma通道,流式传输要切换的比特到板卡上,完成比特的切换,这条路还在摸索,如果能够完成的话,那么对于机箱上的FPGA板卡来说,就可以让上位机保存多份比特,在运行之中随便切换,完成FPGA板卡功能的更新或者切换。
下面仅从怎么做的描述如何将两个工程的比特流合并到同一个mcs文件下,并使用这个mcs来对fpga进行烧录固化,并编写简单的代码来调用icape原语来对启动地址进行切换,以达到不重新烧写比特就能进行工程的切换的方法。
有关FLASH的几个工程xdc约束

需要添加到工程的xdc中
  1. ############## FLASH ##################
  2. set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
  3. set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
  4. set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 1 [current_design]
  5. set_property CONFIG_MODE SPIx1 [current_design]
  6. # 如果 FLASH 大小大于等于 256Mb,要增加如下约束,否则高于24位的地址会被忽略,导致无法启动对应的 update 镜像
  7. set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
复制代码
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]压缩比特,这是一个蛮有用的选项,如果不使用压缩比特的话,那么任何一个工程,不论代码有多简单或者多复杂,都会生成一个同样大小的,未经过压缩的比特,对于7k325t会占用大概11MB的大小,更复杂的片子会更大。如果启用了,就会根据工程代码的复杂程度对比特进行压缩,一般来说都挺有效果的,能把最简单的LED流水灯工程压缩到几百KB的水平。能把我的工程压缩到5.5MB左右大小
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]设置烧录速度,50M是SPI时钟线上的时钟频率,一般的SPI存储芯片都能支持这个速率。
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 1SPI宽度,这是用于控制烧录程序的接口的,因为我们要使用Fallback,所以这里必须是x1
set_property CONFIG_MODE SPIx1配置模式宽度,和上面一样
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] 启用32bit地址线模式,如果FLASH大小大于等于256Mb,也就是32MB,需要启用这个约束,并且写入镜像的地址线的方法需要变动,见后文。我的板子上的s25fl256大小正好是256Mb,所以得开。
multiboot模块的调用方法示例
  1.     // ^ 全局可重构
  2.     multiboot_ctrl multiboot_ctrl_inst (
  3.         .clk  (clk_out_100),
  4.         .rst_n(sys_rst_n),
  5.         .multiboot_start(~reconfig_key_n),   // 使用外部按键触发
  6.         .multiboot_addr (32'h00500000),   // 加载0x00500000处的Golden Image
  7.         .busy_o()
  8.     );
复制代码
这里要注意的是给地址的要求,如果前面使能了32bit地址线,则要根据下文把multiboot_addr[31:8]写到WBSTAR[23:0]
[code]// ^ ICAP 原语实现程控 multiboot(多重启动),K7需要使用 ICAPE2 原语module multiboot_ctrl (    input wire clk,    input wire rst_n,    input wire        multiboot_start,  //触发Multiboot, 上升沿有效    input wire [31:0] multiboot_addr,   //要启动的Muliboot Image的起始地址    output reg busy_o);    //-------------------ICAPE2原语-----------------------------    wire        ICAPE2_CLK;    wire [31:0] ICAPE2_O;    reg         ICAPE2_CSIB;    wire [31:0] ICAPE2_I;    reg         ICAPE2_RDWRB;    assign ICAPE2_CLK = clk;    ICAPE2 #(        .DEVICE_ID         (32'h3651093),  // Specifies the pre-programmed Device ID value to be used for simulation purposes. K7-325T的为32'h3651093        .ICAP_WIDTH("X32"),  // Specifies the input and output data width.        .SIM_CFG_FILE_NAME("NONE")  // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation model.    ) ICAPE2_inst (        .O    (ICAPE2_O),     // 32-bit output: Configuration data output bus        .CLK  (ICAPE2_CLK),   // 1-bit input: Clock Input        .CSIB (ICAPE2_CSIB),  // 1-bit input: Active-Low ICAP Enable        .I    (ICAPE2_I),     // 32-bit input: Configuration data input bus        .RDWRB(ICAPE2_RDWRB)  // 1-bit input: Read/Write Select input    1对应rd,0对应wr    );    wire [31:0] Dummy = 32'hFFFFFFFF;    wire [31:0] Sync_Word = 32'hAA995566;    wire [31:0] NOOP = 32'h20000000;    wire [31:0] WR_WBSTAR = 32'h30020001;    /*When using ICAPE2 to set the WBSTAR address, the 24 most significant address bits should be written  to WBSTAR[23:0]. For SPI 32-bit addressing mode, WBSTAR[23:0] are sent as address bits [31:8]. The  lower 8 bits of the address are undefined and the value could be as high as 0xFF. Any bitstream  at the WBSTAR address should contain 256 dummy bytes before the start of the bitstream.*/    wire [31:0] WBSTAR = {3'b000, 5'h0, multiboot_addr[31:8]};    wire [31:0] WR_CMD = 32'h30008001;    wire [31:0] IPROG = 32'h0000000F;    //ICAPE2 字节序翻转    reg  [31:0]  wrdat;    assign ICAPE2_I = {        wrdat[24],        wrdat[25],        wrdat[26],        wrdat[27],        wrdat[28],        wrdat[29],        wrdat[30],        wrdat[31],        wrdat[16],        wrdat[17],        wrdat[18],        wrdat[19],        wrdat[20],        wrdat[21],        wrdat[22],        wrdat[23],        wrdat[8],        wrdat[9],        wrdat[10],        wrdat[11],        wrdat[12],        wrdat[13],        wrdat[14],        wrdat[15],        wrdat[0],        wrdat[1],        wrdat[2],        wrdat[3],        wrdat[4],        wrdat[5],        wrdat[6],        wrdat[7]    };    //------------------------FSM----------------------------------    localparam S_IDLE = 16'h0001;    localparam S_DUMMY = 16'h0002;    localparam S_SYN_WORD = 16'h0004;    localparam S_NOOP1 = 16'h0008;    localparam S_WR_WBSTAR = 16'h0010;    localparam S_WBSTAR = 16'h0020;    localparam S_WR_CMD = 16'h0040;    localparam S_IPROG = 16'h0080;    localparam S_NOOP2 = 16'h0100;    localparam S_STOP = 16'h0200;    wire multiboot_start_pe;    reg  multiboot_start_d0;    reg  multiboot_start_d1;    assign multiboot_start_pe = multiboot_start_d0 & (~multiboot_start_d1);    always @(posedge clk) begin        multiboot_start_d0

相关推荐

您需要登录后才可以回帖 登录 | 立即注册