08_SPI-Flash 扇区擦除实验

news2024/11/26 6:24:05

08_SPI-Flash 扇区擦除实验

  • 1. 实验目标
  • 2. 操作时序
    • 2.1 扇区擦除操作指令
    • 2.2 完整扇区擦除操作时序
  • 3. 程序框图
    • 3.1 顶层框图
    • 3.2 扇区擦除模块
  • 4. 波形图
  • 5. RTL
    • 5.1 flash_se_ctrl
    • 5.2 spi_flash_se
  • 6. Testbench
    • 6.1 tb_flash_se_ctrl
    • 6.2 tb_spi_flash_se

1. 实验目标

编写扇区擦除工程,擦除事先烧录到 Flash 中的流水灯程序所占的某个扇区,使流水灯程序不能正常工作。在此次实验工程,我们选择擦除第 0 个扇区,擦除地址为24’h00_04_25。

2. 操作时序

2.1 扇区擦除操作指令

扇区擦除(Sector Erase)操作,简称 SE,操作指令为 8’b1101_0000(D8h)。
在这里插入图片描述

2.2 完整扇区擦除操作时序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 程序框图

3.1 顶层框图

在这里插入图片描述

3.2 扇区擦除模块

在这里插入图片描述
在这里插入图片描述

4. 波形图

在这里插入图片描述
在这里插入图片描述

5. RTL

5.1 flash_se_ctrl

`timescale  1ns/1ns




module  flash_se_ctrl
(
    input   wire    sys_clk     ,   //系统时钟,频率50MHz
    input   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;
    else
    case(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

5.2 spi_flash_se

`timescale  1ns/1ns




module  spi_flash_se
(
    input   wire    sys_clk     ,   //系统时钟,频率50MHz
    input   wire    sys_rst_n   ,   //复位信号,低电平有效
    input   wire    pi_key      ,   //按键输入信号

    output  wire    cs_n        ,   //片选信号
    output  wire    sck         ,   //串行时钟
    output  wire    mosi            //主输出从输入数据
);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter   CNT_MAX =   20'd999_999;    //计数器计数最大值

//wire  define
wire    po_key  ;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- key_filter_inst -------------
key_filter
#(
    .CNT_MAX    (CNT_MAX    )   //计数器计数最大值
)
key_filter_inst
(
    .sys_clk    (sys_clk    ),  //系统时钟,频率50MHz
    .sys_rst_n  (sys_rst_n  ),  //复位信号,低电平有效
    .key_in     (pi_key     ),  //按键输入信号

    .key_flag   (po_key     )   //消抖后信号
);

//------------- flash_se_ctrl_inst -------------
flash_se_ctrl  flash_se_ctrl_inst
(
    .sys_clk    (sys_clk    ),  //系统时钟,频率50MHz
    .sys_rst_n  (sys_rst_n  ),  //复位信号,低电平有效
    .key        (po_key     ),  //按键输入信号

    .sck        (sck        ),  //片选信号
    .cs_n       (cs_n       ),  //串行时钟
    .mosi       (mosi       )   //主输出从输入数据
);

endmodule

6. Testbench

6.1 tb_flash_se_ctrl

`timescale  1ns/1ns




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         ;

//时钟、复位信号、模拟按键信号
initial
    begin
        sys_clk     =   0;
        sys_rst_n   <=  0;
        key <=  0;
        #100
        sys_rst_n   <=  1;
        #1000
        key <=  1;
        #20
        key <=  0;
    end

always  #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

6.2 tb_spi_flash_se

`timescale  1ns/1ns




module  tb_spi_flash_se();

//wire  define
wire    cs_n;
wire    sck ;
wire    mosi ;

//reg   define
reg     clk     ;
reg     rst_n   ;
reg     key     ;

//时钟、复位信号、模拟按键信号
initial
    begin
        clk =   0;
        rst_n   <=  0;
        key <=  0;
        #100
        rst_n   <=  1;
        #1000
        key <=  1;
        #20
        key <=  0;
    end

always  #10 clk <=  ~clk;

defparam memory.mem_access.initfile = "initmemory.txt";

