目录

Flash扇区擦除

实现原理

verilog设计代码

verilog测试代码


Flash扇区擦除

实现原理

扇区的概念

  • Flash型号的数字代表容量,单位兆bit,如M25P16,此Flash的容量为16Mbit;
  • Flash的内存大小,扇区大小,页大小在数据手册中可以查看;
  • 每个扇区的地址范围在数据手册中给出, 地址中前两位是扇区地址,中间两位是页地址,后两位是字节地址;
  • 扇区擦除即把选中的扇区全置为1,擦除的最小单位是扇区(不能进行页擦除)

扇区擦除步骤

  1. 在写入扇区擦除指令之前需要写入写使能指令WREN,写入时拉低片选信号,写入完成拉高片选信号,写入写使能指令后便会变为写锁存状态,在此状态下才能进行扇区擦除指令写入;
  2. 写入扇区擦除指令SE和三个字节的扇区地址(选中扇区的任意地址都可),通过MOSI端口写入指令,写入完成则将片选信号拉高,若不拉高,则此指令不会执行;
  3. 扇区擦除指令写入后要等待一个全擦除周期完成擦除操作,周期时间可查看数据手册中的
  4. 以上步骤需要遵循串行输入时序,可在数据手册中查看,见下图;
  5. 需要查看数据手册中Flash读写操作对时钟频率的要求;

注:与全擦除相比只是在写入的擦除指令不同和多了三个字节的扇区地址写入,见下图。

时序图中的表示也同全擦除一样,上一篇文章全擦除中已给出解释,这里不再给出。

verilog设计代码

