FPGA使用SPI控制FLASH

这篇具有很好参考价值的文章主要介绍了FPGA使用SPI控制FLASH。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

通过控制FLASH芯片进一步熟悉SPI协议

一、FLASH与EEPROM芯片

Flash 存储器: Flash 存储器是一种非易失性存储器,它具有 RAM 和 ROM 的一些特点。与 ROM 类似,Flash 存储器的内容在断电时不会丢失,但与 RAM 类似,它可以通过编程来修改存储的内容。Flash 存储器通常用于嵌入式系统中存储程序代码、配置数据等。
EEPROM(电可擦除可编程只读存储器): EEPROM 是一种可编程的非易失性存储器,可以通过电擦除和编程来修改存储的内容。EEPROM 具有 RAM 的特点,可以随机读写,但也具有 ROM 的特点,存储的内容在断电时不会丢失。EEPROM 通常用于存储配置数据、参数设置等。
Flash 存储器和 EEPROM(Electrically Erasable Programmable Read-Only Memory)之间的主要区别在于它们的擦除和编程方法、速度、寿命和应用范围等方面。

  • 擦除和编程方法:
    Flash 存储器通常使用扇区擦除(Sector Erase)的方式来擦除数据,并使用编程器(Programmer)来进行编程。扇区擦除意味着需要一次性擦除一整个存储扇区,然后才能进行写入操作。EEPROM 可以通过逐字节擦除和编程来修改数据,因此擦除和编程更加灵活和精细。

  • 速度:由于 Flash 存储器通常采用扇区擦除的方式,擦除和编程操作比 EEPROM 慢。EEPROM 在擦除和编程时的速度相对较快,因为它可以逐字节地擦除和编程。

  • 寿命:Flash 存储器和 EEPROM 的擦除和编程操作都会导致存储器单元的磨损,从而影响存储器的寿命。由于 Flash 存储器通常需要一次性擦除整个扇区,因此其寿命可能受到擦除次数的限制。EEPROM 的擦除和编程操作更加精细,因此其寿命可能比 Flash 存储器更长。

  • 应用范围:Flash 存储器通常用于存储大容量的程序代码、固件更新等。EEPROM 通常用于存储配置数据、参数设置、小容量数据等。

  • 总的来说,Flash 存储器和 EEPROM 都是非易失性存储器,但它们在擦除和编程方法、速度、寿命和应用范围等方面存在一些差异,因此在选择存储器时需要根据具体的应用需求进行选择
    以下内容为补充的更加详细的参考,来自:https://zhuanlan.zhihu.com/p/27621418
    rom最初不能编程,出厂什么内容就永远什么内容,不灵活。后来出现了prom,可以自己写入一次,要是写错了,只能换一片,自认倒霉。人类文明不断进步,终于出现了可多次擦除写入的EPROM,每次擦除要把芯片拿到紫外线上照一下,想一下你往单片机上下了一个程序之后发现有个地方需要加一句话,为此你要把单片机放紫外灯下照半小时,然后才能再下一次,这么折腾一天也改不了几次。历史的车轮不断前进,伟大的EEPROM出现了,拯救了一大批程序员,终于可以随意的修改rom中的内容了。
    EEPROM的全称是“电可擦除可编程只读存储器”,即Electrically Erasable Programmable Read-Only Memory。是相对于紫外擦除的rom来讲的。但是今天已经存在多种EEPROM的变种,变成了一类存储器的统称。
    狭义的EEPROM:
    这种rom的特点是可以随机访问和修改任何一个字节,可以往每个bit中写入0或者1。这是最传统的一种EEPROM,掉电后数据不丢失,可以保存100年,可以擦写100w次。具有较高的可靠性,但是电路复杂/成本也高。因此目前的EEPROM都是几十千字节到几百千字节的,绝少有超过512K的。
    flash:
    flash属于广义的EEPROM,因为它也是电擦除的rom。但是为了区别于一般的按字节为单位的擦写的EEPROM,我们都叫它flash。**flash做的改进就是擦除时不再以字节为单位,而是以块为单位,一次简化了电路,数据密度更高,降低了成本。**上M字节的rom一般都是flash。
    Flash又分NAND Flash和NOR Flash,NOR型存储内容以编码为主,其功能多与运算相关;NAND型主要功能是存储资料,如数码相机中所用的记忆卡。

  • Nor Flash:主要用来执行片上程序
      优点:具有很好的读写性能和随机访问性能,因此它先得到广泛的应用;
      缺点:单片容量较小且写入速度较慢,决定了其应用范围较窄。

  • NAND Flash:主要用在大容量存储场合
      优点:优秀的读写性能、较大的存储容量和性价比,因此在大容量存储领域得到了广泛的应用;
      缺点:不具备随机访问性能。
    nor flash数据线和地址线分开,可以实现ram一样的随机寻址功能,可以读取任何一个字节。但是擦除仍要按块来擦。
    nand flash同样是按块擦除,但是数据线和地址线复用,不能利用地址线随机寻址。读取只能按页来读取。(nandflash按块来擦除,按页来读,norflash没有页)
    由于nandflash引脚上复用,因此读取速度比nor flash慢一点,但是擦除和写入速度比nor flash快很多。nand flash内部电路更简单,因此数据密度大,体积小,成本也低。因此大容量的flash都是nand型的。小容量的2~12M的flash多是nor型的。
    使用寿命上,nand flash的擦除次数是nor的数倍。而且nand flash可以标记坏块,从而使软件跳过坏块。nor flash 一旦损坏便无法再用。因为nor flash可以进行字节寻址,所以程序可以在nor flash中运行。嵌入式系统多用一个小容量的nor flash存储引导代码,用一个大容量的nand flash存放文件系统和内核。

