打印
[FPGA]

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

[复制链接]
3167|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaochy1126|  楼主 | 2022-3-31 22:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

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

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


使用特权

评论回复
沙发
gaochy1126|  楼主 | 2022-3-31 22:57 | 只看该作者
/***************************
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


使用特权

评论回复
板凳
gaochy1126|  楼主 | 2022-3-31 22:57 | 只看该作者
/***************************
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


使用特权

评论回复
地板
gaochy1126|  楼主 | 2022-3-31 22:58 | 只看该作者
5.需要说明的是擦除需要一个标志位,可以使用按键产生。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:这个社会混好的两种人:一是有权有势,二是没脸没皮的。

1051

主题

11300

帖子

26

粉丝