FPGA控制W25Q64FV实现FPGA配置在线重构

1.硬件环境

        FPGA型号SPARTAN-6 XS6SLX9TQG144I

        FLASH型号W25Q64FV

         FPGA启动方式配置为主串模式(M[1:0] = 0x01)。

        Spartan-6 FPGA Configuration User Guide(ug380)中对FPGA配置为主串模式的说明如下表所示。

2.实现过程

3.FLASH相关操作指令

3.1 芯片擦除

        因为该片FLASH仅仅是用来作为FPGA程序的存储介质,故而在重构是采用直接芯片擦除的方式。若是FLASH还有不可擦除的扇区,则需要选择扇区擦除的方式。W25Q64FV对芯片擦除的时序如下图。

3.2 页编程

         每页最大写入256个字节,即地址范围需是0xXXXX00~0xXXXXFF。所以本人上位机每次发送256个字节,直至最后一帧。最后一帧是有多少写多少。

3.3  写使能/写不使能

        在执行PROGRAM和ERASE操作之前应先进行写使能,执行完后进行写不使能操作。

 3.4 读状态寄存器

       读状态寄存器的目的是判断当前ERASE和PROGRAM操作是否完成。状态寄存器Bit0位等于1则表示忙,等于0表示操作已完成。

状态寄存器1说明

4 程序设计

//instruction_type == 4'd1:	program
//instruction_type == 4'd2:	read data
//instruction_type == 4'd3:	chip erase
//instruction_type == 4'd4:	write disable
//instruction_type == 4'd5:	write enable
//instruction_type == 4'd6:	read status register
//instruction_type == 4'd7:	read device ID
reg [15:0] read_length,write_length;
reg [15:0] write_count;
reg spi_valid;
reg [3:0] state;

assign flash_clk = spi_valid ? CLK : 1'b0;
//assign fifo_rd_clk = fifo_rd_en? CLK : 1'b0;
assign fifo_rd_clk = CLK;

parameter 					idle		=	4'd0,
						send_inst	=	4'd1,
						send_addr	=	4'd2,
						send_data	=	4'd3,
						wait_data	=	4'd4,
						send_done	=	4'd5;

always @(negedge CLK or negedge RSTn)
if(!RSTn) begin
		flash_csn <= 1'b1;
		flash_dataout <= 1'b0;
		frame_done <= 1'b0;
		cnt_cmd <= 5'd7;
		fifo_rd_en <= 1'b0;
		read_cmd <= 1'b0;	
		write_length <= 16'd0;
		read_length <= 16'd0;
		write_count <= 16'd0;
		spi_valid <= 1'b0;
		state <= idle;