二、FLASH(W25Q64JV)常见操作

参考FPGA奇哥系列网课

2.1、FLASH常见操作

FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议

2.2、W25Q64JV芯片存储大小

FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议

2.3、状态寄存器:

BUSY:忙信号,写、擦除操作后自动置0,
WEL:写使能信号,写数据、擦除、写状态寄存器时需要置1.
一般只用这两,有其他需求需要看芯片手册。FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议

2.4、时序图

该芯片存储较大,因此不支持页擦除,最小为块擦除
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
写使能:SPI采用模式0或3
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
写失能:
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
读状态寄存器:0h05则返回第一段状态寄存器数值(7-0bit),0h35为第二段,0h15为第三段,第三段时QSPI才有的。
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
读数据: 读数据时候先传输指令03h,然后地址(24bit分别对应8位扇区地址、8位页地址和8位字节地址),然后FLASH返回读数据
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
页编程: 写数据之前需要先执行擦除,至少写一个byte数据,最大可写246byte,此时字节地址应该为0,若不是从0开始,当写到当前页最后一个地址时,不会跳到下一页,会返回到当前页0地址开始写起。
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
扇区擦除 给扇区擦除指令和地址即可,地址当中的页地址、字节地址没关系,只看扇区地址(本人没有验证过,但看到过这样一句话,有兴趣可以自己验证一下,验证好记得戳一戳我hhh)
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
块擦除(32KB块)
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
块擦除(64KB块)
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
全片擦除:
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议
读厂商ID
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议

三、程序设计框图

完整代码参考GiTHub:https://github.com/shun6-6/FLASH_spi
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议

3.1、FLASH_drive模块

FLASH_drive模块与用户模块和FLASH芯片连接
用户模块输入读写操作指令,以及相应的读写数据地址和长度,FLASH_drive模块结果处理后通过SPI将数据写入FLASH或从中读取数据。
以下为接口代码:

module Flash_drive#(
    parameter                      P_DATA_WIDTH  = 8  ,
    parameter                      P_SPI_CPOL    = 0  ,
    parameter                      P_SPI_CPHL    = 0  ,
    parameter                      P_READ_DWIDTH = 8  ,
    parameter                      P_OP_LEN      = 32  
)(
    input       i_clk                                       ,
    input       i_rst                                       ,
    /*--------user接口--------*/ 
    input  [1 :0]                   i_operation_type        ,
    input  [23:0]                   i_operation_addr        ,
    input  [8 :0]                   i_operation_byte_num    ,
    input                           i_operation_valid       ,
    output                          o_operation_ready       ,
    input  [P_DATA_WIDTH - 1 : 0]   i_write_data            ,
    input                           i_write_sop             ,
    input                           i_write_eop             ,
    input                           i_write_valid           ,
    output [P_DATA_WIDTH - 1 : 0]   o_read_data             ,
    output                          o_read_sop              ,
    output                          o_read_eop              ,
    output                          o_read_valid            ,   
    /*--------spi接口--------*/
    output                          o_spi_cs                ,
    output                          o_spi_clk               ,
    output                          o_spi_mosi              ,
    input                           i_spi_miso              
);

3.2、FLASH_ctrl模块