//-------------spi_flash_se-------------
spi_flash_se    spi_flash_se_inst
(
    .sys_clk    (clk    ),  //系统时钟,频率50MHz
    .sys_rst_n  (rst_n  ),  //复位信号,低电平有效
    .pi_key     (key    ),  //按键输入信号

    .sck        (sck    ),  //串行时钟
    .cs_n       (cs_n   ),  //片选信号
    .mosi       (mosi   )   //主输出从输入数据
);

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《详细》使用ventoy制作linux to go和win to go放在u盘中《即走即用的便携式系统》,自带系统引导

通过docker部署一键爬虫&#xff0c;爬取海量电影&#xff1b;部署ai绘画&#xff1b;部署目标检测算法&#xff1b;部署ai自动上字幕&#xff1b;爬取表格总结数据&#xff1b;......只有你想象不到&#xff0c;没有它做不到 Ventoy制作U盘系统优点&#xff1a; 高效&#xf…

录音怎么转换成mp3格式?

录音怎么转换成mp3格式&#xff1f;将录音转换成MP3格式可以节省存储空间。通常&#xff0c;录音保存的文件格式是WAV等无损音频格式&#xff0c;这种音频格式相对于MP3格式占用的存储空间更大。将录音转换成MP3格式后&#xff0c;可以减小文件的大小&#xff0c;方便储存和传输…

面试题更新之-vue2x监听方面有什么缺点?所以才有了vue3.0

文章目录 vue2x监听vue3.0监听vue2x监听方面有什么缺点&#xff1f;所以才有了vue3.0 vue2x监听 在Vue.js 2.x中&#xff0c;你可以通过监听属性来响应数据的变化。以下是几种常见的监听方式&#xff1a; 监听计算属性&#xff1a;你可以使用computed属性来创建一个计算属性&…

Windows下编译安装ARPACK

ARPACK采用Arnoldi算法求解大型稀疏矩阵特征值。本文拟记录在Windows下编译安装ARPACK的流程。 零、环境 操作系统Windows 10集成开发环境Visual Studio 2019 CommunityCMake3.24.2Intel oneAPI BaseKit w_BaseKit_p_2023.1.0.47256_offline Intel oneAPI HPCKitw_HPCKit_p…

亮相亚太 CDN 峰会,火山引擎 CDN 与加速助力数字化业务加速发展

6月28日- 6月29日&#xff0c;2023 全球分布式云大会和第十二届亚太内容分发大会暨 CDN 峰会在北京成功举办。火山引擎凭借在边缘云领域持续的技术积累、丰富的场景应用、创新的产品与解决方案&#xff0c;荣登“分布式云与算力创新企业榜单”&#xff0c;“中国边缘加速创新企…

通过一个C语言程序的生命周期,了解计算机系统

我们通过跟踪这个hello程序来系统性的了解一个程序是如何被系统执行的。 #include <stdio.h>int main(){printf("hello world"); }一、信息的本质 一个C语言程序的生命周期从一个源程序开始&#xff0c;程序员用编辑器创建并保存的文本文件&#xff0c;文件后…

【Pycharm中快速校准代码格式】

Windows下&#xff1a; ctrlaltL Mac下&#xff1a; optioncommand 如何查看Pycharm的快捷键 keymap 键映射&#xff1a;计算机软件中&#xff0c;将键盘按键与特定功能或命令关联的配置。

scrapy ---分布式爬虫

导模块 pip install scrapy-redis 原来scrapy的Scheduler维护的是本机的任务队列&#xff08;待爬取的地址&#xff09;本机的去重队列&#xff08;放在集合中&#xff09;---》在本机内存中 如果把scrapy项目&#xff0c;部署到多台机器上&#xff0c;多台机器爬取的内容是重…

特斯拉上海工厂二季度交付创历史新高,员工奖金大幅增长

根据路透社的报道&#xff0c;特斯拉上海工厂的几位员工透露&#xff0c;他们在最新一季度获得了大幅增加的绩效奖金。 根据三位工厂员工的陈述&#xff0c;他们在二季度收到的奖金是他们月薪的1.5倍&#xff0c;高于之前按绩效评估获得的季度奖金&#xff08;月薪的1.2倍&…

《面试1v1》Kafka基础

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

Nacos 虚拟机设置开机自启

