中科亿海微Flash擦写读

发布时间:2024年01月01日

引言


????????在数字存储技术的领域中,闪存(Flash)是一种非易失性存储器,以其高速读写、低功耗和较高的可靠性而备受关注。相比于传统的磁盘存储技术,闪存具有更小的体积、更高的数据密度和更长的寿命,因此在各种应用中得到了广泛的应用。闪存最初应用于便携式设备和嵌入式系统中,如手机、平板电脑和闪存卡等。随着技术的不断进步,闪存逐渐取代了传统的硬盘驱动器,成为许多计算机系统的首选存储介质。

????????闪存的工作原理与传统的存储技术有所不同。它采用了一种称为“浮体栅结构”的技术,通过在晶体管中添加控制门、浮动门和栅极等元件,实现了数据的存储和擦除。这种浮体栅结构使得闪存能够在无电源供应的情况下保持数据的稳定性,同时具有较快的读写速度和较低的功耗。

闪存的应用领域包括但不限于:
1. 便携式设备和嵌入式系统:如手机、平板电脑、存储卡和嵌入式系统模块等。
2. 个人电脑和服务器:闪存固态硬盘(SSD)已经成为替代传统硬盘驱动器的首选存储介质。
3. 汽车电子:闪存被用于车载娱乐系统、导航系统和车载通信系统等。
4. 云存储和大数据中心:闪存被用于高速缓存、快速存储和大规模数据处理等。


问题分析

1. 存储密度和容量:


????????闪存的存储密度和容量是一个重要的问题。随着技术的不断发展,闪存的存储密度和容量不断增加,但如何保持稳定的性能和可靠性仍然是一个挑战。如何平衡存储密度和容量与数据可靠性和读写速度之间的关系,是一个需要解决的问题。

2. 读写速度和性能:


????????闪存的读写速度和性能是另一个重要的问题。闪存的读取速度通常比写入速度更快,而写入速度受到擦除操作的限制。如何提高闪存的读写速度,并解决擦除操作带来的延迟和性能问题,是一个需要解决的挑战。

3. 寿命和耐久性:


????????闪存的寿命和耐久性是一个关键问题。闪存存储单元在重复擦写操作后会逐渐损耗,导致寿命减少。如何提高闪存的耐久性,减少擦写操作对存储单元的损耗,是一个需要解决的问题。

4. 错误校正和数据完整性:


????????在闪存中,数据的正确性和完整性是至关重要的。由于闪存存储单元的损耗和环境因素的影响,数据可能会发生错误或丢失。如何设计合适的错误校正和纠正机制,以确保数据的正确性和完整性,是一个需要解决的问题。

5. 垃圾回收和空间管理:


????????闪存中的垃圾回收和空间管理是一个关键问题。在闪存中,擦除操作是一个相对较慢的过程,而闪存存储单元的擦除前必须是空白的。如何高效地进行垃圾回收和空间管理,以充分利用闪存空间并减少擦除操作次数,是一个需要解决的挑战。


解决方案

1. 存储密度和容量:


????????为了提高存储密度和容量,可以采用更高密度的闪存芯片和多级存储技术,如多层堆叠存储器(MLC)和三级堆叠存储器(TLC)。此外,可以采用更高级别的错误校正码(ECC)来增加数据的存储密度。

2. 读写速度和性能:


????????为了提高读写速度和性能,可以采用并行读写和多通道设计,以实现并发的数据访问。同时,可以优化闪存控制器的算法和数据缓存机制,以减少读写操作的延迟。

3. 寿命和耐久性:


????????为了提高闪存的寿命和耐久性,可以采用动态均衡和可编程的擦写算法,以均衡存储单元的使用和减少擦写操作的次数。此外,可以实施写放大和数据分散技术,以减少对特定存储单元的过度擦写。

4. 错误校正和数据完整性:


????????为了确保数据的正确性和完整性,可以采用强大的错误校正和纠正机制,如BCH(Bose-Chaudhuri-Hocquenghem)码和LDPC(低密度奇偶校验)码。这些机制可以检测和纠正数据传输过程中可能出现的错误。

5. 垃圾回收和空间管理:


????????为了高效地进行垃圾回收和空间管理,可以采用闪存控制器中的智能算法和策略。这些算法和策略可以根据存储单元的使用情况和数据访问模式,动态地进行垃圾回收和数据迁移,以减少擦除操作的次数并提高空间利用率。

实施步骤

????????该程序利用FPGA实现了对Flash存储器的多项功能,包括写入使能、整片擦除、全片写入和全片数据读取。通过使用FPGA作为控制器,程序能够有效地控制Flash存储器的写入操作,实现数据的可靠存储。同时,通过整片擦除和全片写入功能,可以在需要时快速清除和写入整个Flash存储器。而全片数据读取功能使得程序能够高效地读取Flash存储器中的全部数据。这些功能的实现,为Flash存储器的使用提供了更大的灵活性和便利性。

