FPGA project : flash_erasure

news2024/9/25 17:15:04

SPI是什么:

SPISerial Peripheral Interface,串行外围设备接口)通讯协议,是Motorola公司提出的一种同步串行接口技术,是一种高速、全双工、同步通信总线,在芯片中只占用四根管脚用来控制及数据传输

       应用:EEPROMFlashRTCADCDSP等。

       优缺点:全双工通信,通讯方式较为简单,相对数据传输速率较没有应答机制确认数据是否接收,在数据可靠性上有一定缺陷(与I2C相比)。

物理层:

SCK (Serial Clock):时钟信号线,用于同步通讯数据

MOSI (Master Output Slave Input):主设备输出/从设备输入引脚

MISO (Master InputSlave Output):主设备输入/从设备输出引脚

𝐶𝑆(CS) ̅ (Chip Select):片选信号线,也称为CS_N

协议层: 

spi通讯协议有四种模式:模式0和模式3,从设备在sck上升沿采样。

模式1和模式2在时钟下降沿采样。

模式0和模式1,在cs_n==1时,sck==0。

模式2和模式3,在cs_n==1时,sck==1。

比较常用的就是模式0和模式3。

flash相关资料:

芯片手册是必须要看的。

模块框图:

状态机:

时序图:

 代码:

module spi (
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   , 
    input       wire            key_start   ,

    output      wire            mosi        ,
    output      wire            miso        ,
    output      reg             cs_n        ,
    output      reg             sck 
);
    // parameter 
    parameter   COMD_W  = 8'h06   ,
                COMD_B  = 8'hc7   ;
    parameter   IDLE    = 4'b0001 ,
                WREN    = 4'b0010 ,
                WEL     = 4'b0100 ,
                BE      = 4'b1000 ;
    // wire signal degine
    wire                IDLEtoWREN; 
    wire                WRENtoWEL ;  
    wire                WRENtoBE  ;   
    wire                BEtoIDLE  ;   
    // reg signal define
    reg     [3:0]       state_c   ;
    reg     [3:0]       state_n   ;
    reg     [3:0]       cnt_20ns  ;
    reg     [3:0]       cnt_bit   ;
    reg                 flag_bit  ;
    reg                 f_b_reg   ; // flag_bit_reg的缩写
    reg     [7:0]       comd      ;