执行命令 : vi /lib/systemd/system/nacos.service 创建并编辑文件将下面的代码放入此文件中,其中注意自己nacos的位置,即ExecStart与ExecReload与ExecStop 后面的nacos相关路径 [Unit] Descriptionnacos Afternetwork.target[Service] Typeforking TimeoutSec0 #防止启动超时…

呼吸灯——FPGA

文章目录 前言一、呼吸灯是什么&#xff1f;1、介绍2、占空比调节示意图 二、系统设计1、系统框图2、RTL视图 三、源码四、效果五、总结六、参考资料 前言 环境&#xff1a; 1、Quartus18.0 2、vscode 3、板子型号&#xff1a;EP4CE6F17C8 要求&#xff1a; 将四个LED灯实现循环…

我伴随HarmonyOS一起成长

大家好&#xff0c;我是waylau&#xff08;老卫&#xff09;&#xff0c;是一名80后程序员&#xff0c;华为开发者联盟社区认证讲师&#xff0c;HarmonyOS技术达人&#xff0c;曾获2021、2022年度牛人之星、2022年度OpenHarmony开源贡献之星。著有《跟老卫学HarmonyOS开发》开源…

jmeter 入门到精通

目录 一、jmeter 安装 二、jmeter 介绍 1、jmeter是什么&#xff1f; 2、jmeter 用来做什么&#xff1f; 3、优点 4、缺点 5、jmeter 目录介绍 ①_bin 目录介绍 ② docs 目录 — — 接口文档目录 ③ extras目录 — — 扩展插件目录 ④ lib 目录 — — 所用到的插件…

网络通信原理系统的认知(NEBASE第十四课)

1 物理层 第一层 物理层&#xff1a;建立、维护、断开物理连接&#xff0c;定义了接口及介质&#xff0c;实现了比特流的传输。 1.1传输层介质分类 有线介质&#xff1a;网线 &#xff08;双绞线&#xff09;光纤 无线: 无线电 1.2 双绞线 五类线 cat5 &#xff1a;适用 10…

[论文分享]ConvMAE:Masked Convolution Meets Masked Autoencoders

论文题目&#xff1a;ConvMAE: Masked Convolution Meets Masked Autoencoders 论文地址&#xff1a;https://arxiv.org/abs/2205.03892 代码地址&#xff1a;https://github.com/Alpha-VL/ConvMAE 摘要 视觉变压器(Vision transformer, ViT)已成为广泛应用于各种视觉任务的架…

如何使用 SVG 作为占位符和其他图像加载技术

从图像生成 SVG 可用于占位符。 一、说明 我们对图像性能优化和使图像在网络上快速加载充满热情。最有趣的探索领域之一是占位符&#xff1a;当图像尚未加载时要显示的内容。 在过去&#xff0c;我遇到了一些使用 SVG 的加载技术&#xff0c;我想在这篇文章中描述它们。 在这…

代码随想录算法训练营第52天 | 动态规划 part13 ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

#300.最长递增子序列 自己想了20min没想出来。但没关系因为没接触过该题型。我想不出来的点就是&#xff0c;如果i-1的最后一个不要的话&#xff0c;我怎么找到上一个结束点。解决方案是&#xff1a;再搞一个循环&#xff0c;一个个找&#xff08;下面的 j &#xff09; 下面…

性能测试 Linux 环境下模拟延时和丢包实现

在性能测试过程中&#xff0c;我们还需要模拟网络异常的情况下&#xff0c;是否会出现一些异常数据。最常见的就是写库操作&#xff0c;比如说我们下单的场景&#xff0c;如果出现网络异常的时候是否会出现数据对不上这种情况。 如我们JMeter发送成功的请求数量和最终数据库表…

龙蜥白皮书精选:面向 HTTP 3.0 时代的高性能网络协议栈

文/高性能网络 SIG 01 背景概述 随着互联网特别是移动互联网的快速发展&#xff0c;对互联网通信协议提出了新的诉求。经过多年的发展&#xff0c;QUIC 协议在 2021 年正式被 IEFT 标准化&#xff0c;成为 HTTP 3 的标准传输层协议。QUIC 是基于 UDP 实现的面向连接可靠有序…