`timescale 1 ps/ 1 ps
//
// Company:
// Engineer:
//
// Create Date: 11-08-2022 16:06:19
// Design Name:
// Module Name: flash_control
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies: 
//
// Revision:
// Additional Comments:
//
//

module flash_control(
	input 			wire			clk				,
	input			wire			rst_n			,
	input  [7:0]  					O_data_out  	, 
	input         					O_tx_done   	, 
	input         					O_rx_done   	, 
	input 							Clock_open		,
	output reg        				I_rx_en     	, 
	output reg        				I_tx_en     	, 
	output reg [7:0]  				I_data_in   	, 
	output reg        				O_spi_cs    	, 
	output reg						strswitch		,
	output reg						flash_done		,
	output reg 						response		,
	output reg 						control_done		/*synthesis noprune*/,
	output reg 						Register_error	,	//无法写入寄存器
	output reg 						DATA_error		,	//数据错误
	output reg [9:0]				record  		,
	output reg [20:0]				Erase_count		
);

//------------------------------------------------------------------------------
//----------- Registers Declarations -------------------------------------------
//------------------------------------------------------------------------------
reg [7:0]	state/* synthesis preserve */;
reg [63:0]	cnt/* synthesis preserve */;
reg [7:0]   DATA/* synthesis preserve */;
reg [7:0]	DATA_out/* synthesis preserve */;
reg [23:0]	addr2/* synthesis preserve */;
reg [23:0]	addr;
reg [2:0]	count/* synthesis preserve */;
reg 		d0,d1;
reg [7:0]	state_reg/* synthesis preserve */;
reg 			a;
reg 			Sector_ER_DONE;


wire 			pos_Clock_open;


assign pos_Clock_open	=	d0	&	(!d1);

//写启动 写禁止
parameter  	Write_Enable					=	8'h06;		//写启动
parameter  	Write_Disable					=	8'h04;		//写禁止
parameter	Read_Data						=	8'h03;		//读数据
parameter	Sector_Erase					=	8'h20;		//扇区擦除
parameter	Chip_Erase						=	8'hc7;		//芯片擦除
parameter	Power_down						=	8'hb9;		//芯片断电
parameter	Quad_Input_Page_Program			=	8'h32;		//页写入
parameter	Block_Erase_64KB				=	8'hd8;		//64K块擦除
parameter   Page_Program					=	8'h02;		//页编程
parameter 	Fast_Read						=	8'h0b;		//快速读取
parameter	Fast_Read_Quad_Output			=	8'h6b;		//读取4页数据
parameter 	Write_Enable_Register			=	8'h50;		//写状态寄存器

//写入状态 读取状态
parameter	Read_Status_Register_1		=	8'h05;			//读状态寄存器1
parameter	Read_Status_Register_2		=	8'h35;			//读状态寄存器2
parameter	Read_Status_Register_3		=	8'h15;			//读状态寄存器2

parameter	Write_Status_Register_1		=	8'h01;			//写状态寄存器1
parameter	Write_Status_Register_2		=	8'h31;			//写状态寄存器2
parameter	Write_Status_Register_3		=	8'h11;			//写状态寄存器3

always @ (posedge clk ) begin 
	
		state_reg	<=	state;

end 

always @ (posedge clk ) begin 
	if (!rst_n)
	 begin 
		d0	<=	1'b0;
		d1	<=	1'b0;
	 end 
	else 
	 begin 
		d0	<=	Clock_open;
		d1	<=	d0;
	 end 
end 

always @ (posedge clk ) begin 
	if (!rst_n)
		a		<=	1'b0;
	else
		a		<=	1'b1;
end 

always @ (posedge clk) begin 
	if (!rst_n)
	 begin 
		state					<=	8'd0		;
		cnt					<=	64'd0		;
		I_rx_en				<=	1'b0		;
		I_tx_en				<=	1'b0		;
		I_data_in			<=	8'd0		;
		DATA					<=	8'd0		;
		O_spi_cs				<=	1'b1		;
		strswitch			<=	1'b1		;	
		addr2					<=	24'd0		;
		addr					<=	24'd0		;
		DATA_out				<=	8'd0		;
		count					<=	3'd0		;
		flash_done			<=	1'b0		;
		response				<=	1'b0		;
		Register_error		<=	1'b0		;
		DATA_error			<=	1'b0		;
		control_done		<=	1'b0		;
		record				<=	10'd0		;
		Erase_count			<=	21'd0		;
		Sector_ER_DONE		<=	1'b0		;
	 end 
	else 
		case (state)
			0:begin 
				if (cnt	==	5000000-1)//5000000-1
				 begin //5秒
					addr					<=	24'd0		;
					Erase_count			<=		21'd0;
					cnt					<=		64'd0;
					state					<=		state		+	1'b1;
					count					<=		3'd0;
					response				<=		1'b0;
					Register_error		<=		Register_error;
					DATA_error			<=		DATA_error;
					control_done		<=		1'b0;
					record				<=		record;
				 end 
				else if (a)
				 begin 
					addr					<=	24'd0		;
					cnt					<=		cnt		+	1'b1;
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b0;
					O_spi_cs			<=		1'b1;
					strswitch			<=		1'b1;
					control_done		<=		1'b0;
					record				<=		record;
				 end 
				else 
				 begin 
					cnt					<=	64'd0;
				 end 
			end 
			//***********************写启动
			1:begin 
					DATA					<=		8'hff;
					Erase_count			<=		Erase_count;
					state				<=		state		+	1'b1;
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b1;
					O_spi_cs			<=		1'b0;
					I_data_in			<=		Write_Enable;
					strswitch			<=		1'b1;		
					addr2				<=		24'd0;
					count				<=		count	+	1'b1;
					control_done		<=		1'b0;
			end 
			2:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 	
					state				<=		state;
			end 
			//***********************全片擦除
			3:begin 
					I_tx_en				<=		1'b0;
					O_spi_cs			<=		1'b1;
					state				<=		state	+	1'b1;
			end 
			4:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		Chip_Erase;	
				record					<=		record	+	1'b1;
				control_done			<=		1'b0	;
			end 
			5:begin 
				if (O_tx_done)
				 begin 
					control_done		<=		1'b0;
					state				<=		state	+	1'b1;
				 end 
				else 	
				 begin 
					control_done		<=		1'b0;
					state				<=		state;
				 end 
			end 
			6:begin 
					O_spi_cs			<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
					DATA_out			<=		8'haa;
			end 
			//***********************读取状态寄存器
			7:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		Read_Status_Register_1;
			end 
			8:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 
					state				<=		state;
			end 
			9:begin //读写切换
					I_rx_en				<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************读数据
			10:begin 
				if (O_rx_done)
				 begin 
					DATA				<=		O_data_out;
					state				<=		state	+	1'b1;
				 end 
				else 
					state				<=		state;
			end 
			//***********************判断读取数据
			11:begin 	
				if (DATA[0]	==	0)			
				 begin 
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1;
					cnt					<=		64'd0;
					Register_error		<=		1'b0;
				 end 
				else 
				 begin 
					Register_error		<=		1'b1;
					state				<=		state	-	1;
				 end 
			end 
			12:begin //全片擦除完成 进行写操作
					Sector_ER_DONE		<=		1'b0;
					O_spi_cs				<=		1'b1;
					state					<=		state	+	1;
					Erase_count			<=		Erase_count	+1;
			end 
			//***********************写启动
			13:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		Write_Enable;	
			end 
			14:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 	
					state				<=		state;
			end 
			15:begin 
					O_spi_cs			<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************写状态寄存器
			16:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		Write_Enable_Register;	
			end 
			17:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 	
					state				<=		state;
			end 
			18:begin 
					O_spi_cs			<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************写状态
			19:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		Write_Status_Register_2;	
			end 
			20:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 
					state				<=		state;
			end 
			21:begin 
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************写状态数据
			22:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs				<=		1'b0;
				state					<=		state	+	1'b1;
				strswitch				<=		1'b1;	
				I_data_in				<=		8'h02;
			end 
			23:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 		
					state				<=		state;
			end 
			24:begin
					O_spi_cs			<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************读状态
			25:begin 
				I_tx_en					<=		1'b1;
				O_spi_cs					<=		1'b0;
				state						<=		state	+	1'b1;
				strswitch				<=		1'b1;
				I_data_in				<=		Read_Status_Register_2;	
			end 
			26:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 
					state				<=		state;
			end 
			27:begin 
//					DATA					<=		8'hff;	
					control_done		<=		1'b0;
					I_rx_en				<=		1'b1;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1'b1;
			end 
			//***********************读数据
			28:begin 
				if (O_rx_done)
				 begin 
					DATA				<=		O_data_out;
					state				<=		state	+	1'b1;
				 end 
				else 
					state				<=		state;
			end 
			//***********************判断读取数据
			29:begin 	
				if (DATA[1:0]	==	2'b10)			
				 begin 
					O_spi_cs			<=		1'b1;
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b0;
					state				<=		state	+	1;
					cnt					<=		64'd0;
					Register_error		<=		1'b0;
				 end 
				else 
				 begin 
					Register_error		<=		1'b1;
					state				<=		state	+	1;
				 end 
			end 
			30:begin 
				if (cnt		>=		500000-1)
				 begin 
					cnt					<=		64'd0;
					state				<=		state	+	1'b1;
				 end 
					cnt					<=		cnt	+	1'b1;
			end 
			//***********************等待buf时间缓存
			31:begin 
				if (cnt	>=	500)//5000000-1
				 begin 
					cnt					<=		64'd0;
					state				<=		state		+	1'b1;
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b1;
					O_spi_cs			<=		1'b0;
					I_data_in			<=		Write_Enable;	
					strswitch			<=		1'b1;		
//					count				<=		25'd0;
				 end 
				else 
				 begin 
					cnt					<=		cnt		+	1'b1;
					I_rx_en				<=		1'b0;
					I_tx_en				<=		1'b0;
					O_spi_cs			<=		1'b1;
					strswitch			<=		1'b1;
				 end 
			end 
			32:begin 
				if (O_tx_done)
					state				<=		state	+	1'b1;
				else 	
					state				<=		state;
			end 
			33:begin 
					I_tx_en				<=		1'b0;
					O_spi_cs			<=		1'b1;
					state				<=		state	+	1'b1;
			end 
			//***********************页写入
			34:begin 
					I_tx_en				<=		1'b1;
					O_spi_cs			<=		1'b0;
					I_data_in			<=		Quad_Input_Page_Program;	
					state				<=		state	+	1'b1;
			end 
			35:if (O_tx_done)
				 begin 
					I_data_in			<=		addr2[23:16];
					state				<=		state	+	1'b1;
				 end 
				else 
					state				<=		state;
			36:begin 
				if (O_tx_done)
				 begin 
					I_data_in			<=		addr2[15:8];
					state				<=		state	+	1'b1;
				 end 
				else 
					state				<=		state;
			end 
			37:begin 
				if (O_tx_done)
				 begin 
					I_data_in			<=		addr2[7:0];
					state				<=		state	+	1'b1;
				 end 
				else 
					state				<=		state;
			end 
			38:begin 								//提前切换
				if (O_tx_done)
				 begin 
					strswitch			<=	1'b0;		//使用并行
					state				<=	state	+	1'b1;
				 end 
				else 
					state				<=	state;
			end 
			39:begin 
					I_tx_en				<=	1'b0;
					state				<=	state	+	1'b1;
			end 
			40:begin 
					I_tx_en				<=	1'b1;
					I_data_in			<=	DATA_out;
					state				<=	state	+	1'b1;
					cnt					<=	cnt	+	1'b1;
			end 
			41:begin 
				if (cnt	>=	257)
				 begin 
					cnt					<=	64'd0;
					state				<=	state	+	2;
				 end 
				else if (O_tx_done)
				 begin 
					strswitch			<=	1'b0;
					I_tx_en				<=	1'b0;
					I_data_in			<=	DATA_out;
					state				<=	state	+	1'b1;
					cnt					<=	cnt	+	1'b1;
				 end 
				else 
				 begin 
					I_tx_en				<=	1'b1;
					state				<=	state;
				 end 
			end 
			42:begin 
				if (O_tx_done)
				 begin 
					strswitch			<=	1'b0;
					I_tx_en				<=	1'b0;
					I_data_in			<=	DATA_out;
					state				<=	state	-	1'b1;
					cnt					<=	cnt	+	1'b1;
				 end 
				else 
				 begin 
					I_tx_en				<=	1'b1;
					state				<=	state;
				 end 
			end 
			43:begin 
				if (Sector_ER_DONE)
				 begin 
					state				<=	state	+	1'b1;
				 end 
				else if (addr2	>=		8388608-1)
				 begin 
					state				<=	state	+	1'b1;
					addr2				<=	24'd0;
				 end 
				else 
				 begin 
					I_tx_en			<=	1'b0;
					O_spi_cs			<=	1'b1;
					state				<=	8'd31;
					addr2				<=	addr2	+	128;
				 end 
			end 
			44:begin 
					strswitch			<=	1'b1 ;
					state				<=	state	+	1'b1;
					I_rx_en				<=	1'b0;
					I_tx_en				<=	1'b0;
					O_spi_cs			<=	1'b1;
			end 
//**************************************开时读取
//***********************写启动
			45:begin 
				if (cnt	==	25000000-1)
				 begin 
					cnt 	<=	32'd0;
					state	<=	state	+	1'b1;
				 end 
				else 
				 begin 
					cnt 	<=	cnt 	+	1'b1;
					state	<=	state;
				 end 
			end 
			46:begin 
					state					<=	state		+	1'b1;
					I_rx_en				<=	1'b0;
					I_tx_en				<=	1'b1;
					O_spi_cs				<=	1'b0;
					I_data_in			<=	Write_Enable;		//启动状态寄存器
					strswitch			<=	1'b1;		
					addr2					<=	addr;
			end 
			47:begin 
				if (O_tx_done)
					state					<=	state	+	1'b1;
				else 	
					state					<=	state;
			end 
			48:begin 
					I_tx_en				<=	1'b0;
					O_spi_cs				<=	1'b1;
					state					<=	state	+	1'b1;
			end  
			//***********************读状态
			49:begin 
				I_tx_en					<=	1'b1;
				O_spi_cs					<=	1'b0;
				state						<=	state	+	1'b1;
				strswitch				<=	1'b1;
				I_data_in				<=	Read_Status_Register_2;	
			end 
			50:begin 
				if (O_tx_done)
					state					<=	state	+	1'b1;
				else 
					state					<=	state;
			end 
			51:begin 
					I_rx_en				<=	1'b1;
					I_tx_en				<=	1'b0;
					state					<=	state	+	1'b1;
			end 
			52:begin 
				if (O_rx_done)
				 begin 
					DATA					<=	O_data_out;
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			end 
			//***********************判读读取数据
			53:begin 	
				if (DATA[1:0]	==	2'b10)			
				 begin 
					O_spi_cs				<=	1'b1;
					I_rx_en				<=	1'b0;
					I_tx_en				<=	1'b0;
					state					<=	state	+	2;
					cnt					<=	64'd0;
					Register_error		<=	1'b0;
				 end 
				else 
				 begin 
					Register_error		<=	1'b1;
					state					<=	state	+	2;
				 end 
			end 
			54:begin 
				if (cnt		>=		500000-1)
				 begin 
					cnt					<=	64'd0;
					state					<=	state	+	1'b1;
				 end 
					cnt					<=	cnt	+	1'b1;
			end 
			//***************增加缓存时间读取数据
			55:begin 
				if (cnt	>=	500-1)
				 begin 
					cnt					<=	64'd0;
					state					<=	state	+	1'b1;
				 end 
				  begin 
					strswitch			<=	1'b1;
					cnt					<=	cnt	+	1'b1;
//					DATA					<=	8'hff;
				  end 
			end 
			//********************四线制读取
			56:begin 
				cnt						<=	64'd0;
				I_tx_en					<=	1'b1;
				O_spi_cs					<=	1'b0;
				state						<=	state	+	1'b1;
				I_data_in				<=	Fast_Read_Quad_Output;	
			end 
			57:if (O_tx_done)
				 begin 
					I_data_in			<=	addr2[23:16];
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			58:begin 
				if (O_tx_done)
				 begin 
					I_data_in			<=	addr2[15:8];
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			end 
			59:begin 
				if (O_tx_done)
				 begin 
					I_data_in			<=	addr2[7:0];
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			end 
			60:begin 								//提前切换
				if (O_tx_done)
				 begin 
					strswitch			<=	1'b0;		//使用并行
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			end 
			//***************读取数据
			61:begin 
					I_tx_en				<=	1'b0;
					I_rx_en				<=	1'b1;
					state					<=	state	+	1'b1;
			end 
			62:begin 
				if (cnt	>=		257)
				 begin 
					cnt					<=	64'd0;
					state					<=	state	+	2;
				 end 
				else if (O_rx_done)
				 begin 
					DATA					<=	O_data_out;
					state					<=	state	+	1'b1;
				 end 
				else 
					state					<=	state;
			end 
			63:begin 
				if (DATA			==	DATA_out)
				 begin 
					cnt					<=	cnt	+	1'b1;
					state					<=	state	-	1'b1;
					DATA_error			<=	1'b0;
				 end 
				else 
				 begin 
					DATA_error			<=	1'b1;
					state					<=	state	-	1'b1;
				 end 
			end 
			//换页读取数据判断
			64:begin 
				if (Sector_ER_DONE)
				 begin 
					state				<=	80;
				 end 
				else if (addr2	>=	8388608-1)
				 begin 
					state				<=	state	+	1'b1;
					addr2				<=	24'd0;
				 end 
				else 
				 begin 
					addr2				<=	addr2	+	128;
					state				<=	8'd55;
				 end 
			end 
			//  全片擦除10次 , 两个扇区擦除 1w次
			65:begin  
				if (Erase_count	==	10 - 1)
				 begin 
					O_spi_cs			<=	1'b1	;
					state				<=	state	+	1'b1;
					I_tx_en				<=	1'b0	;
					I_rx_en				<=	1'b0	;
					strswitch			<=	1'b1 	;
					addr					<=	24'd0		;
				 end 
				else 
				 begin 
					O_spi_cs			<=	1'b1	;
					state				<=	8'd1 	;
					I_tx_en				<=	1'b0	;
					I_rx_en				<=	1'b0	;
					strswitch			<=	1'b1 	;
				 end 
			end  
//**********************************************************************启动两个扇区各擦除 1w次
			//*******************写启动
			66:begin 
				O_spi_cs		<=	1'b0;
				I_tx_en		<=	1'b1;
				state			<=	state	+	1'b1;
				I_data_in	<=	Write_Enable;	
			end 
			67:begin 
				if (O_tx_done)
				 begin 
					I_tx_en	<=	1'b0;
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			//*******************延迟等待 
			68:begin 
				if (cnt	==	2) 
				 begin 
					cnt		<=		23'd0;
					O_spi_cs	<=		1'b1;
					state		<=		state	+	1'b1;
				 end 
				else 
				 begin 
					cnt		<=		cnt		+	1'b1;
					state		<=		state;
				 end 
			end 
			//*******************扇区擦除指令 
			69:begin 
				O_spi_cs		<=	1'b0;
				I_tx_en		<=	1'b1;
				state			<=	state	+	1'b1;
				I_data_in	<=	Sector_Erase;			
			end 
			70:begin 
				if (O_tx_done)
				 begin 
					I_data_in<=	addr[23:16];
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			71:begin 
				if (O_tx_done)
				 begin 
					I_data_in<=	addr[15:8];
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			72:begin 
				if (O_tx_done)
				 begin 
					I_data_in<=	addr[7:0];
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			73:begin 
				if (O_tx_done)
				 begin 
					I_tx_en	<=	1'b0;
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			//*******************延迟等待 
			74:begin 
				if (cnt	==	2) 
				 begin 
					cnt		<=		23'd0;
					O_spi_cs	<=		1'b1;
					state		<=		state	+	1'b1;
				 end 
				else 
				 begin 
					cnt		<=		cnt		+	1'b1;
					state		<=		state;
				 end 
			end 
			//*******************读取状态寄存器 
			75:begin 
				O_spi_cs		<=	1'b0;
				I_tx_en		<=	1'b1;
				state			<=	state	+	1'b1;
				I_data_in	<=	Read_Status_Register_1;			
			end 
			76:begin 
				if (O_tx_done)
				 begin 
					I_rx_en	<=		1'b1;
					I_tx_en	<=		1'b0;
					state		<=		state	+	1'b1;
				 end 
				else 
					state		<=		state;
			end 	
			77:begin 
				if (O_rx_done)
				 begin 
					DATA		<=	O_data_out;
					state		<=	state	+	1'b1;
				 end 
				else 
					state		<=	state;
			end 
			78:begin 
				if (DATA[0]	==	0)
					state		<=	state	+	1'b1;
				else 
					state		<=	state	-	1'b1;
			end 
			// 扇区擦除完成,进行写操作   ,  (跳转到13状态进行写数据与读取数据操作)
			79:begin 
					Sector_ER_DONE	<=	1'b1;
					state				<=	13;
					addr2				<=	addr;
			end 
			80:begin //20000
				 if (Erase_count	==	20000-10)
				  begin 
					I_rx_en		<=		1'b0;
					I_tx_en		<=		1'b0;
					state			<=	state	+	2;
					O_spi_cs		<=	1'b1;
					Erase_count	<=	Erase_count;
				  end //10000
				 else if (Erase_count	==	10000-10)
				  begin 
					I_rx_en		<=		1'b0;
					I_tx_en		<=		1'b0;
					state			<=	state	+	1;
					O_spi_cs		<=	1'b1;
					Erase_count	<=	Erase_count	+	1'b1;
				  end 
				 else 
				  begin 
					O_spi_cs		<=	1'b1;
					Erase_count	<=	Erase_count	+	1'b1;
					state			<=	66;
				  end 
			end 
			//切换扇区    
			81:begin 
					I_rx_en		<=	1'b0;
					I_tx_en		<=	1'b0;
					O_spi_cs		<=	1'b1;
					addr			<=	addr	+	128;
					state			<=	66;
			end 
			//完成
			82:begin 
					I_rx_en		<=	1'b0;
					I_tx_en		<=	1'b0;
					O_spi_cs		<=	1'b1;
					addr			<=	addr;
					state			<=	state;
			end 
	default : ;
 endcase 
end 

endmodule 

`timescale 1 ps/ 1 ps
//
// Company:
// Engineer:
//
// Create Date: 11-08-2022 16:06:06
// Design Name:
// Module Name: SPI
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
// 
// Revision: 
// Additional Comments:
//
//

 
module SPI(
    input               I_clk       , // 鍏ㄥ眬鏃堕挓1MHz
    input               I_rst_n     , // 澶嶄綅淇″彿锛屼綆鐢靛钩鏈夋晥
    input               I_rx_en     , // 璇讳娇鑳戒俊鍙
    input               I_tx_en     , // 鍙戦€佷娇鑳戒俊鍙
    input        [7:0]  I_data_in   , // 瑕佸彂閫佺殑鏁版嵁
	input 				strswitch	, // 涓茶涓庡苟琛屽垏鎹1浣跨敤涓茶		0浣跨敤骞惰
    output  reg  [7:0]  O_data_out  , // 鎺ユ敹鍒扮殑鏁版嵁
    output  reg         O_tx_done   /*synthesis preserve*/, // 鍙戦€佷竴涓瓧鑺傚畬姣曟爣蹇椾綅
    output  reg         O_rx_done   , // 鎺ユ敹涓€涓瓧鑺傚畬姣曟爣蹇椾綅
    
    // 鍥涚嚎鏍囧噯SPI淇″彿瀹氫箟
    output  reg         O_spi_sck   , // SPI鏃堕挓
    inout		        O_spi_mosi  , // SPI杈撳嚭锛岀敤鏉ョ粰浠庢満鍙戦€佹暟鎹   	IO0
    inout               I_spi_miso  , // SPI涓茶杈撳叆锛岀敤鏉ユ帴鏀朵粠鏈虹殑鏁版嵁   IO1
	inout 				WP			, // IO2
	inout			    HOLD		  // IO3
);
 