FLASH_ctrl模块将用户操作指令以及数据进行处理,并产生相应指令驱动SPI_drive模块。
对于写数据过程:用户模块会将写指令、写地址以及写数据发送至FLASH_ctrl模块,FLASH_ctrl模块将数据存至本地FIFO,并发送写使能指令和写数据指令,并且根据SPI_drive模块的i_user_write_req信号把FIFO当中存入的用户写数据一个个取出,这是因为用户输入的的数据都是并行的8bit数据,而SPI是穿行传输的,所以需要SPI_drive串行传输完一个byte之后,向FLASH_ctrl模块发起下一个byte请求,也就是i_user_write_req信号。注:在写同一个地址的时候,一定要先擦除,再写,这是因为FLASH芯片只能把1变为0,不可以把0变为1,需要重新擦除,将芯片变为全1,才可以继续写。
对于读数据过程:用户模块输入读指令、读地址以及要读取的数据长度信息告知FLASH_ctrl模块,FLASH_ctrl模块会产生相应的读指令以控制SPI_drive模块读FLASH,并且将读到的数据先存入FIFO,最后完整的传递给用户模块。
FLASH_ctrl模块接口代码:

module Flash_ctrl#(
    parameter                       P_DATA_WIDTH  = 8       ,//数据位宽
    parameter                       P_SPI_CPOL    = 0       ,//spi时钟极性:0/1表示空闲时钟电平为0/1
    parameter                       P_SPI_CPHL    = 0       ,//spi时钟相位:0/1表示数据采集沿为时钟第1/2跳变沿
    parameter                       P_READ_DWIDTH = 8       ,//读数据位宽
    parameter                       P_OP_LEN      = 32       //操作数据长度
)(      
    input                           i_clk                   ,
    input                           i_rst                   ,
    /*--------用户接口--------*/        
    input  [1 :0]                   i_operation_type        ,//操作类型 1:read 2:write
    input  [23:0]                   i_operation_addr        ,//操作地址
    input  [8 :0]                   i_operation_byte_num    ,//max write 256 byte
    input                           i_operation_valid       ,//操作有效信号
    output                          o_operation_ready       ,//操作准备信号

    input  [P_DATA_WIDTH - 1 : 0]   i_write_data            ,//写数据
    input                           i_write_sop             ,//写数据-开始信号
    input                           i_write_eop             ,//写数据-结束信号
    input                           i_write_valid           ,//写数据有效

    output [P_DATA_WIDTH - 1 : 0]   o_read_data             ,//读数据
    output                          o_read_sop              ,//读数据-开始信号
    output                          o_read_eop              ,//读数据-结束信号
    output                          o_read_valid            ,//读数据有效
    /*--------驱动接口--------*/            
    output [P_OP_LEN - 1 : 0]       o_user_op_data          ,//操作数据(数据8+地址24)
    output [1:0]                    o_user_op_type          ,//操作类型(读写数据,读写指令)
    output [15:0]                   o_user_op_len           ,//操作数据长度(读写数据8+24,指令8)
    output [15:0]                   o_user_clk_len          ,//时钟周期,读写数据时为8+24+8*字节数
    output                          o_user_op_valid         ,//用户数据有效信号
    input                           i_user_op_ready         ,//驱动准备信号

    output [P_DATA_WIDTH - 1 : 0]   o_user_write_data       ,//写数据
    input                           i_user_write_req        ,//写数据请求

    input  [P_READ_DWIDTH - 1 : 0]  i_user_read_data        ,//读数据
    input                           i_user_read_valid        //读数据有效
    );

FLASH_ctrl模块状态机描述代码:

//FSM 
localparam  P_ST_IDLE      = 11'b00000000001,//空闲状态,握手成功后进入运行状态
            P_ST_RUN       = 11'b00000000010,//运行状态,如果是读指令则进入读数据状态,否则为擦除或者写数据指令,都需要先进入写使能状态
            P_ST_W_EN      = 11'b00000000100,//写使能状态,若为写数据指令则进入写指令状态,否则进入擦除状态
            P_ST_W_INS     = 11'b00000001000,//写数据指令状态
            P_ST_W_DATA    = 11'b00000010000,//写数据状态
            P_ST_R_INS     = 11'b00000100000,//读数据指令状态
            P_ST_R_DATA    = 11'b00001000000,//读数据状态
            P_ST_CLEAR     = 11'b00010000000,//擦除状态
            P_ST_BUSY      = 11'b00100000000,//读忙状态寄存器
            P_ST_BUSY_CHK  = 11'b01000000000,//检查返回的忙状态寄存器状态,若为忙则进入P_ST_BUSY_WAIT状态,不忙则说明读数据结束,返回空闲状态
            P_ST_BUSY_WAIT = 11'b10000000000;//读忙等待状态,计数256后再次返回P_ST_BUSY读忙状态