/****************************************************************************/
    // 三段式状态机
    // 现态与次态描述
    // state_c
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= IDLE ;
        else
            state_c <= state_n ;
    end
    // state_n
    always @(*) begin
        case (state_c)
        IDLE   :if(IDLEtoWREN)
                    state_n <= WREN ;
                else 
                    state_n <= IDLE ;
        WREN   :if(WRENtoWEL)
                    state_n <= WEL  ;
                else 
                    state_n <= WREN ;
        WEL    :if(WRENtoBE)
                    state_n <= BE   ;
                else 
                    state_n <= WEL  ;
        BE     :if(BEtoIDLE)
                    state_n <= IDLE ;
                else 
                    state_n <= BE   ;
        default:    state_n <= IDLE ;
        endcase
    end
    // 状态转移描述
    assign  IDLEtoWREN  = ( state_c == IDLE) && ( key_start     ) ;
    assign  WRENtoWEL   = ( state_c == WREN) && ( f_b_reg       ) ;
    assign  WRENtoBE    = ( state_c == WEL ) && ( cnt_20ns == 6 ) ;
    assign  BEtoIDLE    = ( state_c == BE  ) && ( f_b_reg       ) ;
    // 相关信号描述
    // reg     [3:0]       cnt_20ns  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_20ns <= 4'd0 ;
        else 
        case (state_c)
        IDLE :  cnt_20ns <= 4'd0 ;
        WREN :  if(cnt_20ns || f_b_reg)
                    cnt_20ns <= 4'd0 ;
                else 
                    cnt_20ns <= cnt_20ns + 1'b1 ;
        WEL  :  if(cnt_20ns == 6) // 60x20ns==120ns
                    cnt_20ns <= 4'd0 ;
                else
                    cnt_20ns <= cnt_20ns + 1'b1 ;
        BE   :    if(cnt_20ns || f_b_reg)
                    cnt_20ns <= 4'd0 ;
                else 
                    cnt_20ns <= cnt_20ns + 1'b1 ;
        default:    cnt_20ns <= 4'd0 ;
        endcase
    end
    // reg     [3:0]       cnt_bit   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_bit <= 4'd0 ;
        else 
        case (state_c)
        IDLE :  cnt_bit <= 4'd0 ;
        WREN :  if(!cnt_20ns && sck && cnt_bit == 7)
                    cnt_bit <= 4'd0 ;
                else if(!cnt_20ns && sck)
                    cnt_bit <= cnt_bit + 1'b1 ;
        WEL  :  cnt_bit <= 4'd0 ;
        BE   :  if(!cnt_20ns && sck && cnt_bit == 7)
                    cnt_bit <= 4'd0 ;
                else if(!cnt_20ns && sck)
                    cnt_bit <= cnt_bit + 1'b1 ;
        default:    cnt_bit <= 4'd0 ;
        endcase
    end
    // reg                 flag_bit  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flag_bit <= 1'b0 ;
        else
        case (state_c)
        IDLE :  flag_bit <= 1'b0 ;
        WREN :  if(cnt_bit == 7 && sck && !cnt_20ns)
                    flag_bit <= 1'b1 ;
                else 
                    flag_bit <= flag_bit ;
        WEL  :  flag_bit <= 1'b0 ;
        BE   :  if(cnt_bit == 7 && sck && !cnt_20ns)
                    flag_bit <= 1'b1 ;
                else 
                    flag_bit <= flag_bit ;
        default: flag_bit <= 1'b0 ;
        endcase
    end
    // reg                 f_b_reg   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            f_b_reg <= 1'b0 ;
        end else begin
            f_b_reg <= flag_bit ;
        end
    end
    // reg     [7:0]       comd      ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            comd <= 8'd0 ;
        else
        case (state_c)
        IDLE :  comd <= 8'd0 ;
        WREN :  if(cnt_20ns && sck)
                    comd <= (COMD_W << cnt_bit) ;
                else if(!cnt_bit)
                    comd <= COMD_W ;
                else 
                    comd <= comd ;
        WEL  :  comd <= 8'd0 ;
        BE   :  if(cnt_20ns && sck)
                    comd <= (COMD_B << cnt_bit) ;
                else if(!cnt_bit)
                    comd <= COMD_B ;
                else 
                    comd <= comd ;
        default :   comd <= 8'd0 ;
        endcase 
    end
    // output signal
    // wire            mosi        ,
    assign mosi = comd[7] ;
    // wire            miso        ,
    assign miso = 1'bz ;
    // reg             cs_n        ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cs_n <= 1'b1 ;
        end else begin
            case (state_c)
            IDLE :  if(key_start)
                        cs_n <= 1'b0 ;
                    else 
                        cs_n <= 1'b1 ;
            WREN :  if(f_b_reg)
                        cs_n <= 1'b1 ;
                    else 
                        cs_n <= cs_n ;
            WEL  :  if(cnt_20ns == 6) 
                        cs_n <= 1'b0 ;
                    else 
                        cs_n <= cs_n ;
            BE   :  if(f_b_reg)
                        cs_n <= 1'b1 ;
                    else 
                        cs_n <= cs_n ;
            default:    cs_n <= 1'b1 ;
            endcase
        end
    end
    // reg             sck 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            sck <= 1'b0 ;
        else 
        case (state_c)
        IDLE :  sck <= 1'b0 ;
        WREN :  if(cnt_20ns)
                    sck <= ~sck ;
                else 
                    sck <= sck  ;
        WEL  :  sck <= 1'b0 ;
        BE   :  if(cnt_20ns)
                    sck <= ~sck ;
                else 
                    sck <= sck  ;
        default:    sck <= 1'b0 ;
        endcase
    end

endmodule

 

