当前位置:首页 > 后端开发 > 正文内容

Flash驱动操控--芯片擦除(SPI协议)

邻居的猫1个月前 (12-09)后端开发1705

摘要: 本篇博客详细包括SPI协议的根本原理、形式挑选以及时序逻辑要求,选用FPGA(EPCE4),经过SPI通讯协议,对flash(W25Q16BV)存储的固化程序进行芯片擦除操作。

关键词:SPI;Verilog HDL;Flash


【SPI协议通讯形式】

SPI是Motorola公司推出的一种同步串行接口,是一种高速、全双工、同步的通讯总线,广泛应用于存储器,数模转化器,实时时钟等。

  • 长处:支撑全双工通讯,通讯办法简略,相对数据传输速率较快。
  • 缺点:没有指定的流操控,没有应对机制,数据可靠性上存在缺点。

SPI协议经过四根线进行数据传输,即SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、/SS(Slave Select,低电平有用)(或/CS)。

接口处理办法:一主一从(左)、一主多从【星型链式】(右)SPI通讯要求主机和从机具有同步的时钟信号,传输速率直接遭到时钟频率(SCLK)的影响。

image

信号线阐明:

MOSI、MISO数据在SCK同步信号下传输,每个时钟周期传输一位数据,输入输出同步进行,要保证MSB或LSB先行需共同。/SS从设备信号挑选线,由高变低,是SPI通讯的起始信号。当从设备/SS线检测到起始信号后,即为选中使能与主机通讯。/SS信号由低变高,为中止信号,从设备的选中状况被撤销。

注:SPI每次数据传输能够8位或16位为单位,每次传输的单位数不受约束。

SPI通讯时钟形式:

SPI通讯加入了时钟相位(CPHA)时钟极性(CPOL)的设置,经过组合CPOL和CPHA的不同设置,SPI共支撑四种常见的时钟装备形式。

CPOL CPHA
时钟极性,界说时钟信号在闲暇状况下的电平 时钟相位,界说数据采样和转化的时钟边际
CPOL=0:SCK闲暇为低电平 CPHA=0:SCK的第一个边际采样数据并转化输出信号
CPOL=1:SCK闲暇为高电平 CPHA=1:SCK的第二个边际采样数据并转化输出信号

​ 在CPHA指示为l时, 数据就会在SCLK的第二个有用边际被采样(/SS拉低后,闲暇为高,为上升沿;闲暇为低,下降沿),一起被锁存到寄存器中;假如CPHA 清零,数据就会在SCLK的第一个有用边际被采样(/SS拉低后,闲暇为高,为下降沿;闲暇为低,为上升沿),一起被锁存起来。SPI的主从设备须装备相同的时序形式,见下图。

image

【W25Q16BV操作阐明】

板载Flash芯片型号:W25Q16BV;总容量为16M bit,即2M字节;存储阵列被分红8192个可编程页,每页容量256字节;支撑Standard SPI、Dual SPI和Quad SPI三种SPI通讯协议,最大读/写传输速率达50MB/s。它支撑多种擦除操作,包括扇区擦除(4KB)、块擦除(32KB或64KB)以及全芯片擦除。

1、接口处理与结构逻辑

image

上图能够看到,除SPI经典的四个引脚外,还有/WP和/HOLD,别离用于写维护和输入坚持。关于不同倍率SPI协议,引脚运用调配是有差异的。

W25Q16BV内部存储结构的逻辑和功用安排见下图,SPI接口担任接纳指令和地址,并经过操控逻辑进行解析和履行。状况寄存器(Status Register)用于存储设备的状况信息,如是否繁忙(BUSY位);写操控经过IO2引脚操控,用于发动写操作;高电平生成器(High Voltage Generators)用于履行如擦除等操作;操控逻辑(Control Logic)担任解析SPI接口接纳到的指令,并依据需求操控存储器的读/写操作。列解码(Column Decode)和页面缓冲(256-Byte Page Buffer)用于支撑页面的读/写操作。

image

存储器部分被分割成32个块(Block),单个块区包括16个扇区(Sector),每个扇区又由16个页组成,单页存储256字节数据,合计32 x 16 x 16 x 256 ≈ 2M 字节。存储器经过页地址和字节地址来定位特定的数据方位。

24位地址线经过上述的层次结构来映射整个存储器的地址空间,详细见下面表格。

