08_SPI-Flash 扇区擦除实验

这篇具有很好参考价值的文章主要介绍了08_SPI-Flash 扇区擦除实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 实验目标

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

2. 操作时序

2.1 扇区擦除操作指令

扇区擦除(Sector Erase)操作,简称 SE,操作指令为 8’b1101_0000(D8h)。
08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发

2.2 完整扇区擦除操作时序

08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发
08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发
08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发

3. 程序框图

3.1 顶层框图

08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发

3.2 扇区擦除模块

08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发
08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发

4. 波形图

08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发
08_SPI-Flash 扇区擦除实验,# Verilog学习强化案例,fpga开发文章来源地址https://www.toymoban.com/news/detail-565921.html

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

到了这里,关于08_SPI-Flash 扇区擦除实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 实验(三):SPI应用:读写串行FLASH 实验

    实验目的: 1. 学习对SPI的使用; 2. 掌握KEIL5的仿真与调试。 任务: 1. 根据要求编写程序,并写出原理性注释; 2. 将检查程序运行的结果,分析一下是否正确; 3. 完成所建工程的验证调试。 以一种使用SPI 通讯的串行FLASH 存储芯片的读写实验为大家讲解STM32 的SPI 使用方法。

    2024年01月21日
    浏览(28)
  • STM32单片机Flash不擦除直写案例分析

    产品跳闸前需保存致使产品动作的故障类型和具体的故障分析数据,并在产品二次上电后读取故障类型,进行相应指示;之后清除故障类型的相关Flash,但故障分析数据仍保存,以便后续读出分析。然而,Flash扇区擦除时间较长,会影响程序正常运行、判断。 Flash的编程原理都

    2024年02月16日
    浏览(37)
  • 【问题】STM32G0芯片擦除flash失败,发现死在FLASH_SR_CFGBSY一直为1(已解决)

    本人开发stm32g030和g070都遇到过擦除flash失败的问题,HAL库中按照例程方式擦除存在擦除失败问题。例程基本流程如下: 按照这种方式其实很容易擦除失败。网上多数是说中断问题等,还有些是看门狗喂狗问题。 以上问题之外,本人遇到的是FLASH_FLAG_CFGBSY一直被置位,导致擦除

    2024年02月10日
    浏览(43)
  • 【FPGA】SPI读写flash

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

    2024年02月05日
    浏览(28)
  • SPI 及 NOR Flash 介绍

    1.SPI的含义 SPI:串行外设设备接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线。SPI接口主要应用在存储芯片、AD转换器以及LCD中。SPI接口主要应用在存储芯片、AD转换器以及LCD中。 SPI 的引脚信息: MISO(Master In / Slave Out)主设备数据输入,从设备数据

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

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

    2024年02月16日
    浏览(28)
  • FPGA使用SPI控制FLASH

    通过控制FLASH芯片进一步熟悉SPI协议 Flash 存储器 : Flash 存储器是一种非易失性存储器,它具有 RAM 和 ROM 的一些特点。与 ROM 类似,Flash 存储器的内容在断电时不会丢失,但与 RAM 类似,它可以通过编程来修改存储的内容。Flash 存储器通常用于嵌入式系统中存储程序代码、配置

    2024年03月19日
    浏览(40)
  • 【FLASH存储器系列五】SPI NOR FLASH芯片使用指导之一

    👉个人主页: highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容   目录 1芯片简介 2引脚定义 3功能框图 4器件操作 4.1操作框图 4.2标准SPI 4.3DaulSPI 4.4QaudSPI 4.5QPI 4.6DTR(W25Q128不支持) 4.73-字节/4-字节地址模式(W25Q128只支持3字节) 4.8保持

    2023年04月19日
    浏览(35)
  • SPI FLASH Fatfs文件系统移植

    FATFS是面向小型嵌入式系统的FAT文件系统。他由C语言编写并且独立与底层I/O介质。支持的内核有:8051,PLC,ARV,ARM等。FATFS支持FAT12,FAT16,FAT32等文件系统格式。 官网链接 diskio.c:包含底层存储介质的操作函数,需要与硬件设备适配移植。主要是在这个文件里调用用户实现的底层驱

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

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

    2024年02月05日
    浏览(36)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包