module key_filter
#(
    parameter MAX_CNT_20MS = 20'd100_0000 
)(
    input           wire    sys_clk     ,
    input           wire    sys_rst_n   ,
    input           wire    key_in      ,

    output          wire    key_out     
);

    reg     key_r_0 ;
    reg     key_r_1 ;
    wire    nege    ;
    wire    pose    ;

    reg     [19:00]     cnt_20ms     ;
    wire                add_cnt_20ms ;
    wire                end_cnt_20ms ;
    reg                 add_cnt_flag ;

    // key_r_0 key_r_1 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            key_r_0 <= 1'b1 ;
        end else begin
            key_r_0 <= key_in ;
        end
    end
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            key_r_1 <= 1'b1 ;
        end else begin
            key_r_1 <= key_r_0 ;
        end
    end

    // nege pose
    assign nege = ~key_r_0 &&  key_r_1 ;
    assign pose =  key_r_0 && ~key_r_1 ;

    // add_cnt_flag
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            add_cnt_flag <= 1'b0 ;
        end else begin
            if(nege) begin
                add_cnt_flag <= 1'b1 ;
            end else begin
                if( pose || end_cnt_20ms ) begin
                    add_cnt_flag <= 1'b0 ;
                end else begin
                    add_cnt_flag <= add_cnt_flag ;
                end
            end 
        end
    end

    // cnt_20ms add_cnt_20ms end_cnt_20ms
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_20ms <= 20'd0 ;
        end else begin
            if(add_cnt_20ms) begin
                if(end_cnt_20ms) begin
                    cnt_20ms <= 20'd0 ;
                end else begin
                    cnt_20ms <= cnt_20ms + 20'd1 ;
                end
            end else begin
                cnt_20ms <= 20'd0 ;
            end
        end
    end
    assign add_cnt_20ms = add_cnt_flag ;
    assign end_cnt_20ms = add_cnt_20ms && cnt_20ms == ( MAX_CNT_20MS - 1'b1 ) ;

    // key_out
    // always @(posedge sys_clk or negedge sys_rst_n) begin
    // // always @(*) begin // 这样的话 会综合成 数据选择器
    //     if(~sys_rst_n) begin
    //         key_out <= 1'b0 ;
    //     end else begin
    //         if(end_cnt_20ms) begin
    //             key_out <= 1'b1 ;
    //         end else begin
    //             key_out <= 1'b0 ;
    //         end
    //     end
    // end
    assign key_out = end_cnt_20ms ;
endmodule
module top(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            key_in      ,

    output      wire            cs_n        ,
    output      wire            sck         ,
    output      wire            mosi        
);
    // 例化间连线
    wire            key_flag ;

key_filter key_filter_inst(
    .sys_clk                    ( sys_clk   ) ,
    .sys_rst_n                  ( sys_rst_n ) ,
    .key_in                     ( key_in    ) ,

    .key_out                    ( key_flag  )     
);

spi spi_inst(
    .sys_clk                    ( sys_clk   ) ,
    .sys_rst_n                  ( sys_rst_n ) ,
    .key_start                  ( key_flag  ) ,

    .mosi                       ( mosi      ) ,
    .miso                       (           ) ,
    .cs_n                       ( cs_n      ) ,
    .sck                        ( sck       )
);endmodule
`timescale 1ns/1ns
module test_top();
    reg             sys_clk     ;
    reg             sys_rst_n   ;
    reg             key_in      ;

    wire            cs_n        ;
    wire            sck         ;
    wire            mosi        ;
    wire            miso        ;

top top_inst(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .key_in                 ( key_in    ) ,

    .cs_n                   ( cs_n      ) ,
    .sck                    ( sck       ) ,
    .mosi                   ( mosi      ) ,
    .miso                   ( miso      )
);

    parameter CYCLE = 20 ;
    defparam  top_inst.key_filter_inst.MAX_CNT_20MS = 20'd100 ;

    initial begin
        sys_clk = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        key_in    <= 1'b1 ;
        #(CYCLE) ;
        sys_rst_n <= 1'b1 ;
        #(CYCLE * 30) ;
        key_in <= 1'b0 ;
        #(CYCLE * 130) ;
        key_in <= 1'b1 ;
        #(CYCLE * 100) ;
        $stop;
    end
    always #(CYCLE/2) sys_clk = ~sys_clk ;

endmodule

 仿真波形:

 上板验证:

先往板子上固化一个流水灯程序,也就是把生成的.jic文件,写进flash。

重启开发板,流水灯正常工作,说明程序写进了flash。

然后把全擦除程序(.sof),写进开发板。

重启开发板,流水灯效果消失。

说明上板成功。

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

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

相关文章

k8s使用

一、Kubernetes好处 ​ kubernetes&#xff0c;是一个全新的基于容器技术的分布式架构领先方案&#xff0c;是谷歌严格保密十几年的秘密武器----Borg系统的一个开源版本&#xff0c;于2014年9月发布第一个版本&#xff0c;2015年7月发布第一个正式版本。 ​ kubernetes的本质…

docker 安装oracle

拉取镜像 拉取oracle_11g镜像 拉取oracle镜像(oracle 11.0.2 64bit 企业版 实例名: helowin) Oracle主要在Docker基础上安装&#xff0c;安装环境注意空间和内存&#xff0c;Oracle是一个非常庞大的一个软件&#xff0c; 建议使用网易镜像或阿里镜像网站这里以oracle 11.0.2…

XPath在数据采集中的应用:从XML和HTML中提取数据

目录 一、XPath简介 二、XPath的语法 三、XPath在数据采集中的应用 四、XPath和其他数据格式 总结 在当今的数据驱动时代&#xff0c;从各种数据源中提取有用的信息变得至关重要。其中&#xff0c;XML和HTML作为主流的数据源格式&#xff0c;常常出现在我们的数据提取任务…

PHP Discord获取频道消息功能实现

PHP Discord获取频道消息功能实现 1. 关注对应频道2. 添加机器人3. 配置机器人权限4. 使用 DiscordPHP 类库5. 代码示例 (Laravel 框架)6. 服务器部署 1. 关注对应频道 首先要创建自己的频道, 然后到对应的公告频道中关注这个频道(这时 Discord 会让你选择频道, 选择之前创建的…

集成内部高端电源开关LTC3637HMSE、LTC3637MPMSE稳压器,TJA1443AT汽车CAN FD收发器。

一、LTC3637 76V、1A 降压型稳压器 &#xff08;简介&#xff09;LTC3637是一款高效率降压DC/DC稳压器&#xff0c;集成内部高端电源开关&#xff0c;功耗仅12μA DC&#xff0c;空载时可保持稳定的输出电压。LTC3637可提供高达1A的负载电流&#xff0c;并具有可编程峰值电流限…

虹科分享 | 想买车无忧?AR为您带来全新体验!

新能源汽车的蓬勃发展&#xff0c;推动着汽车行业加速进行数字化变革。据数据显示&#xff0c;全球新能源汽车销售额持续上升&#xff0c;预计到2025年&#xff0c;新能源汽车市场规模将达到约 4200亿美元&#xff0c;年复合增长率超过 30%。这表明消费者对清洁能源出行的需求不…

3.Javaweb模块进阶

1.2web进阶 什么是 CSRF 攻击&#xff0c;如何避免&#xff1f; CSRF&#xff1a;Cross-Site Request Forgery&#xff08;中文&#xff1a;跨站请求伪造&#xff09;&#xff0c;可以理解为攻击者盗用了你的身份&#xff0c;以你的名义发送恶意请求&#xff0c;比如&#x…

SIP对讲求助终端sip解码广播终端

SIP对讲求助终端sip解码广播终端 SV-2701VP具有10/100M以太网接口&#xff0c;支持最高48KHz采样&#xff0c;192Kbps的音频流播放。接入12V/1A的直流电源。具有1路mic输入&#xff0c;1路线路输入&#xff0c;1路立体音线路输入&#xff0c;这3组信号经过信号混合后输出到本地…

计算机毕业设计选什么题目好?springboot 社区流浪动物救助领养系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Websocket获取B站直播间弹幕教程——第二篇、解包/拆包

教程一、Websocket获取B站直播间弹幕教程 — 哔哩哔哩直播开放平台 1、封包 我们连接上B站Websocket成功后&#xff0c;要做两件事情&#xff1a; 第一、发送鉴权包。第二、发送心跳包&#xff0c;每30秒一次&#xff0c;维持websocket连接。 这两个包不是直接发送过去&…

PowerShell pnpm : 无法加载文件 C:\Users\lenovo\AppData\Roaming\npm\pnpm.ps1

1、右键点击【开始】&#xff0c;打开Windows PowerShell&#xff08;管理员&#xff09; 2、运行命令set-ExecutionPolicy RemoteSigned 3、根据提示&#xff0c;输入A,回车 此时管理员权限已经可以运行pnpm 如果vsCode还报该错误 继续输入 4、右键点击【开始】&#xff0c;打…

如何将gif变成视频?3个转换方法

如何将gif变成视频&#xff1f;没错&#xff0c;GIF是一种动态图片格式&#xff0c;与视频在本质上有所区别。在一些自媒体平台上&#xff0c;我们无法直接分享GIF格式的图片&#xff0c;但可以将其转换为视频格式后再进行分享。因此&#xff0c;当我们想要分享我们喜欢的GIF图…

C# 文件监听FileSystemWatcher

用处 当文件修改后&#xff0c;触发其他操作&#xff0c;例如删除另一个文件夹下的文件等 代码 using System; using System.Collections.Generic; using System.Diagnostics; using System.IO;namespace ConsoleApp6FileSystemWatcher {internal class Program{static void …

【TES720D-KIT】基于复旦微FMQL20S400全国产化ARM开发套件(核心板+底板)

TES720D-KIT是专门针对我司TES720D&#xff08;基于复旦微FMQL20S400的全国产化ARM核心板&#xff09;的一套开发套件&#xff0c;它包含1个TES720D核心板&#xff0c;加上一个TES720D-EXT扩展底板。 FMQL20S400是复旦微电子研制的全可编程融合芯片&#xff0c;在单芯片内集成…

微信小程序在TS模板下引入TDesign组件

介绍 TDesign 是腾讯官方出品的一款微信小程序组件库。本文介绍如何在新建ts空白模板下引入TDesign库 步骤 新建一个空白项目&#xff0c;这里可以选择TS-基础模板 新建项目目录结构如图所示&#xff1a; 注意这里其实小程序的文件都存放在miniprogram文件夹下&#xff0c;…

本文整理了Debian 11在国内的几个软件源。

1&#xff0e;使用说明 一般情况下&#xff0c;将/etc/apt/sources.list文件中Debian默认的软件仓库地址和安全更新仓库地址修改为国内的镜像地址即可&#xff0c;比如将deb.debian.org和security.debian.org改为mirrors.xxx.com&#xff0c;并使用https访问&#xff0c;可使用…

关于神经网络的思考

关于感知机 感知机&#xff08;Perceptron&#xff09;和神经网络&#xff08;Neural Network&#xff09;之间有一定的关系&#xff0c;可以说感知机是神经网络的一个基本组成单元。 感知机&#xff1a; 感知机是一种简单的二分类线性分类器。它接受多个输入&#xff0c;对每…

sanic框架解决多进程共享缓存问题

最近在用sanic框架做项目&#xff0c;今天需要处理多进程共享缓存问题&#xff0c;在网上搜索了很多&#xff0c;知道使用multiprocessing模块&#xff0c;但是导入后&#xff0c;直接使用会报错&#xff0c;然后看官网解决问题。 直接看官方文档点我哦 大致意思如下&#xf…

flutter 常用组件:文本、图片和按钮

文章目录 文本控件富文本控件图片本地图片网络图片按钮文本控件 ##一’码’当先 Text(这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本,textAlign:TextAlign.center,style: TextStyle(fontWeight: FontWeight.bold, font…

简单好用的CHM文件阅读器 CHM Viewer Star最新 for mac

CHM Viewer Star 是一款适用于 Mac 平台的 CHM 文件阅读器软件&#xff0c;支持本地和远程 CHM 文件的打开和查看。它提供了直观易用的界面设计&#xff0c;支持多种浏览模式&#xff0c;如书籍模式、缩略图模式和文本模式等&#xff0c;并提供了丰富的功能和工具&#xff0c;如…