分区 地址位
块(Block)地址 23~16位(0x1F0000到0x1FFFFF)
扇区(Sector)地址 15~12位(0x00F000到0x00FFFF)
页(Page)地址 11~8位
字节(Byte)地址 7~0位

2、指令与时序阐明

软件指令:W25Q16BV的指令集由30条根本指令组成,指令彻底经过SPI总线操控。指令的发动是经过/CS的下降边际来触发的,/CS拉高前须完结指令输入,不然无效。DI输入的第一个字节供给指令代码,DI输入上的数据是在时钟的上升沿采样的,首要采样的是最高有用位(MSB)。指令的长度从单个字节到几个字节不等,后边或许跟着地址字节、数据字节、虚拟字节(可选),在某些情况下,还或许是它们组合。一切的读指令都能够在任何一个时钟位之后完结。

指令 编码 指令 编码
Write Enable 06h Write Disable 04h
Sector Erase (4KB) 20h Block Erase (32KB) 52h
Block Erase (64KB) D8h Chip Erase C7h/60h
Continuous Read Mode Reset FFh Read Data 03h
Fast Read 0Bh Write Status Register 01h

一切写、编程或擦除指令有必要在字节鸿沟上完结(即,在完好的8位数据被时钟同步后,/CS被驱动为高)。假如不在字节鸿沟上完结,该指令将被停止。这一特性旨在维护设备免受意外写入的影响。

当内存正在被编程或擦除,或许当状况寄存器正在被写入时,除了读状况寄存器指令之外的一切指令都将被疏忽,直到编程或擦除周期完结。

电平切换时序要求:

下图为Serial Input Timing,其间片选线/CS待输入完结后拉高电平坚持时刻(tSHSL) (for Array Read Array Read / Erase or Program Read Status Registers) :至少7/40 ns;片选信号有用树立时刻(tSLCH):至少为5ns;片选信号有用坚持时刻(tCHSH):至少为5ns。留意:读指令/写指令时钟频率最大为50Mhz

image

写使能(Write Enable ):该指令用于设置(状况寄存器中)写使能锁存器(WEL)位为1,保证存储器处于可写状况。

image

首要,将/CS(Chip Select)引脚拉低,SPI通讯发动。在CLK上升沿,将数据输入(DI)引脚上的数据位设置为指令代码“06h”,即0000 0110。完结后,将/CS引脚拉高,SPI通讯的完毕和写使能完结。

读操作(Read Data):这个指令答应从存储器中次序地读取一个或多个数据字节。首要,经过将/CS引脚拉低来发动指令,将指令代码“03h”(0000 0011)和一个24位地址(A23-A0)经过DI引脚移位输入,代码和地址位在CLK上升沿时被确定。最终,经过将/CS引脚拉高完结指令。

image

假如在擦除、编程或写入周期正在进行时(BUSY=1)宣布读取数据指令,该指令将被疏忽。

芯片全擦除操作(Chip Erase):Chip Erase 指令会将设备内的一切存储器设置为擦除状况,即一切位都设为1。

image

①擦除发动:在履行芯片擦除指令之前,有必要先履行一个“写使能”指令,使设备能够承受芯片擦除指令(状况寄存器的WEL位有必要等于1)。将/CS引脚拉低来发动指令,移位输入指令代码“C7h”或“60h”,在第八位被确定后,/CS引脚须被拉高。

②擦除进程:/CS被拉高后,自计时的芯片擦除指令将开端履行。芯片擦除周期(典型3s,最大10s)进行期间,依然能够经过“读取状况寄存器”指令来查看BUSY位的状况(BUSY位在芯片擦除周期期间为1)。

③擦除后的状况:WEL位会被置0,留意:存储数据的任何部分遭到块维护(BP2、BP1和BP0)位的维护,则不会履行芯片擦除指令。

【Flash全擦除操作】

1、Quartus II进行程序固化下载及擦除

烧录程序办法:①将程序下载到FPGA内部的SRAM之中,烧录进程耗时较短,但掉电后程序丢掉;②将程序固化到FPGA外部挂载的非易失性存储器Flash芯片,掉电后程序不丢掉。

在Quartus II的主界面中,挑选“File”菜单下的“Convert Programming Files”选项,用于将编译生成的特定文件(如sof文件)转化为其他格局的文件,如jic文件,以便下载到FPGA板载的flash或其他方针设备中,流程见下图。

image