FLASH_ctrl模块状态机跳转代码:

always @(*)begin
    case (r_st_cur)
        P_ST_IDLE       : r_st_nxt = w_user_op_active   ? P_ST_RUN      : P_ST_IDLE  ;
        P_ST_RUN        : r_st_nxt = ri_operation_type == P_READ_TYPE ? P_ST_R_INS : P_ST_W_EN;
        P_ST_W_EN       : r_st_nxt = w_spi_op_active    ? 
                                     ri_operation_type == P_WRITE_TYPE ? P_ST_W_INS : P_ST_CLEAR
                                    : P_ST_W_EN  ;
        P_ST_W_INS      : r_st_nxt = w_spi_op_active    ? P_ST_W_DATA   : P_ST_W_INS ;
        P_ST_W_DATA     : r_st_nxt = i_user_op_ready    ? P_ST_BUSY     : P_ST_W_DATA;
        P_ST_R_INS      : r_st_nxt = w_spi_op_active    ? P_ST_R_DATA   : P_ST_R_INS ;
        P_ST_R_DATA     : r_st_nxt = i_user_op_ready    ? P_ST_BUSY     : P_ST_R_DATA;
        P_ST_CLEAR      : r_st_nxt = w_spi_op_active    ? P_ST_BUSY     : P_ST_CLEAR ;
        P_ST_BUSY       : r_st_nxt = w_spi_op_active    ? P_ST_BUSY_CHK : P_ST_BUSY  ;      
        P_ST_BUSY_CHK   : r_st_nxt = ri_user_read_valid ? 
                                     ri_user_read_data[0] ? P_ST_BUSY_WAIT : P_ST_IDLE
                                     : P_ST_BUSY_CHK;  
        P_ST_BUSY_WAIT  : r_st_nxt = r_st_cnt == 255    ? P_ST_BUSY     : P_ST_BUSY_WAIT;
        default         : r_st_nxt = P_ST_IDLE;      
    endcase
end

3.3、spi_drive模块

该模块则是按照SPI协议和FLASH的相关操作指令,将输入的指令以及数据发送给FLASH。
spi_drive模块接口代码:

module spi_drive#(
    parameter                      P_DATA_WIDTH  = 8  ,
    parameter                      P_SPI_CPOL    = 0  ,
    parameter                      P_SPI_CPHL    = 0  ,
    parameter                      P_READ_DWIDTH = 8  ,
    parameter                      P_OP_LEN      = 32  //操作数据长度
)( 
    input                          i_clk              ,
    input                          i_rst              ,
                               
    output                         o_spi_cs           ,//spi片选信号
    output                         o_spi_clk          ,//spi时钟线
    output                         o_spi_mosi         ,//spi主机输出
    input                          i_spi_miso         ,//spi主机输入
 
    input  [P_OP_LEN - 1 : 0]      i_user_op_data     ,//操作数据(数据8+地址24)
    input  [1:0]                   i_user_op_type     ,//操作类型(读写数据,读写指令)
    input  [15:0]                  i_user_op_len      ,//操作数据长度(读写数据8+24,指令8)
    input  [15:0]                  i_user_clk_len     ,//时钟周期,读写数据时为8+24+8*字节数
    input                          i_user_op_valid    ,//用户数据有效信号
    output                         o_user_op_ready    ,//主机准备信号
 
    input  [P_DATA_WIDTH - 1 : 0]  i_user_write_data  ,//写数据
    output                         o_user_write_req   ,//写数据请求
 
    output [P_READ_DWIDTH - 1 : 0] o_user_read_data   ,//读数据
    output                         o_user_read_valid   //读数据有效

    );

SPI协议的实现过程:
该FLASH芯片支持的SPI是模式0和3,波形图当中是模式0。
run运行信号在片选信号cs拉低时同步拉高,同时开启一个1bit计数器r_spi_cnt,该计数器波形与spi_clk一致,因此以此计数器可以表示当前时钟的上升沿或者下降沿,模式0是在时钟的下降沿改变数据,上升沿采样数据。
FPGA使用SPI控制FLASH,FPGA低速接口系列学习,fpga开发,学习,网络协议文章来源地址https://www.toymoban.com/news/detail-841433.html