module  flash_se_ctrl
(input   wire    sys_clk     ,   //系统时钟,频率50MHzinput   wire    sys_rst_n   ,   //复位信号,低电平有效input   wire    key         ,   //按键输入信号output  reg     cs_n        ,   //片选信号output  reg     sck         ,   //串行时钟output  reg     mosi            //主输出从输入数据
);//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************////parameter define
parameter   IDLE    =   4'b0001 ,   //初始状态WR_EN   =   4'b0010 ,   //写状态DELAY   =   4'b0100 ,   //等待状态SE      =   4'b1000 ;   //扇区擦除状态
parameter   WR_EN_INST  =   8'b0000_0110,   //写使能指令SE_INST     =   8'b1101_1000;   //扇区擦除指令
parameter   SECTOR_ADDR =   8'b0000_0000,   //扇区地址PAGE_ADDR   =   8'b0000_0100,   //页地址BYTE_ADDR   =   8'b0010_0101;   //字节地址//reg   define
reg     [3:0]   cnt_byte;   //字节计数器
reg     [3:0]   state   ;   //状态机状态
reg     [4:0]   cnt_clk ;   //系统时钟计数器
reg     [1:0]   cnt_sck ;   //串行时钟计数器
reg     [2:0]   cnt_bit ;   //比特计数器//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************////cnt_clk:系统时钟计数器,用以记录单个字节
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_clk  <=  5'd0;else    if(state != IDLE)cnt_clk  <=  cnt_clk + 1'b1;//cnt_byte:记录输出字节个数和等待时间
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_byte    <=  4'd0;else    if((cnt_clk == 5'd31) && (cnt_byte == 4'd9))cnt_byte    <=  4'd0;else    if(cnt_clk == 31)cnt_byte    <=  cnt_byte + 1'b1;//cnt_sck:串行时钟计数器,用以生成串行时钟
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_sck <=  2'd0;else    if((state == WR_EN) && (cnt_byte == 1'b1))cnt_sck <=  cnt_sck + 1'b1;else    if((state == SE) && (cnt_byte >= 4'd5) && (cnt_byte <= 4'd8))cnt_sck <=  cnt_sck + 1'b1;//cs_n:片选信号
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)cs_n    <=  1'b1;else    if(key == 1'b1)cs_n    <=  1'b0;else    if((cnt_byte == 4'd2) && (cnt_clk == 5'd31) && (state == WR_EN))cs_n    <=  1'b1;else    if((cnt_byte == 4'd3) && (cnt_clk == 5'd31) && (state == DELAY))cs_n    <=  1'b0;else    if((cnt_byte == 4'd9) && (cnt_clk == 5'd31) && (state == SE))cs_n    <=  1'b1;//sck:输出串行时钟
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)sck <=  1'b0;else    if(cnt_sck == 2'd0)sck <=  1'b0;else    if(cnt_sck == 2'd2)sck <=  1'b1;//cnt_bit:高低位对调,控制mosi输出
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_bit <=  3'd0;else    if(cnt_sck == 2'd2)cnt_bit <=  cnt_bit + 1'b1;//state:两段式状态机第一段,状态跳转
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)state   <=  IDLE;elsecase(state)IDLE:   if(key == 1'b1)state   <=  WR_EN;WR_EN:  if((cnt_byte == 4'd2) && (cnt_clk == 5'd31))state   <=  DELAY;DELAY:  if((cnt_byte == 4'd3) && (cnt_clk == 5'd31))state   <=  SE;SE:     if((cnt_byte == 4'd9) && (cnt_clk == 5'd31))state   <=  IDLE;default:    state   <=  IDLE;endcase//mosi:两段式状态机第二段,逻辑输出
always@(posedge sys_clk or  negedge sys_rst_n)if(sys_rst_n == 1'b0)mosi    <=  1'b0;else    if((state == WR_EN) && (cnt_byte == 4'd2))mosi    <=  1'b0;else    if((state == SE) && (cnt_byte == 4'd9))mosi    <=  1'b0;else    if((state == WR_EN) && (cnt_byte == 4'd1) && (cnt_sck == 5'd0))mosi    <=  WR_EN_INST[7 - cnt_bit];  //写使能指令else    if((state == SE) && (cnt_byte == 4'd5) && (cnt_sck == 5'd0))mosi    <=  SE_INST[7 - cnt_bit];    //扇区擦除指令else    if((state == SE) && (cnt_byte == 4'd6) && (cnt_sck == 5'd0))mosi    <=  SECTOR_ADDR[7 - cnt_bit];  //扇区地址else    if((state == SE) && (cnt_byte == 4'd7) && (cnt_sck == 5'd0))mosi    <=  PAGE_ADDR[7 - cnt_bit];    //页地址else    if((state == SE) && (cnt_byte == 4'd8) && (cnt_sck == 5'd0))mosi    <=  BYTE_ADDR[7 - cnt_bit];    //字节地址endmodule

verilog测试代码

module  tb_flash_se_ctrl();//wire  define
wire    cs_n;
wire    sck ;
wire    mosi ;//reg   define
reg     sys_clk     ;
reg     sys_rst_n   ;
reg     key         ;//时钟、复位信号、模拟按键信号
initialbeginsys_clk     =   0;sys_rst_n   <=  0;key <=  0;#100sys_rst_n   <=  1;#1000key <=  1;#20key <=  0;endalways  #10 sys_clk <=  ~sys_clk;//写入Flash仿真模型初始值(全F)
defparam memory.mem_access.initfile = "initmemory.txt";//------------- flash_se_ctrl_inst -------------
flash_se_ctrl  flash_se_ctrl_inst
(.sys_clk    (sys_clk    ),  //系统时钟,频率50MHz.sys_rst_n  (sys_rst_n  ),  //复位信号,低电平有效.key        (key        ),  //按键输入信号.sck        (sck        ),  //串行时钟.cs_n       (cs_n       ),  //片选信号.mosi       (mosi       )   //主输出从输入数据
);//------------- memory -------------
m25p16  memory
(.c          (sck    ),  //输入串行时钟,频率12.5Mhz,1bit.data_in    (mosi   ),  //输入串行指令或数据,1bit.s          (cs_n   ),  //输入片选信号,1bit.w          (1'b1   ),  //输入写保护信号,低有效,1bit.hold       (1'b1   ),  //输入hold信号,低有效,1bit.data_out   (       )   //输出串行数据
);endmodule

基于SPI协议的Flash驱动控制-扇区擦除相关推荐

  1. 基于SPI协议的Flash驱动控制-数据普通读操作

    目录 Flash数据普通读操作 实现原理 verilog设计代码 verilog测试代码 Flash数据普通读操作 实现原理 将片选信号拉低,写入读操作指令,最少读取一个字节的数据,写入读指令后要写入 ...

  2. 基于I2C协议的EEPROM驱动控制

    基于I2C协议的EEPROM驱动控制 `timescale 1ns / 1ps module i2c_ctrl #(parameter DEVICE_ADDR = 7'b1010_000,//i2c设 ...

  3. 基于SPI协议的Flash全擦除

    基于SPI协议的Flash全擦除 `timescale 1ns / 1ps module flash_be_ctrl(input wire sys_clk,//系统时钟频率50MHZ input wi ...

  4. FPGA进阶(2):基于I2C协议的EEPROM驱动控制

    文章目录 第49讲:基于I2C协议的EEPROM驱动控制 理论部分 设计与实现 i2c_ctrl i2c_rw_data eeprom_byte_rd_wr tb_eeprom_byte_rd_wr ...

  5. 基于I2C协议的EEPROM驱动控制(笔记整理)

    一.目标 要求:设计一个使用I2C通讯协议的EEPROM读写控制器.使用写按键向EEPROM中写入1~10共10字节数据:使用读按键读出之前写入的数据并显示在数码管上. 分析:①首先按键控制读写操作按 ...

  6. FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用

    写在前面 SPI协议系列文章: FPGA实现的SPI协议(一)----SPI驱动 FPGA实现的SPI协议(二)----基于SPI接口的FLASH芯片M25P16的使用 在上篇文章,简要介绍了SPI协 ...

  7. 基于SPI协议下的OLED显示

    文章目录 一.SPI简介 二.OLED显示 1.任务要求 2.实验器材 3.实验过程 (1)显示自己的学号和姓名 (2) 显示AHT20的温度和湿度 (3)上下或左右的滑动显示长字符(SSD1306驱 ...

  8. 基于 SPI 协议的0.96 寸OLED显示

    目录 一. SPI 协议 1.简介 2.SPI的连接方式 3.通信过程​ 二.OLED 1.OLED原理 2.点阵编码原理与显示 三.OLED显示实验 Demo 程序 1.要求 2. OLED 显示汉 ...

  9. 基于VXWORKS的NAND FLASH驱动程序设计

    基于VXWORKS的NAND FLASH驱动程序设计 3162412793@qq.com 技术交流QQ群: 691976956 目前,随着电子技术的不断发展,计算机技术也得到飞速的发展,产生了很多新技 ...

最新文章

  1. C#对象数组排序方法
  2. “高引用”《牛顿传》重版再出,今晚八点,来直播间“遇见牛顿”!
  3. Springboot 抛出Failed to determine a suitable driver class异常原因
  4. vue 分模块打包 脚手架_手动撸一个webpack4脚手架(仿vuecli2)
  5. neo4j 4.1.8版本安装图算法包
  6. linux mysql v_Linux 主机升级MySQL v5.5 性能提升360%
  7. redis常用集群方案汇总
  8. ubuntu切换python版本
  9. 如何使用WindowsPerformanceToolKit对程序进行分析
  10. 【房屋租赁管理模块的设计与实现】
  11. 优秀的jquery插件
  12. magedu第一天学习(计算机基础部分)
  13. 程序员需谨记的8条团队开发原则
  14. 怎样在大公司混成中层干部
  15. 计算机网络导论 虚电路 X.25 帧中继 ATM
  16. 蚂蚁金服区块链朱永春:蚂蚁金服业务新思路,用以往通用场景结合出新的解决方案...
  17. 使用python对指定手机号获取各网站登录的验证码。
  18. Java+spring+springmvc 基于ssm的家乡特产销售系统#毕业设计
  19. centos php mcrypt,CentOS下安装Php mcrypt扩展方法
  20. 万年历单片机c语言,万年历单片机c语言

热门文章

  1. It Was a Good Barn
  2. blender绑定骨骼法 2 rig
  3. 系统突然变慢的处理方案
  4. linux卡利系统设置密码,Kail Linux2019.04更新:新增“卧底模式” 模拟Win10界面
  5. 手把手教你做树莓派魔镜-MagicMirror(七)-接下来
  6. 实用工具分享——PDF阅读
  7. NO7、斐波那契数列(easy不需再刷)
  8. 第十六章 综合实例——《跟我学Shiro》
  9. 接入Google Sdk 遇到的坑
  10. 前端项目微金所1 - bootstrap模板,Compatible(兼容),Viewport(视口),条件注释,第三方依赖,MediaQuery媒体查询...