基于FPGA的flash板卡程序擦除与固化

xiaoxiao2025-04-14  7

转至:https://blog.csdn.net/headogerz/article/details/82251175

1.擦除程序,程序擦除是可以用软件,但本文主要讨论用代码实现擦除。擦除已经固化好的程序需要对flash芯片(M25P94)的时序进行描述。时序原理如图所示:

    这里主要是对flash的前8个扇区进行擦除,为了产生擦除标志,所以多家了一个wait_3s的标识,8个扇区总共需要24秒。

2.固化原理描述,fpga是没有存储程序的空间的。所以需要flash芯片来存储程序,可以用ise软件固化,也可以用verilog代码固化。这里就需要阅读M25P64 flash芯片的手册,主要是对时序的控制。

3.通过uart协议发送固化程序,需要在ise软件中生成bin文件,然后通过matlab实现进制转化。最终发送到fpga芯片中。

4.擦除与固化的代码为:

/*************************** spi协议控制flash扇区固化 ****************************/ module flash_ctrl_wr( input wire sclk, input wire rst_n, input wire pi_flag, input wire [7:0] data_in, output reg cs_n, output reg sck, output reg sdi ); reg [9:0] state; parameter idle =10'b0000_0000_01; parameter WAIT1 =10'b0000_0000_10; parameter WRITE =10'b0000_0001_00; parameter WAIT2 =10'b0000_0010_00; parameter WAIT3 =10'b0000_0100_00; parameter WAIT4 =10'b0000_1000_00; parameter PP =10'b0001_0000_00; parameter INIT_ADDR =10'b0010_0000_00; parameter DATA_IN =10'b0100_0000_00; parameter WAIT5 =10'b1000_0000_00; reg [4:0] sclk_cnt; parameter SCLK_CNT=31; reg [1:0] cnt_init_addr; reg [1:0] cnt4; reg [2:0] bit_cnt; reg add_addr_flag; reg [23:0] init_addr; parameter INIT_ADDR_Location=6'h00_00_00; parameter wr_en=8'h06; parameter PP_en=8'h02; always@(posedge sclk or negedge rst_n) if(!rst_n) add_addr_flag<=0; else if(state==WAIT5&&sclk_cnt==SCLK_CNT) add_addr_flag<=1; else add_addr_flag<=0; always@(posedge sclk or negedge rst_n) if(!rst_n) init_addr<=INIT_ADDR_Location; else if(add_addr_flag==1) init_addr<=init_addr+24'h0000_01; //字节自动加一,加到255后页自动加一 //else init_addr<=24'd0; always@(posedge sclk or negedge rst_n) if(!rst_n) cnt4<=2'd0; else if(cnt4==3) cnt4<=2'd0; else if(state==WRITE||state==PP||state==INIT_ADDR||state==DATA_IN) cnt4<=cnt4+1; always@(posedge sclk or negedge rst_n) if(!rst_n) bit_cnt<=3'd0; else if(bit_cnt==7&&cnt4==3) bit_cnt<=3'd0; else if(cnt4==3) bit_cnt<=bit_cnt+1; always@(posedge sclk or negedge rst_n) if(!rst_n) cs_n<=1; else if(pi_flag==1) cs_n<=0; else if(state==WAIT2&&sclk_cnt==SCLK_CNT) cs_n<=1; else if(state==WAIT3&&sclk_cnt==SCLK_CNT) cs_n<=0; else if(sclk_cnt==SCLK_CNT&&state==WAIT5) cs_n<=1; always@(posedge sclk or negedge rst_n) if(!rst_n) sclk_cnt<=5'd0; else if (sclk_cnt==SCLK_CNT&&state==WAIT5) sclk_cnt<=5'd0; else if(sclk_cnt==SCLK_CNT) sclk_cnt<=5'd0; else if(cs_n==0) sclk_cnt<=sclk_cnt+1; else if(state==WAIT3) sclk_cnt<=sclk_cnt+1; always@(posedge sclk or negedge rst_n) if(!rst_n) cnt_init_addr<=2'd0; else if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT) cnt_init_addr<=2'd0; else if(sclk_cnt==SCLK_CNT&&state==INIT_ADDR) cnt_init_addr<=cnt_init_addr+1; always@(posedge sclk or negedge rst_n) if(!rst_n) state<=idle; else case(state) idle: if(pi_flag==1) state<=WAIT1; else state<=idle; WAIT1: if(sclk_cnt==SCLK_CNT) state<=WRITE; else state<=WAIT1; WRITE: if(sclk_cnt==SCLK_CNT) state<=WAIT2; else state<=WRITE; WAIT2: if(sclk_cnt==SCLK_CNT) state<=WAIT3; else state<=WAIT2; WAIT3: if(sclk_cnt==SCLK_CNT) state<=WAIT4; else state<=WAIT3; WAIT4: if(sclk_cnt==SCLK_CNT) state<=PP; PP: if(sclk_cnt==SCLK_CNT) state<=INIT_ADDR; else state<=PP; INIT_ADDR: if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT) state<=DATA_IN; else state<=INIT_ADDR; DATA_IN: if(sclk_cnt==SCLK_CNT) state<=WAIT5; else state<=DATA_IN; WAIT5: if(sclk_cnt==SCLK_CNT) state<=idle; else state<=WAIT5; default: state<=idle; endcase always@(posedge sclk or negedge rst_n) //时钟传递 if(!rst_n) sck<=0; else if(state==WRITE &&cnt4==1) sck<=1; else if(state==WRITE&&cnt4==3) sck<=0; else if (state==PP&&cnt4==1) sck<=1; else if(state==PP&&cnt4==3) sck<=0; else if (state==INIT_ADDR&&cnt4==1) sck<=1; else if(state==INIT_ADDR&&cnt4==3) sck<=0; else if (state==DATA_IN&&cnt4==1) sck<=1; else if(state==DATA_IN&&cnt4==3) sck<=0; always@(posedge sclk or negedge rst_n) if(!rst_n) sdi<=1'b1; else if(state==WRITE) sdi<=wr_en[7-bit_cnt]; else if(state==PP) sdi<=PP_en[7-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==0) sdi<=init_addr[23-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==1) sdi<=init_addr[15-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==2) sdi<=init_addr[7-bit_cnt]; else if(state==DATA_IN) sdi<=data_in[7-bit_cnt]; else sdi<=1'b1; endmodule /*************************** spi协议控制flash扇区擦除 ****************************/ module se_ctrl( input wire sclk, input wire rst_n, input wire pi_se_flag, output reg led, output reg cs_n, output reg sck, output reg sdi ); reg [9:0] state; parameter idle =10'b0000_0000_01; parameter WAIT1 =10'b0000_0000_10; parameter WRITE =10'b0000_0001_00; parameter WAIT2 =10'b0000_0010_00; parameter WAIT3 =10'b0000_0100_00; parameter WAIT4 =10'b0000_1000_00; parameter SE =10'b0001_0000_00; parameter INIT_ADDR =10'b0010_0000_00; parameter WAIT5 =10'b0100_0000_00; parameter WAIT_3S =10'b1000_0000_00; reg [4:0] sclk_cnt; parameter SCLK_CNT=31; reg [1:0] cnt_init_addr; reg [25:0] cnt_1s; parameter ONE_S=49_9999_99; reg [1:0] cnt_3s; reg [1:0] cnt4; reg [2:0] bit_cnt; reg [3:0] cnt_wait_3s; reg [23:0] init_addr; //parameter INIT_ADDR_Location=6'h00_00_00; parameter wr_en=8'h06; //信号差了一个时钟周期 parameter se_en=8'hd8; parameter CNT_wait_3s=7; reg cnt_3s_en; //always@(posedge sclk or negedge rst_n) // if(!rst_n) // se_flag<=0; // else if(pi_se_flag==1) // se_flag<=1; always@(posedge sclk or negedge rst_n) //循环擦除 if(!rst_n) cnt_wait_3s<=3'd0; else if(cnt_wait_3s==CNT_wait_3s&&cnt_1s==ONE_S&&cnt_3s==2) cnt_wait_3s<=3'd0; else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2) cnt_wait_3s<=cnt_wait_3s+1'b1; always@(posedge sclk or negedge rst_n) //扇区地址变换 if(!rst_n) init_addr<=24'd0; else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2) init_addr<=init_addr+24'h01_0000; else if(state==idle) init_addr<=24'd0; always@(posedge sclk or negedge rst_n) //为输出时钟计数 if(!rst_n) cnt4<=2'd0; else if(cnt4==3) cnt4<=2'd0; else if(state==WRITE||state==SE||state==INIT_ADDR) cnt4<=cnt4+1; always@(posedge sclk or negedge rst_n) // bit位计数 if(!rst_n) bit_cnt<=3'd0; else if(bit_cnt==7&&cnt4==3) bit_cnt<=3'd0; else if(cnt4==3) bit_cnt<=bit_cnt+1; always@(posedge sclk or negedge rst_n) if(!rst_n) cnt_1s<=26'd0; else if(cnt_1s==ONE_S) cnt_1s<=26'd0; else if(cnt_3s_en==1) cnt_1s<=cnt_1s+1; always@(posedge sclk or negedge rst_n) if(!rst_n) cnt_3s<=2'd0; else if(cnt_1s==ONE_S&&cnt_3s==2) cnt_3s<=2'd0; else if(cnt_1s==ONE_S) cnt_3s<=cnt_3s+1; always@(posedge sclk or negedge rst_n) //3秒使能信号 if(!rst_n) cnt_3s_en<=0; else if(cnt_1s==ONE_S&&cnt_3s==2) cnt_3s_en<=0; else if(state==WAIT_3S) cnt_3s_en<=1; always@(posedge sclk or negedge rst_n) if(!rst_n) cs_n<=1; else if(pi_se_flag==1) cs_n<=0; else if(state==idle) cs_n<=1; else if(state==WAIT2&&sclk_cnt==SCLK_CNT) //片选信号没有描述对 cs_n<=1; else if(state==WAIT3&&sclk_cnt==SCLK_CNT) cs_n<=0; else if(state==WAIT5&&sclk_cnt==SCLK_CNT) cs_n<=1; else if(state==WAIT_3S&&cnt_1s==ONE_S&&cnt_3s==2) cs_n<=0; //else if(cnt_wait_3s==CNT_wait_3s) //cs_n<=1; always@(posedge sclk or negedge rst_n) if(!rst_n) sclk_cnt<=5'd0; else if (sclk_cnt==SCLK_CNT&&cnt_wait_3s==CNT_wait_3s) sclk_cnt<=5'd0; else if(sclk_cnt==SCLK_CNT) sclk_cnt<=5'd0; else if(cs_n==0) sclk_cnt<=sclk_cnt+1; else if(state==WAIT3) sclk_cnt<=sclk_cnt+1; always@(posedge sclk or negedge rst_n) //3位状态计数 if(!rst_n) cnt_init_addr<=2'd0; else if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT) cnt_init_addr<=2'd0; else if(sclk_cnt==SCLK_CNT&&state==INIT_ADDR) cnt_init_addr<=cnt_init_addr+1; always@(posedge sclk or negedge rst_n) if(!rst_n) state<=idle; else case(state) idle: if(pi_se_flag==1) state<=WAIT1; else state<=idle; WAIT1: if(sclk_cnt==SCLK_CNT) state<=WRITE; else state<=WAIT1; WRITE: if(sclk_cnt==SCLK_CNT) state<=WAIT2; else state<=WRITE; WAIT2: if(sclk_cnt==SCLK_CNT) state<=WAIT3; else state<=WAIT2; WAIT3: if(sclk_cnt==SCLK_CNT) state<=WAIT4; else state<=WAIT3; WAIT4: if(sclk_cnt==SCLK_CNT) state<=SE; SE: if(sclk_cnt==SCLK_CNT) state<=INIT_ADDR; else state<=SE; INIT_ADDR: if(cnt_init_addr==2'd2&&sclk_cnt==SCLK_CNT) state<=WAIT5; else state<=INIT_ADDR; WAIT5: if(sclk_cnt==SCLK_CNT) state<=WAIT_3S; else state<=WAIT5; WAIT_3S: if(cnt_1s==ONE_S&&cnt_3s==2) state<=WAIT1; else if(cnt_wait_3s==CNT_wait_3s) state<=idle; default: state<=idle; endcase always@(posedge sclk or negedge rst_n) //时钟传递 if(!rst_n) sck<=0; else if(state==WRITE &&cnt4==1) sck<=1; else if(state==WRITE&&cnt4==3) sck<=0; else if (state==SE&&cnt4==1) sck<=1; else if(state==SE&&cnt4==3) sck<=0; else if (state==INIT_ADDR&&cnt4==1) sck<=1; else if(state==INIT_ADDR&&cnt4==3) sck<=0; always@(posedge sclk or negedge rst_n) //低电平传输数据 上升沿采集数据 if(!rst_n) sdi<=1'b1; else if(state==WRITE) sdi<=wr_en[7-bit_cnt]; else if(state==SE) sdi<=se_en[7-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==0) sdi<=init_addr[23-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==1) sdi<=init_addr[15-bit_cnt]; else if(state==INIT_ADDR&&cnt_init_addr==2) sdi<=init_addr[7-bit_cnt]; else sdi<=1'b1; //检查发现有问题 always@(posedge sclk or negedge rst_n) if(!rst_n) led<=0; else if(cnt_3s_en==1) led<=1; else led<=0; endmodule

5.需要说明的是擦除需要一个标志位,可以使用按键产生。  

转载请注明原文地址: https://www.6miu.com/read-5028250.html

最新回复(0)