到了这里,关于FPGA使用SPI控制FLASH的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA】SPI读写flash

    SPI是同步全双工通信,通信原理以主从方式工作,通常有一个主设备和一个或多个从设备,需要4根线连接:MISO(主设备数据输入)、MOSI(主设备输出)、SCLK(时钟)、CS(片选)。通常拉低对应从机的片选来收发数据。 MISO:主设备输入,从设备输出 MOSI:主设备输出,从设备输入 SCLK:时

    2024年02月05日
    浏览(44)
  • 【FPGA】SPI读写FLASH闪存

    通信原理 SPI也是以主从方式工作,通常需要四根线来完成数据的传输,分别是MISO MOSI CS SCLK。以下是这四根线代表的含义: MISO:主设备输入,从设备输出 MOSI:主设备输出,从设备输入 CS :片选信号,选择进行通信的从设备 SCLK:时钟线,由主设备产生给到从设备 SPI通信的

    2024年02月16日
    浏览(40)
  • FPGA模块——SPI协议(读写FLASH)

    芯片引脚图: 内部结构图: 存储区域总共分成了32块,每块64KB。每块又分成了16个部分,每个部分4KB。方便进行读取和局部操作。 电路设计 SPI的四种模式 这里使用这个模式: 主机和从机在时钟上升沿放入要输出的数据,在时钟下降沿读取要输入的数据。 8个时钟后交换一个

    2024年02月05日
    浏览(47)
  • 【FPGA】SPI-FLASH-M25P16手册解读

    M25P16概述: M25P16是一款带有先进写保护机制和高速SPI总线访问的串行Flash存储器。M25P16特点如下: 存储结构:16M Bit(2M Byte)的存储空间,一共32个扇区(sector),每个扇区256页,每页256字节,每个字节的的存储地址由扇区地址(8bit)+页地址(8bit)+字节地址(8bit)构成。 SP

    2024年02月04日
    浏览(40)
  • FPGA实现SPI接口(1)--什么是SPI接口?

    目录 1、什么是SPI协议 2、SPI协议详述 2.1、SPI协议物理层 2.2、SPI 协议层 2.3、SPI协议通信过程 2.4、SPI协议的特性 2.5、SPI协议的优势、劣势 3、驱动代码的设计实现 3.1、接口定义与整体设计 3.2、Verilog代码 4、Testbench及仿真结果 4.1、单个BYTE的仿真 4.2、多个BYTE的仿真 5、其他  

    2024年02月09日
    浏览(44)
  • FPGA常见接口及逻辑实现(三)—— SPI

    一、SPI协议简介         SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种同步串行接口,相对于之前介绍过的UART和I2C,SPI的速率就高出很多,最高能到100M左右,SPI协议比较简单,就不多做介绍,主要介绍下与UART和I2C的不同,SPI是一主多从协议,每个从机通过

    2024年04月26日
    浏览(34)
  • [FPGA IP系列] FPGA常用存储资源大全(RAM、ROM、CAM、SRAM、DRAM、FLASH)

    本文主要介绍FPGA中常用的RAM、ROM、CAM、SRAM、DRAM、FLASH等资源。 RAM(Random Access Memory)是FPGA中最基本和常用的内部存储块,根据不同架构可以实现不同容量,最大可达几十Mb。 FPGA中的RAM主要包括: 分布式RAM:存在于逻辑块(LE)中的小容量RAM,通常为几百比特到几千比特。 块RAM:F

    2024年02月12日
    浏览(49)
  • FPGA驱动SPI接口的LCD(三)——LCD的初始化

    LCD初始化函数 void LCD_Init(void);  首先是LCD的复位 void LCD_RESET(void) {     LCD_RST_CLR;        //拉低复位引脚     Delay_Ms(100);        //延时100ms         LCD_RST_SET;        //拉高复位引脚     Delay_Ms(50);        //延时50ms } 向LCD屏幕写入一个8位命令 void LCD_WR_REG(u8 data) {     

    2024年02月01日
    浏览(40)
  • 【FLASH存储器系列八】ONFI数据接口详述之一

    👉个人主页: highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 目录 1.1 数据接口类型概览 1.2 信号功能分配 1.3 接口模式切换         ONFI目前支持5中不同的数据接口类型:SDR,NV-DDR,NV-DDR2、NV-DDR3和NV-LPDDR4。SDR是传统的NAND接口,使

    2024年02月13日
    浏览(68)
  • GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相关操作

    本文主要针对使用GD(兆易创新)系列的FLASH做启动配置片时,遇到的相关问题进行简单整理复盘,避免后人踩坑。 本人操作固化芯片型号为:ZYNQ7045、690T(复旦微替代型号V7 690T)。 由于GD SPI Flash器件和进口器件的厂家ID不一致,而Vivado软件又不支持跳过ID检查,导致使用G

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包