7系列FPGA动态配置

        由于之前在基础学习阶段不太重视FPGA的配置,但是在做项目过程中发现需要特别关注这部分内容,而且FPGA自带的配置会给最终设备的操作提供很多便利,尤其是动态配置(通俗讲就是可以做到不断电重启),所以这一篇介绍AMD FPGA此部分内容。

       虽然每个系列配置接口都不同,但7系列芯片的配置步骤步骤对于所有芯片都是相同的。如果需要做到在线更新以及动态配置,一般需要准备两个固件,Golden Image(Base Address)和Multiboot Image(Upper Address)。首先,Golden Image从Base Address加载,接下来,Golden Image将触发要加载的MultiBoot Image。如果在Upper Address加载Multiboot Image时出错,将从Base Address加载Golden Image。

        IPROG命令是PROGRAM_B引脚功能的一个子集。IPROG命令不会擦除用于启动多启动和回退的WBSTAR、计时器、BSPI和引导寄存器。IPROG命令触发初始化,当发出IPROG命令并尝试配置时,INIT和DONE都变为Low。该命令可以通过用户逻辑控制ICAPE2发出IPROG命令。这允许用户逻辑重新配置芯片。

        WBSTAR(热启动启动地址)寄存器保存配置控制器在发出IPROG命令后使用的地址。这个寄存器可以从bit流中加载,或从ICAPE2中加载。如果在bit流中没有设置寄存器,则加载它的默认值为0。因此,在Golden Image设置WBSTAR值并启动MultiBoot Image后。在通电时,设备向闪灯发出读取命令,然后发出一个开始地址为0。在加载WBSTAR命令并发出IPROG命令后,配置控制器从WBSTAR地址指定的地址发出读取命令。

命令的顺序:

        在配置逻辑接收到IPROG命令后,FPGA将重置除专用重配置逻辑之外的所有内容,并且INIT_B和DONE引脚变低。在FPGA清除所有配置内存后,INIT_B再次启动。然后将WBSTAR中的值用于起始地址。该配置模式决定了哪些引脚是由WBSTAR控制的。

写入数据需要进行位交换,无论数据的方向如何,每个字节的MSB都指向D0位:

  • 在数据的位交换版本中,进入D0的位是最正确的位;
  • 在非位交换的数据中,到达D0的位是最左边的位;

        数据是否必须进行位交换,这完全依赖于应用程序。位交换适用于Serial, SelectMAP, 或者BPI PROM files文件,以及ICAPE2接口。

 重启模块代码

/* 
 * file			: multiboot_ctrl.v
 * author		: 今朝无言
 * Lab			: WHU-EIS-LMSWE
 * date			: 2023-11-30
 * version		: v1.0
 * description	: ICAP 原语实现程控 multiboot(多重启动),K7需要使用 ICAPE2 原语
 * Copyright © 2023 WHU-EIS-LMSWE, All Rights Reserved.
 */
`default_nettype none
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
);

//-------------------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'h362D093),	// 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		<= multiboot_start;
	multiboot_start_d1		<= multiboot_start_d0;
end

reg		[15:0]	state		= S_IDLE;
reg		[15:0]	next_state;

always @(posedge clk) begin
	if(~rst_n) begin
		state	<= S_IDLE;
	end
	else begin
		state	<= next_state;
	end
end

always @(*) begin
	case(state)
	S_IDLE: begin
		if(multiboot_start_pe) begin
			next_state	<= S_DUMMY;
		end
		else begin
			next_state	<= S_IDLE;
		end
	end
	S_DUMMY:		next_state	<= S_SYN_WORD;
	S_SYN_WORD:		next_state	<= S_NOOP1;
	S_NOOP1:		next_state	<= S_WR_WBSTAR;
	S_WR_WBSTAR:	next_state	<= S_WBSTAR;
	S_WBSTAR:		next_state	<= S_WR_CMD;
	S_WR_CMD:		next_state	<= S_IPROG;
	S_IPROG:		next_state	<= S_NOOP2;
	S_NOOP2:		next_state	<= S_STOP;
	S_STOP:			next_state	<= S_IDLE;
	default:		next_state	<= S_IDLE;
	endcase
end

always @(posedge clk) begin
	case(state)
	S_IDLE: begin
		wrdat			<= 32'd0;
		ICAPE2_CSIB		<= 1'b1;
		ICAPE2_RDWRB	<= 1'b1;
	end
	S_DUMMY: begin
		wrdat			<= Dummy;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_SYN_WORD: begin
		wrdat			<= Sync_Word;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_NOOP1: begin
		wrdat			<= NOOP;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_WR_WBSTAR: begin
		wrdat			<= WR_WBSTAR;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_WBSTAR: begin
		wrdat			<= WBSTAR;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_WR_CMD: begin
		wrdat			<= WR_CMD;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_IPROG: begin
		wrdat			<= IPROG;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_NOOP2: begin
		wrdat			<= NOOP;
		ICAPE2_CSIB		<= 1'b0;
		ICAPE2_RDWRB	<= 1'b0;
	end
	S_STOP: begin
		wrdat			<= 32'd0;
		ICAPE2_CSIB		<= 1'b1;
		ICAPE2_RDWRB	<= 1'b1;
	end
	default: begin
		wrdat			<= 32'd0;
		ICAPE2_CSIB		<= 1'b1;
		ICAPE2_RDWRB	<= 1'b1;
	end
	endcase
end

always @(*) begin
	case(state)
	S_IDLE:		busy	<= 1'b0;
	default:	busy	<= 1'b1;
	endcase
end

endmodule

顶层文件: 

//生成2个点灯的程序,使用ICAP来回切换这两个Image
//本工程作为 Golden Image 存入地址 0
`default_nettype none
module Top(
input	wire			clk_sys,	//OXCO_10M
input   wire 			sys_rst_n,

input	wire	[1:0]	Key,
output	wire	[3:0]	LED
);


reg [31:0]start_cnt;
reg start_en;
always@(posedge clk_sys)begin
	if(!sys_rst_n)begin
		start_cnt <= 32'd0;
		start_en <= 0;
	end
	else if(start_cnt == 32'd49_999_999)begin
		start_en <= 1'b1;
	end
	else if(start_en == 1'b0)begin
		start_cnt <=  start_cnt + 1'b1;
	end
end

reg [31:0]reboot_addr;
reg key_sig;
always@(posedge clk_sys)begin
	if(!sys_rst_n)begin
		reboot_addr <= 32'h00400000;
		key_sig <= 1'b0;
	end
	else if(~Key[1])begin
		reboot_addr <= 32'h00000000;
		key_sig <= 1'b1;
	end
	else if(~Key[0])begin
		reboot_addr <= 32'h00400000;
		key_sig <= 1'b1;
	end
end

Multiboot_Ctrl multiboot_ctrl_inst(
	.clk				(clk_sys),
	.rst_n				(1'b1),

	.multiboot_start	(key_sig),
	.multiboot_addr		(reboot_addr),		//加载0x01000000处的Multiboot Image

	.busy				()
);


assign	LED		= (start_en == 1'b0) ? 4'b1100 : 4'b1111;


endmodule

xdc文件内添加的代码: 

set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design]

参考文章

ug470_7Series_Config.pdf 

K7系列FPGA多重启动(Multiboot)-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值