下载程序时,方针.jic文件后,右下指示框很明显看到下载至Flash(这儿是EPCS16相似W25Q16),仅勾选Program/Configure 进行程序固化下载,仅勾选Erase表明擦除Flash操作。

image

2、Verilog程序完结Flash芯片擦除操作(SPI)

依据Flash读/写时序要求,片选信号拉低后,需进行5ns(tSLCH≥5ns)等候时刻,及后写入写使能指令。写入完结后,再次进行5ns(tCHSH≥5ns)等候,拉高片选线坚持≥100ns,接续完结写入操作指令流程。

image

Flash芯片数据读操作的时钟频率(SCK)上限为50MHz,这儿经过四分频设定SCK频率为12.5Mhz。单个时钟周期写入1 bit数据,完好的单字节指令需求8个完好的SCK时钟周期,即32个完好的体系时钟,体系时钟频率为50MHz,完好指令的写入需求640ns。

image

mosi信号输出选用了状况机搬运的逻辑办法:

状况 阐明 状况 阐明
IDLE 闲暇初始状况,等候触发信号 WR_EN 发送写使能指令
DELAY 等候状况,坚持时序 CH_ER 芯片擦除指令发送

key_flag信号有用时,从IDLE搬运到WR_EN状况,在WR_ENCH_ER状况中,别离写入相应的写使能和指令后,等候tCHSH时刻,然后拉高片选信号。在WR_EN状况写入指令后,搬运到DELAY状况等候tSHSL时刻。在DELAY状况等候完结后,搬运到CH_ER状况,回来IDLE状况。相关代码如下:

parameter   IDLE = 4'b0001,	WREN = 4'b0010,	DELAY= 4'b0100,	CH_ER= 4'b1000;
parameter   WREN_CODE = 8'b0000_0110,	CH_ER_CODE = 8'b1100_0111;
            
