N25Q00AA NOR SPIFLASH 的FPGA驱动开发


N25Q00AA简介

该芯片是Micron公司的Serial NOR FLASH,主存储区为1Gbits,分为4个256Mb的die,基于SPI协议通信。支持3-byte和4-byte地址。支持4KB\64KB\32MB擦除。

命令集

这里写图片描述
这里写图片描述
本文主要实现了图中红框所示命令,以下所述是在EXTENDED SPI协议下

读写寄存器

-对于任意写操作(写寄存器或者PROGRAM)都需要执行WRITE ENABLE命令.
其时序为:
这里写图片描述
发送8比特命令0x06,之后片选拉高

-工程中使用Write extended address register命令
其时序为:
这里写图片描述
发送16比特,其中前8比特为命令0xC5,后8比特为扩展地址

-读寄存器相对写寄存器少了写使能操作,工程中使用了读状态寄存器命令,读标志状态寄存器命令和读扩展地址命令。
READ STATUS REG/READ FLAG STATUS REG/READ EXTENDED ADDRESS REG时序
这里写图片描述

读FLASH

-使用了3-byte寻址模式,根据该芯片的主存区划分,3-byte地址只能访问128Mb数据量,但是该芯片支持一次READ操作读取1个die(即256Mb数据量),需要配置extended address register来访问其他3个die的存储空间。也就是说读取完该芯片所有容量1Gb至少需要4次读操作。
READ操作时序
这里写图片描述

写FLASH(PAGE PROGRAM)

-擦除之后,存储区数据为1,也就是说写操作将1变成0.每一次写操作最多能够写256byte(one page),同时注意写之前需确认该区域已经擦除。
PROGRAM MEMORY时序
这里写图片描述

擦除(DIE 擦除)

-工程中需要一次性将整块颗粒擦除完,所以使用die擦除方式。
-擦除与read类似,如果要擦除整片,在3-byte寻址模式下,需要修改扩展地址。
-整片擦除操作步骤
-a)写使能
-b)写扩展地址addr_extend=0x00
-c)die erase命令0xC4
-d)轮询读取状态寄存器,直至bit0为0
-e)读取FLAG STATUS寄存器,同时判断是否擦除完整块芯片,如果没有:判断bit7若为1则跳转b)更改addr_extend+=2,否则跳转c);如果擦除完,擦除成功,退出擦除状态

附录一 SPI通信模块

module spi_flash_config
(
input rst_n,
input sys_clk,

input [31:0] send_data,
input        send_trig, 
input [15:0] conf_data,

output reg[15:0] rece_data,
output reg       rece_data_valid,
output reg       send_done,

output       spi_sclk_o  ,
output       spi_ncs_o   ,
output       spi_mosi_o  ,
input        spi_miso_i  

);

reg [2:0] spi_state;
parameter s_IDLE = 3’d0,
s_NCS = 3’d1,
s_CMD = 3’d2,
s_RECE_DATA = 3’d3,
s_DELAY = 3’d4,
s_END = 3’d5;

reg [7:0] cnt_delay;

reg [7:0] cnt_send ;
reg [7:0] cnt_sclk ;
reg[31:0] send_buff;

wire rece_en ;
reg [7:0] cnt_rece ;
reg [15:0] rece_buff;

reg spi_ncs ;
wire spi_mosi ;
wire spi_sclk ;

assign spi_sclk_o = spi_sclk;
assign spi_ncs_o = spi_ncs;
assign spi_mosi_o = spi_mosi;

//generate spi_ncs ,spi_sclk,spi_mosi
always@(posedge sys_clk)
begin
if(rst_n == 1’b0)
begin
spi_state <= 3’d0;
cnt_delay <= 8’h0;

    cnt_send        <= 8'h0;
    cnt_rece            <= 8'h0;

    cnt_sclk            <= 'h0;

    send_buff      <= 32'h0;        
    spi_ncs         <= 1'b1;        
    send_done       <= 1'b0;