end else begin
		case(state)
				idle:			begin
										flash_csn <= 1'b1;
										cnt_cmd <= 5'd7;
										frame_done <= 1'b0;
										write_count <= 16'b0;
										if(instruction_type[3] == 1'b1) begin
												state <= send_inst;
										end else begin
												state <= idle;
										end
								end
				send_inst:	if(cnt_cmd > 4'd0) begin
										flash_csn <= 1'b0;
										spi_valid <= 1'b1;
										flash_dataout <= flash_instruction[cnt_cmd];
										cnt_cmd <= cnt_cmd - 1'b1;
								end else begin
										flash_dataout <= flash_instruction[0];
										if((instruction_type[2:0] == 3'd3) || (instruction_type[2:0] == 3'd4) || (instruction_type[2:0] == 3'd5)) begin
												cnt_cmd <= 5'd7;
												state <= send_done;
										end else if(instruction_type[2:0] == 3'd6) begin
												read_length <= 16'd2;
												state <= wait_data;
										end else begin
												cnt_cmd <= 5'd23;
												state <= send_addr;
										end
								end
				send_addr:	if(cnt_cmd > 4'd0) begin
										flash_dataout <= flash_address[cnt_cmd];
										cnt_cmd <= cnt_cmd - 1'b1;
								end else begin
										flash_dataout <= flash_address[0];
										if(instruction_type[2:0] == 3'd1) begin
												cnt_cmd <= 5'd7;
												//write_length <= 16'd20;
												write_length <= frame_write_length;
												fifo_rd_en <= 1'b1;
												state <= send_data;
										end else if(instruction_type[2:0] == 3'd2) begin
												read_length <= 16'd256;
												cnt_cmd <= 5'd7;			//unused
												state <= wait_data;
										end else begin	
												read_length <= 16'd2;
												cnt_cmd <= 5'd7;			//unused
												state <= wait_data;
										end
								end
				send_data:	if(write_count < write_length - 1'b1) begin
										if(cnt_cmd == 5'd0) begin
												cnt_cmd <= 5'd7;
												fifo_rd_en <= 1'b1;
												write_count <= write_count + 1'b1;
												flash_dataout <= flash_data_i[0];
										end else begin
												fifo_rd_en <= 1'b0;
												flash_dataout <= flash_data_i[cnt_cmd];
												cnt_cmd <= cnt_cmd - 1'b1;
										end
								end else begin
										if(cnt_cmd == 5'd0) begin
												cnt_cmd <= 5'd7;
												//fifo_rd_en <= 1'b1;
												//write_count <= write_count + 1'b1;
												write_count <= 16'd0;
												flash_dataout <= flash_data_i[0];
												//spi_valid <= 1'b0;
												fifo_rd_en <= 1'b0;
												state <= send_done;
										end else begin
												fifo_rd_en <= 1'b0;
												flash_dataout <= flash_data_i[cnt_cmd];
												cnt_cmd <= cnt_cmd - 1'b1;
										end
//										
//										spi_valid <= 1'b0;
//										fifo_rd_en <= 1'b0;
//										state <= send_done;
								end
				wait_data:	if(read_count < read_length) begin
										read_cmd <= 1'b1;	
										state <= wait_data;
								end else begin
										read_cmd <= 1'b0;	
										spi_valid <= 1'b0;
										state <= send_done;
								end
				send_done:	begin
										flash_csn <= 1'b1;
										spi_valid <= 1'b0;
										frame_done <= 1'b1;
										state <= idle;
								end
				default:		state <= idle;
		endcase
end

reg [15:0] read_count;
reg [3:0] j;
reg [7:0] recv_data;


assign flash_data_o = (read_cmd && (j == 4'd7))? recv_data : flash_data_o;

always @(posedge CLK or negedge RSTn)
if(!RSTn) begin
		read_over <= 1'b0;
		read_count <= 16'd0;
		recv_data <= 8'h00;
		flash_data_valid <= 1'b0;
end else begin
		if(read_cmd) begin
				if(j == 4'd0) begin
						j <= 4'd7;
						recv_data[j] <= flash_datain;
						read_count <= read_count + 1'b1;
						flash_data_valid <= 1'b1;
				end else begin
						j <= j - 1'b1;
						recv_data[j] <= flash_datain;
						flash_data_valid <= 1'b0;
				end
		end else begin
				j <= 4'd7;
				read_count <= 16'd0;
				read_over <= 1'b0;
				flash_data_valid <= 1'b0;
		end
end

endmodule

 

//instruction_type == 4'd1:	program
//instruction_type == 4'd2:	read data
//instruction_type == 4'd3:	chip erase
//instruction_type == 4'd4:	write disable
//instruction_type == 4'd5:	write enable
//instruction_type == 4'd6:	read status register
//instruction_type == 4'd7:	read device ID

always @(posedge CLK or negedge RSTn)
if(!RSTn) begin
	instruction_type <= 4'b0000;
	flash_instruction <= 8'h00;
	flash_address <= 24'd0;
	flash_address_r <= 24'd0;
	frame_write_address <= 24'd0;
	erase_finish <= 1'b0;
	flash_program_finish <= 1'b0;
	DeviceID <= 8'h00;
	counter <= 32'd0;
	state <= 5'd0;
end else begin
	case(state)
		5'd0:		if(counter == 32'd1000) begin		//wait a moment
						counter <= 32'd0;
		    			state <= state + 1'b1;
					end else begin
						counter <= counter + 1'b1;
						state <= state;
					end
		5'd1:		if(frame_done) begin				//read device ID
						DeviceID <= flash_data_o;
						instruction_type <= 4'b0000;
						flash_address <= 24'd0;
						flash_instruction <= 8'h00;
						state <= state + 1'b1;
					end else begin
						instruction_type <= 4'b1111;
						flash_address <= 24'd0;
						flash_instruction <= 8'h90;
						state <= state;
			    	end
		5'd2:		if(erase_start) begin					//erase chip
						frame_write_address <= 24'd0;
						state <= state + 1'b1;
					end else if(pos_frame_valid) begin		//program 
						flash_address_r <= frame_write_address;
						frame_write_address <= frame_write_address + 24'h000100;
						state <= 5'd9;
					end else if(pos_send_valid) begin		//read data
						state <= 5'd15;
					end else begin
						erase_finish <= 1'b0;
						flash_program_finish <= 1'b0;
						state <= state;
					end
				//chip erase sequency
		5'd3:		if(frame_done) begin		//write enable instruction
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1101;
									flash_address <= 24'd0;
									flash_instruction <= 8'h06;
									state <= state;
							end
				5'd4:		if(frame_done) begin				//erase chip
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1011;
									flash_address <= 24'd0;
									flash_instruction <= 8'hC7;
									state <= state;
							end
				5'd5:		if(counter == 32'd1000000) begin		//wait one second
									counter <= 32'd0;
									state <= state + 1'b1;
							end else begin
									counter <= counter + 1'b1;
									state <= state;
							end
				5'd6:		if(frame_done) begin				//read status register 1
									if(flash_data_o[0] == 1'b0) begin
											instruction_type <= 4'b0000;
											flash_address <= 24'd0;
											flash_instruction <= 8'h00;
											state <= state + 1'b1;
									end else begin
											instruction_type <= 4'b1110;
											flash_address <= 24'd0;
											flash_instruction <= 8'h05;
											state <= state;
									end
							end else begin
									instruction_type <= 4'b1110;
									flash_address <= 24'd0;
									flash_instruction <= 8'h05;
									state <= state;
							end
				5'd7:		if(frame_done) begin				//write disable
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1100;
									flash_address <= 24'd0;
									flash_instruction <= 8'h04;
									state <= state;
							end
				5'd8:		if(frame_done) begin				//read status register 1
									if(flash_data_o[0] == 1'b0) begin
											instruction_type <= 4'b0000;
											flash_address <= 24'd0;
											flash_instruction <= 8'h00;
											state <= 5'd2;
									end else begin
											instruction_type <= 4'b1110;
											flash_address <= 24'd0;
											flash_instruction <= 8'h05;
											state <= state;
									end
							end else begin
									erase_finish <= 1'b1;
									instruction_type <= 4'b1110;
									flash_address <= 24'd0;
									flash_instruction <= 8'h05;
									state <= state;
							end
				//write sequency
				5'd9:		if(frame_done) begin		//write enable instruction
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1101;
									flash_address <= 24'd0;
									flash_instruction <= 8'h06;
									state <= state;
							end
				5'd10:	if(counter == 32'd10) begin		//wait a moment
									counter <= 32'd0;
									state <= state + 1'b1;
							end else begin
									counter <= counter + 1'b1;
									state <= state;
							end
				5'd11:	if(frame_done) begin				//program 256 data
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1001;
									//flash_address <= 24'h800000;
									flash_address <= flash_address_r;
									flash_instruction <= 8'h02;
									state <= state;
							end
				5'd12:	if(counter == 32'd1000) begin		//wait a moment
									counter <= 32'd0;
									state <= state + 1'b1;
							end else begin
									counter <= counter + 1'b1;
									state <= state;
							end
				5'd13:	if(frame_done) begin				//read status register 1
									if(flash_data_o[0] == 1'b0) begin
											instruction_type <= 4'b0000;
											flash_address <= 24'd0;
											flash_instruction <= 8'h00;
											state <= state + 1'b1;
									end else begin
											instruction_type <= 4'b1110;
											flash_address <= 24'd0;
											flash_instruction <= 8'h05;
											state <= state;
									end
							end else begin
									instruction_type <= 4'b1110;
									flash_address <= 24'd0;
									flash_instruction <= 8'h05;
									state <= state;
							end
				5'd14:	if(frame_done) begin				//write disable
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= 5'd2;
							end else begin
									flash_program_finish <= 1'b1;
									instruction_type <= 4'b1101;
									flash_address <= 24'd0;
									flash_instruction <= 8'h04;
									state <= state;
							end
				//read sequency			
				5'd15:	if(frame_done) begin				//read status register 1
									if(flash_data_o[0] == 1'b0) begin
											instruction_type <= 4'b0000;
											flash_address <= 24'd0;
											flash_instruction <= 8'h00;
											state <= state + 1'b1;
									end else begin
											instruction_type <= 4'b1110;
											flash_address <= 24'd0;
											flash_instruction <= 8'h05;
											state <= state;
									end
							end else begin
									instruction_type <= 4'b1110;
									flash_address <= 24'd0;
									flash_instruction <= 8'h05;
									state <= state;
							end
				5'd16:	if(frame_done) begin				//read 256
									instruction_type <= 4'b0000;
									flash_address <= 24'd0;
									flash_instruction <= 8'h00;
									state <= state + 1'b1;
							end else begin
									instruction_type <= 4'b1010;
//									flash_address <= 24'h023000;
									flash_address <= flash_address_r;
									flash_instruction <= 8'h03;
									state <= state;
							end
				5'd17:	state <= 5'd2;	
				default: state <= 5'd0;	
		endcase
end

程序链接:

链接:https://pan.baidu.com/s/1YxvZhcjUr5azazlGKVrD4Q 
提取码:gb8e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值