always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	state <= IDLE;
    else case(state)
            IDLE :if(key_flag)state <= WREN;
            WREN :if((cnt_byte == 3'd2)&&(cnt_clk == 5'd31))state <= DELAY;
            DELAY:if((cnt_byte == 3'd3)&&(cnt_clk == 5'd31))state <= CH_ER;
            CH_ER:if((cnt_byte == 3'd6)&&(cnt_clk == 5'd31))state <= IDLE;
            default:state <= IDLE;
        endcase
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	mosi <= 1'b0;
    else if((state == WREN)&&(cnt_byte == 3'd2))	 mosi <= 1'b0;
    else if((state == CH_ER)&&(cnt_byte == 3'd6))	 mosi <= 1'b0;
    else if((state == WREN)&&(cnt_byte == 3'd1)&&(cnt_sck == 2'd0))
        mosi <= WREN_CODE[7 - cnt_bit];
    else if((state == CH_ER) && (cnt_byte == 3'd5) && (cnt_sck == 2'd0))
        mosi <= CH_ER_CODE[7 - cnt_bit];
end

而关于其他的信号逻辑处理:cnt_clk作为预期设定单位距离(640ns)的计数器,cnt_byte依据其完结7个阶段的转化。sck为写操作的时钟信号,cnt_sck作为其在有用时刻段内计数器,使得scksys_clk四分配输出。

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	 cnt_clk <= 5'd0;
    else if(state != IDLE)	cnt_clk <= cnt_clk + 1'b1;  //位宽清零
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	cnt_byte <= 3'd0;
    else if((cnt_byte == 3'd6)&&(cnt_clk == 5'd31))	cnt_byte <= 3'd0;
    else if(cnt_clk == 5'd31) cnt_byte <= cnt_byte + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	cnt_sck <= 2'd0;
    else if((state == WREN)&&(cnt_byte == 3'd1))	cnt_sck <= cnt_sck + 1'b1;  //位宽清零
    else if((state == CH_ER)&&(cnt_byte == 3'd5))	cnt_sck <= cnt_sck + 1'b1;  //位宽清零
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	cnt_bit <= 3'd0;
    else if(cnt_sck == 2'd2)	cnt_bit <= cnt_bit + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	ss_n <= 1'b1;
    else if(key_flag)	ss_n <= 1'b0;
    else if((cnt_byte == 3'd2)&&(cnt_clk == 5'd31)&&(state == WREN))	ss_n <= 1'b1;
    else if((cnt_byte == 3'd3)&&(cnt_clk == 5'd31)&&(state == DELAY))	ss_n <= 1'b0;
    else if((cnt_byte == 3'd6)&&(cnt_clk == 5'd31)&&(state == CH_ER))	ss_n <= 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	sck <= 1'b0;
    else if(cnt_sck == 2'd0)	sck <= 1'b0;
    else if(cnt_sck == 2'd2)	sck <= 1'b1;
end

导入仿真文件,对芯片擦除操作进行仿真,因为该操作耗时长,仿真前在Flash参数文件缩放擦除周期至4000ns。从上图仿真成果能够看到,在4710ns处,Flash发动芯片擦除,在8710ns完毕擦除操作。

image

image

依据仿真成果显现,sys_clk拉高后,程序正常作业,当检测到key_flag为高电平后,片选线SS_n拉低,指令操作敞开。等候一个有用树立时刻后(这儿是640ns,便于编写代码),sck正式输出八段时钟切换(12.5Mhz)。首要,按写使能指令,输出一个时序(0000_0110,06h)。等候一个片选线树立时刻后拉高,进入等候状况(≥100ns,640ns)接续完结芯片擦除指令的录入。cnt_bytestate的状况,随cnt_clk时钟计数改换。

image

文献参阅:

[1]刘满. SPI协议接口的规划与完结[D]. 陕西:西安电子科技大学,2020;

[2]根据spi协议的flash驱动操控(https://doc.embedfire.com/fpga/altera/ep4ce10_pro/zh/latest/code/spi_flash.html);

[3] W25Q16BV Datasheet(PDF) - Winbond (alldatasheet.com);


本篇文章中运用的Verilog程序模块,若有需见网页左栏Gitee库房链接:https://gitee.com/silly-big-head/little-mouse-funnyhouse/tree/FPGA-Verilog/

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=258

标签: FPGA-Verilog类
分享给朋友:

“Flash驱动操控--芯片擦除(SPI协议)” 的相关文章

万字长文详解怎么运用Swift进步代码质量

万字长文详解怎么运用Swift进步代码质量

前语 京喜APP最早在2019年引入了Swift,运用Swift完成了第一个订单模块的开发。之后一年多咱们继续在团队/公司内部推行和遍及Swift,现在Swift现已支撑了70%+以上的事务。经过运用Swift进步了团队内同学的开发功率,一起也带来了质量的进步,现在来自Swift的Crash的占比不...

Flutter/Dart第05天:Dart特别特性Mixin详解

Flutter/Dart第05天:Dart特别特性Mixin详解

Dart官网文档:https://dart.dev/language/mixins 重要阐明:本博客依据Dart官网文档,但并不是简略的对官网进行翻译,在掩盖中心功用情况下,我会依据个人研制经历,参加自己的一些扩展问题和场景验证。 Mixin意图和运用办法(with) 官网文档:Mixins are...

c语言gets函数,使用、风险与替代方案

在C语言中,`gets` 函数用于从标准输入(通常是键盘)读取一行字符串,直到遇到换行符 `` 或文件结束符 EOF。它将读取的字符串存储在指定的缓冲区中,并自动在字符串末尾添加一个空字符 `0` 以表示字符串的结束。需要注意的是,`gets` 函数存在一个严重的安全问题:它不会检查目标缓冲区的大小...

java算法,基础概念与常用算法解析

java算法,基础概念与常用算法解析

Java是一种广泛使用的高级编程语言,用于开发各种应用程序,包括桌面应用程序、Web应用程序、移动应用程序和游戏等。在Java中实现算法时,通常需要遵循一定的步骤和最佳实践,以确保代码的效率、可读性和可维护性。1. 理解算法:在开始编码之前,确保你完全理解了算法的工作原理。这包括理解算法的输入、输出...

c语言按位取反

c语言按位取反

在C语言中,按位取反可以通过按位取反运算符 `~` 来实现。这个运算符会将操作数的每一位都取反,即0变成1,1变成0。下面是一个简单的例子,演示如何使用按位取反运算符:```cinclude int main { int num = 5; // 二进制表示为 101 int invert...

verilog语言入门教程,verilog语言

如果你想学习Verilog语言,这里有几篇入门教程可以参考:1. 菜鸟教程 Verilog 教程 这篇教程介绍了Verilog HDL的基本语法、设计层次和仿真方法,适合初学者和进阶者。通过实例和代码,你可以学习如何用Verilog设计数字电路,如4位宽10进制计数器。 2. CSDN...