end
else
begin

    case(spi_state)
    s_IDLE:
        begin
            if(send_trig)
            begin
                cnt_send  <= conf_data[7:0];
                cnt_rece  <= conf_data[15:8];
                send_buff <= send_data;
                spi_state <= s_NCS; 
            end
            else
            begin
                send_buff <= 32'h0;
                spi_state <= s_IDLE;
            end
            spi_ncs <= 1'b1;
            cnt_delay<= 8'd2;
            send_done<= 1'b0;
        end

    s_NCS://1
        begin
            spi_ncs  <= 1'b0;
            if(cnt_delay == 8'd0)
                spi_state <= s_CMD;
            else
                cnt_delay <= cnt_delay - 1'b1;
        end

    s_CMD://2
        begin

            send_buff <= {send_buff[30:0],1'b0};

            if(cnt_send == 0)
            begin
                if(cnt_rece == 'h0)
                    spi_state <= s_DELAY;
                else
                    spi_state <= s_RECE_DATA;
                cnt_sclk <= 'h0;
            end
            else
                cnt_send <= cnt_send - 1'b1;

        end

    s_RECE_DATA://3
        begin
            cnt_delay<= 8'd2;
            if(cnt_sclk == cnt_rece)
            begin
                cnt_sclk <= 'h0;
                spi_state <= s_DELAY;
            end
            else
                cnt_sclk <= cnt_sclk + 1'b1;

        end

    s_DELAY://4
        begin
            if(cnt_delay == 8'd0)
            begin
                send_done <= 1'b1;
                spi_state <= s_END;
                spi_ncs  <= 1'b1;
            end
            else
                cnt_delay <= cnt_delay - 1'b1;


        end

    s_END://5
        begin
            send_done       <= 1'b0;
            spi_state       <= s_IDLE;
            spi_ncs         <= 1'b1;
        end

    default:
        begin
            send_done       <= 1'b0;
            spi_state      <= s_IDLE;
            spi_ncs         <= 1'b1;
        end

    endcase

end

end
assign spi_mosi = send_buff[31];
assign spi_sclk = ((spi_state == s_CMD) || (spi_state == s_RECE_DATA)) && (~sys_clk);

assign rece_en = (spi_state == s_RECE_DATA);
//receive data
initial begin rece_buff = ‘h0;end
always@(posedge spi_sclk or posedge send_trig)
begin
if(send_trig)
rece_buff <= ‘h0;
else
if(rece_en)
rece_buff <= {rece_buff[14:0],spi_miso_i};
else;
end
reg rece_en_r;
reg rece_en_rr;
reg rece_en_falling;

always@(posedge sys_clk)
begin
if(rst_n == 1’b0)
begin
rece_data <= ‘h0;
rece_data_valid <= 1’b0;

    rece_en_r        <= 1'b0;
    rece_en_rr       <= 1'b0;
    rece_en_falling <= 1'b0;
end
else
begin
    rece_en_r        <= rece_en;
    rece_en_rr       <= rece_en_r;
    rece_en_falling <= rece_en_rr &&(~rece_en_r);

    if(rece_en_rr &&(~rece_en_r))
    begin
        rece_data <= rece_buff;
        rece_data_valid <= 1'b1;
    end
    else
    begin
        rece_data <= rece_data;
        rece_data_valid <= 1'b0;
    end
end

end

endmodule

### 回答1: FPGA是一种可编程逻辑器件,它可以根据用户的需求来重新配置其逻辑功能。SPI闪存是指使用串行外设接口(SPI)协议进行通信的闪存存储器。N25Q256是一种具体型号的SPI闪存,其容量为256Mb(32MB)。 FPGA可以与SPI闪存进行直接的通信,以实现程序代码或数据的存储和读取。通常情况下,FPGA上有专门的SPI控制器模块,它可以与SPI闪存进行通信,读取和写入数据。 在使用FPGASPI闪存进行通信的时候,首先需要配置FPGA的引脚和SPI控制器以适配SPI闪存。然后,根据SPI闪存的规格书和通信协议,设置合适的时序和命令来读取或写入数据。 对于N25Q256 SPI闪存,可以通过SPI控制器发送读取命令来获取存储在闪存芯片中的数据。同时,也可以通过SPI控制器发送写入命令将FPGA中的数据写入到闪存芯片中。 通常情况下,FPGASPI闪存之间的通信速率相对较慢,因此在设计中需要考虑到通信的延时和时序问题。另外,还需要注意SPI闪存的操作电压和FPGA引脚电压的兼容性,以及SPI闪存的容量是否满足项目的需求。 总之,利用FPGASPI闪存可以实现高速读写和存储数据的功能,为嵌入式系统和数字电路设计带来更大的灵活性和可扩展性。 ### 回答2: FPGA是可编程逻辑器件,可实现复杂的数字电路设计和逻辑功能。SPI(Serial Peripheral Interface)是一种串行外设接口,可用于将FPGA与外部设备进行通信和数据交换。 N25Q256是一种SPI闪存芯片,具有256Mb的存储容量。它采用SPI接口进行通信,具备高速读写特性和可编程擦除功能。该闪存芯片可以作为FPGA的外部存储器,用于存储程序代码、配置文件和其他数据。 要在FPGA中使用N25Q256,首先需要将FPGA与闪存芯片连接起来。这可以通过将SPI接口引脚连接到对应的FPGA引脚来实现。接下来,需要编写FPGA的程序代码,使用SPI协议与闪存芯片进行通信。 在FPGA中,可以通过SPI接口向N25Q256发送命令来读取或写入数据。对于读取操作,FPGA发送读取命令和地址信息,然后从闪存芯片接收数据。对于写入操作,FPGA发送写入命令、地址信息和要写入的数据,然后将数据写入到闪存芯片。 通过使用N25Q256作为FPGA的外部存储器,可以实现对程序代码的存储和更新。此外,闪存芯片的大容量还可以用于存储其他数据,如传感器数据、配置信息等。 综上所述,FPGASPI闪存N25Q256的结合可以为FPGA提供可编程的外部存储解决方案,实现数据的存储和读取功能,并且具备高速读写和可编程擦除的特性,适用于各种应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值