//------------------------------------------------------------------------------
//----------- Registers Declarations -------------------------------------------
//------------------------------------------------------------------------------
reg [3:0]   R_tx_state      		; 
reg [3:0]   R_rx_state      		;
reg [4:0]   R_tx_state_c      		;  
reg [3:0]   R_rx_state_c      		;
reg			fag_IO0					;
reg			fag_IO1					;
reg			fag_IO2					;
reg			fag_IO3					;
reg [5:0]	cnt						;

//		1鍙戦€佺粰鑺墖鏁版嵁		0鎺ユ敹鑺墖鏁版嵁
assign		O_spi_mosi		=	I_tx_en==0	?	1'hz	:	fag_IO0;
assign		I_spi_miso		=	I_tx_en==0	?	1'hz	:	fag_IO1;
assign		WP				=	I_tx_en==0	?	1'hz	:	fag_IO2;
assign		HOLD			=	I_tx_en==0	?	1'hz	:	fag_IO3;


always @(posedge I_clk )
begin
    if(!I_rst_n)
        begin
            R_tx_state  <=  4'd0    ;
            R_rx_state  <=  4'd0    ;
			R_tx_state_c<=	5'd0	;
			R_rx_state_c<=	4'd0	;
            O_spi_sck   <=  1'b0    ;
            O_tx_done   <=  1'b0    ;
            O_rx_done   <=  1'b0    ;
            O_data_out  <=  8'd0    ;
			fag_IO0		<=	1'b0	;
			fag_IO1		<=	1'b0	;
			fag_IO2		<=	1'b0	;
			fag_IO3		<=	1'b0	;
			cnt			<=	6'd0	;
        end 
    else if(I_tx_en	&&	strswitch) // 鍙戦€佷娇鑳戒俊鍙锋墦寮€鐨勬儏鍐典笅
        begin
            case(R_tx_state_c)
                0:    // 鍙戦€佺7浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;	
                        fag_IO0  		<=  I_data_in[7]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c      	;
                        O_tx_done   	<=  1'b0                ;
                     end 
                1: 
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                2:    // 鍙戦€佺6浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[6]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c        ;
                        O_tx_done   	<=  1'b0                ;
                     end
                3: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                4:    // 鍙戦€佺5浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[5]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c        ;
                        O_tx_done   	<=  1'b0                ;
                     end 
                5: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                6:    // 鍙戦€佺4浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[4]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c    	;
                        O_tx_done   	<=  1'b0                ;
                     end 
                7: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                8:    // 鍙戦€佺3浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[3]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c        ;
                        O_tx_done   	<=  1'b0                ;
                     end    
                 9: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end 
                10:    // 鍙戦€佺2浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[2]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c        ;
                        O_tx_done   	<=  1'b0                ;
                     end 
                11: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                12:    // 鍙戦€佺1浣
					if (cnt	>=	25-1)
					 begin 
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[1]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c      	;
                        O_tx_done  	 	<=  1'b0                ;
                     end 
                13: //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
                14:    // 鍙戦€佺0浣
					if (cnt	>=	25-1)
					 begin 
						O_tx_done   	<=  1'b0                ;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end
					else 
                     begin
						O_tx_done   	<=  1'b0                ;
						cnt 			<=	cnt		+	1'b1	;
                        fag_IO0  		<=  I_data_in[0]        ;
						fag_IO1			<=	1'hz				;
						fag_IO2			<=	1'hz				;
						fag_IO3			<=	1'hz				;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state_c  	<=  R_tx_state_c        ;
                     end
                15 : //鏁村悎濂囨暟鐘舵€
					if (cnt	>=	25-1)
					 begin 
						O_tx_done   	<=  1'b0                ;
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0;
						R_tx_state_c  	<=  R_tx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_rx_done		<=	1'b0;
						cnt 			<=	cnt		+	1'b1		;			
                        O_spi_sck   	<=  1'b1                	;
                        R_tx_state_c  	<=  R_tx_state_c    		;
                        O_tx_done  	 	<=  1'b0                	;
                     end
				16:begin 
					if (cnt	>=	25-1)
					 begin 
						O_rx_done		<=	1'b0;
						cnt				<=	6'd0				;
						O_tx_done   	<=  1'b1                ;
						R_tx_state_c	<=	0					;
					 end 
					else 
					 begin 
						O_spi_sck   	<=  1'b0                	;
						O_rx_done		<=	1'b0;
						O_tx_done   	<=  1'b0                ;
						cnt 			<=	cnt		+	1'b1	;
					 end 
				end 
                default:               ;   
            endcase 
        end
    else if(I_rx_en	&&	strswitch) // 鎺ユ敹浣胯兘淇″彿鎵撳紑鐨勬儏鍐典笅
        begin
            case(R_rx_state_c)
                4'd0, 4'd2 , 4'd4 , 4'd6  , 
                4'd8, 4'd10, 4'd12, 4'd14 : //鏁村悎鍋舵暟鐘舵€
					if (cnt	==	25-1)
					 begin 
						O_tx_done   	<=  1'b0                ;
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						O_tx_done   	<=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
						O_spi_sck		<=	1'b0				;
						R_rx_state_c	<=	R_rx_state_c		;
						O_rx_done		<=	1'b0				;
                     end
                4'd1:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin                       
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c		;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[7]   <=  I_spi_miso          ;   
                     end
                4'd3:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[6]   <=  I_spi_miso          ; 
                     end
                4'd5:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[5]   <=  I_spi_miso          ; 
                     end 
                4'd7:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c  	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[4]   <=  I_spi_miso          ; 
                     end 
                4'd9:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[3]   <=  I_spi_miso          ; 
                     end                            
                4'd11:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[2]   <=  I_spi_miso          ; 
                     end 
                4'd13:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						cnt				<=	6'd0;
						R_rx_state_c  	<=  R_rx_state_c	+	1'b1;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[1]   <=  I_spi_miso          ; 
                     end 
                4'd15:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b1                ;
						cnt				<=	6'd0;
						R_rx_state_c  	<=  0;
					 end 
					else 
                     begin
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state_c	<=	R_rx_state_c	    ;
                        O_data_out[0]   <=  I_spi_miso          ; 
                     end
                default:R_rx_state_c  <=  4'd0                    ;   
            endcase 
        end    
    else if(I_tx_en	&&	strswitch==0) // 鍙戦€佷娇鑳戒俊鍙锋墦寮€鐨勬儏鍐典笅
        begin
            case(R_tx_state)
                4'd0:    // 鍙戦€佺0浣
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_tx_state  	<=  R_tx_state	+	1'b1;
					 end 
					else 
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
                        fag_IO0			<=   I_data_in[4]       ;
						fag_IO1			<=	 I_data_in[5]		;
						fag_IO2			<=	 I_data_in[6]		;
						fag_IO3			<=	 I_data_in[7]		;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state  	<=  R_tx_state          ;
                        O_tx_done   	<=  1'b0                ;
                     end 
				4'd1:
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0               ;
						cnt				<=	6'd0				;
						R_tx_state  	<=  R_tx_state	+	1'b1;
					 end 
					else 
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck   	<=  1'b1                ;
                        R_tx_state  	<=  R_tx_state	   		;
                        O_tx_done   	<=  1'b0                ;
                     end
                4'd2:    // 鍙戦€佺1浣
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_tx_state  	<=  R_tx_state	+	1'b1;
					 end 
					else 
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
                        fag_IO0			<=  I_data_in[0]        ;
						fag_IO1			<=	I_data_in[1]		;
						fag_IO2			<=	I_data_in[2]		;
						fag_IO3			<=	I_data_in[3]		;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state  	<=  R_tx_state 	   		;
                        O_tx_done   	<=  1'b0                ;
                     end
				4'd3:
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_tx_state  	<=  R_tx_state	+	1'b1;
					 end 
					else 
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck   	<=  1'b1                ;
                        R_tx_state  	<=  R_tx_state 		    ;
                        O_tx_done   	<=  1'b0                ;
                     end
				4'd4:
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						O_tx_done   	<=  1'b1                ;
						R_tx_state  	<=  4'd0     	        ;
					 end 
					else 
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck   	<=  1'b0                ;
                        R_tx_state  	<=  R_tx_state 		    ;
					 end 
                default: ;   
            endcase 
        end
    else if(I_rx_en	&&	strswitch==0) // 鎺ユ敹浣胯兘淇″彿鎵撳紑鐨勬儏鍐典笅
        begin
            case(R_rx_state)
				4'd0:
					if (cnt	==	25-1)
					 begin 
						O_tx_done   	<=  1'b0                ;
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_rx_state  	<=  R_rx_state	+	1'b1;
					 end 
					else 
					 begin 
						O_tx_done   	<=  1'b0                ;
						cnt				<=	cnt 	+	1'b1	;
						O_spi_sck		<=	1'b0				;
						R_rx_state		<=	R_rx_state	 		;
						O_rx_done		<=	1'b0				;
					 end 
                4'd1:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_rx_state  	<=  R_rx_state	+	1'b1;
					 end 
					else 
					 begin 	
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state      <=  R_rx_state 		    ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[4]   <=  O_spi_mosi			;   
						O_data_out[5]   <=  	I_spi_miso				;
						O_data_out[6]   <=  	WP		;
						O_data_out[7]   <=  HOLD				;	
                     end
				4'd2:
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_rx_state  	<=  R_rx_state	+	1'b1;
					 end 
					else 
					 begin 
						cnt				<=	cnt 	+	1'b1	;
						O_spi_sck		<=	1'b0				;
						R_rx_state		<=	R_rx_state			;
						O_rx_done		<=	1'b0				;
					 end 
                4'd3:    // 鎺ユ敹绗浣
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b0                ;
						cnt				<=	6'd0				;
						R_rx_state  	<=  R_rx_state	+	1'b1;
					 end 
					else 
					 begin 
						cnt				<=	cnt 	+	1'b1	;
                        O_spi_sck       <=  1'b1                ;
                        R_rx_state      <=  R_rx_state          ;
                        O_rx_done       <=  1'b0                ;
                        O_data_out[0]   <=  O_spi_mosi			;   
						O_data_out[1]   <=  I_spi_miso			;
						O_data_out[2]   <=  WP					;
						O_data_out[3]   <=  HOLD				;	
                     end
				4'd4:
					if (cnt	==	25-1)
					 begin 
						O_rx_done       <=  1'b1                ;
						cnt				<=	6'd0				;
						R_rx_state		<=	4'd0     	        ;
					 end 
					else 
					 begin 
						cnt				<=	cnt 	+	1'b1	;
						O_spi_sck		<=	1'b0				;
						R_rx_state		<=	R_rx_state			;
					 end 
                default: ;   
            endcase 
        end    
    else
        begin
            R_tx_state  <=  4'd0    ;
            R_rx_state  <=  4'd0    ;
			R_tx_state_c<=	5'd0	;
			R_rx_state_c<=	4'd0	;
            O_tx_done   <=  1'b0    ;
            O_rx_done   <=  1'b0    ;
            O_spi_sck   <=  1'b0    ;
            O_data_out  <=  8'd0    ;
			cnt 		<=	6'd0	;
        end      
end
 
endmodule


结论

????????综上所述,通过利用FPGA实现的该程序,成功实现了Flash存储器的写入使能、整片擦除、全片写入和全片数据读取功能。这些功能的实现为Flash存储器的使用带来了更大的便利性和灵活性,使得数据的存储和访问更加可靠和高效。通过该程序,用户能够有效地控制Flash存储器的操作,并实现对整个存储器的快速擦除和写入,以及高效的数据读取。这些功能的结合为各种应用场景提供了更多的选择和解决方案。

文章来源:https://blog.csdn.net/weixin_46062412/article/details/135330135
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。