FPGA project : flash_continue_write

news2024/11/20 11:35:56

本实验学习了通过spi通信协议,驱动flash;完成连续写操作。

连续写:

本质上还是页编程指令,两种连续写的方式:

1,每次只写1byte的数据。

2,每次写满1页数据,计算剩余数据够不够写满1页,并计算地址。

本实验采取方案一。

模块框图:

状态机: 

 时序图:

代码:

只放spi模块。 

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

    input       wire            miso        ,

    output      reg             cs_n        ,
    output      reg             sck         ,
    output      reg             mosi        ,
    output      reg             po_flag     ,
    output      wire    [7:0]   po_data     
);
    // localparam define 一般状态机的状态定义用局部参数就可以。
    localparam  IDLE     = 4'b0001 ,
                INSTRUCT = 4'b0010 ,
                READ     = 4'b0100 ,
                SEND     = 4'b1000 ;
    // parameter define  指令,计数器最大值,用全局参数定义。
    parameter   COMD_REA = 8'h03 , // comd_read
                ADDR_SEC = 8'h00 , // address_secter 扇区地址
                ADDR_PAG = 8'h00 , // address_page   页地址(行地址)
                ADDR_BYT = 8'hc8 , // assress_byte   字节地址
                NUM_COMD = 4'd4  ; // 用来记录在指令状态传递指令和地址byte数量
    parameter   CNT_MAX_BYTE = 11'd260   , // 4 + 要读出的数据。例如: 4 + 256
                CNT_MAX_SEND = 20'd53000 ;
    // reg signal define 
    reg     [3:0]       state_c   ;
    reg     [3:0]       state_n   ;
    reg                 cnt_20_ns ;
    reg     [2:0]       cnt_bit   ;
    reg     [10:0]      cnt_byte  ;
    reg                 flag_b    ; // flag_byte
    reg                 flagBreg  ;
    reg                 flag_R_S  ; // flag_byte
    reg                 flag_RSr  ;
    reg     [7:0]       datInFifo ; // data_in_fifo
    reg                 flag_data ; // flag_data 采样标志信号
    reg                 flaInFifo ; // flag_in_fifo
    reg     [19:0]      cnt_send  ; // uart_tx模块发送1byte数据的等待时间。
    reg                 flaSenEnd ; // 计数器cnt_send计数到CNT_MAX_SEND - 2 拉高一个时钟周期,
    reg                 flag_out_fifo_reg ;
    // wire signal define
    wire                empty     ;
    wire                full      ;
    wire                flaOutFif ; // flag_out_fifo  
    wire    [9:0]       usedw     ; // fifo中存储的数据量   
    wire                IDLEtoINSTRUCT  ;
    wire                INSTRUCTto_READ ;
    wire                READtoSEND      ;
    wire                SENDtoIDLE      ; 
/**********************************************************************/
    // // reg signal describe 
    /*******状态机采用三段式描述*******/
    // reg     [3:0]       state_c   ;
    // reg     [3:0]       state_n   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= IDLE ;
        else 
            state_c <= state_n ;
    end
    always @(*) begin
        case (state_c)
        IDLE     :  if(IDLEtoINSTRUCT)
                        state_n <= INSTRUCT ;
                    else 
                        state_n <= IDLE ;
        INSTRUCT :  if(INSTRUCTto_READ)
                        state_n <= READ ;
                    else 
                        state_n <= INSTRUCT ;
        READ     :  if(READtoSEND)
                        state_n <= SEND ;
                    else 
                        state_n <= READ ;
        SEND     :  if(SENDtoIDLE)
                        state_n <= IDLE ;
                    else 
                        state_n <= SEND ;
        default:        state_n <= IDLE ;
        endcase
    end
    assign   IDLEtoINSTRUCT  = (state_c == IDLE    ) && (key_flag) ;
    assign   INSTRUCTto_READ = (state_c == INSTRUCT) && (flagBreg) ; // 指令的的最后1byte发送完毕
    assign   READtoSEND      = (state_c == READ    ) && (flag_RSr) ; // 读完想要的最后1byte
    assign   SENDtoIDLE      = (state_c == SEND    ) && (flaSenEnd && empty) ;
    // reg                 cnt_20_ns ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_20_ns <= 1'b0 ;
        else if(state_c == INSTRUCT || state_c == READ)
            cnt_20_ns <= cnt_20_ns + 1'b1 ;
        else if(state_c != INSTRUCT || state_c != READ)
            cnt_20_ns <= 1'b0 ;
        else 
            cnt_20_ns <= 1'b0 ;
    end
    // reg     [2:0]       cnt_bit   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_bit <=3'd0 ;
        else
        case (state_c)
        IDLE    :   cnt_bit <=3'd0 ;
        INSTRUCT:   if(!cnt_20_ns && sck && cnt_bit == 7)  
                        cnt_bit <= 3'd0 ;
                    else if(!cnt_20_ns && sck)
                        cnt_bit <= cnt_bit + 1'b1 ;
        READ    :   if(!cnt_20_ns && sck && cnt_bit == 7)  
                        cnt_bit <= 3'd0 ;
                    else if(!cnt_20_ns && sck)
                        cnt_bit <= cnt_bit + 1'b1 ;
        SEND    :   cnt_bit <=3'd0 ;
        default :   cnt_bit <=3'd0 ; 
        endcase
    end
    // reg     [10:0]       cnt_byte  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cnt_byte <= 4'd0 ;
        else if(cnt_bit == 7 && cnt_byte == CNT_MAX_BYTE - 1 && !cnt_20_ns && sck)
            cnt_byte <= 4'd0 ;
        else if(cnt_bit == 7 && !cnt_20_ns && sck)
            cnt_byte <= cnt_byte + 1'b1 ;
        else 
            cnt_byte <= cnt_byte ;
    end
    // reg                 flag_R_S  ;
    // reg                 flag_b    ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            flag_b   <= 1'b0 ;
            flag_R_S <= 1'b0 ;
        end
        else
        case (state_c)
        IDLE    :   begin
                        flag_b <= 1'b0 ;
                        flag_R_S <= 1'b0 ;
                    end         
        INSTRUCT:   begin 
                        if((cnt_byte == NUM_COMD - 1) && (cnt_bit == 7) && !cnt_20_ns && sck)
                            flag_b <= 1'b1 ;
                        else 
                            flag_b <= flag_b ;

                        flag_R_S <= 1'b0 ;
                    end
        READ    :   begin
                        if(cnt_byte == NUM_COMD)
                            flag_R_S <= 1'b0 ;
                        else if((cnt_byte == CNT_MAX_BYTE - 1) && (cnt_bit == 7) && !cnt_20_ns && sck)
                            flag_R_S <= 1'b1 ;
                            
                        flag_b <= 1'b0 ;
                    end
        SEND    :   begin
                        flag_b <= 1'b0 ;
                        flag_R_S <= 1'b0 ;
                    end 
        default :   begin
                        flag_b <= 1'b0 ;
                        flag_R_S <= 1'b0 ;
                    end 
        endcase 
    end
    // reg                 flagBreg  ;
    // reg                 flag_RSr  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flagBreg <= 1'b0 ;
        else 
            flagBreg <= flag_b ;
    end
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flag_RSr <= 1'b0 ;
        else 
            flag_RSr <= flag_R_S ;
    end
    // reg     [7:0]       datInFifo ; // data_in_fifo
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            datInFifo <= 1'b0 ;
        else if(flag_data)
            datInFifo <= {datInFifo[6:0],miso}; // 读flash中数据,先传的低位{miso,datInFifo[7:1]}。
        else 
            datInFifo <= datInFifo ;
    end
    // reg                 flag_data ; // flag_data 采样标志信号
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flag_data <= 1'b0 ;
        else if(state_c == READ) begin
            if(cnt_20_ns && !sck)
                flag_data <= 1'b1 ;
            else 
                flag_data <= 1'b0 ;
        end else begin
            flag_data <= 1'b0 ;
        end
    end
    // reg                 flaInFifo ; // flag_in_fifo
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flaInFifo <= 1'b0 ;
        else if(state_c == READ && cnt_bit == 7 && flag_data)
            flaInFifo <= 1'b1 ;
        else 
            flaInFifo <= 1'b0 ;
    end
    // reg     [19:0]      cnt_send  ; // uart_tx模块发送1byte数据的等待时间。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_send <= 20'd0 ;
        else 
        if(state_c == SEND) begin
            if(cnt_send == CNT_MAX_SEND - 1) 
                cnt_send <= 20'd0 ;
            else 
                cnt_send <= cnt_send + 1'b1 ;
        end
        else 
            cnt_send <= 20'd0 ;
    end
    //     reg                 flag_out_fifo_reg ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            flag_out_fifo_reg <= 1'b0 ;
        else if(flaSenEnd && !empty)
            flag_out_fifo_reg <= 1'b1 ;
        else 
            flag_out_fifo_reg <= 1'b0 ;
    end
    //     reg                 flaSenEnd ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            flaSenEnd <= 1'b0 ;
        else if(cnt_send == CNT_MAX_SEND - 2)
            flaSenEnd <= 1'b1 ;
        else 
            flaSenEnd <= 1'b0 ;
    end
    // output signal describe
    // cs_n        ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            cs_n <= 1'b1 ;
        else 
        case (state_c)
        IDLE    :   if(key_flag)
                        cs_n <= 1'b0 ;
                    else 
                        cs_n <= cs_n ;
        INSTRUCT:   cs_n <= cs_n ;
        READ    :   cs_n <= cs_n ;
        SEND    :   cs_n <= 1'b1 ;
        default :   cs_n <= 1'b1 ;
        endcase
    end
    // 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 ; 
        INSTRUCT:   if(cnt_20_ns)
                        sck <= ~sck ;
                    else 
                        sck <= sck  ;
        READ    :   if(cnt_20_ns)
                        sck <= ~sck ;
                    else 
                        sck <=  sck ;
        SEND    :   sck <= 1'b0 ; 
        default :   sck <= 1'b0 ; 
        endcase
    end
    // mosi        ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            mosi <= 1'b0 ;
        end else begin
            case (state_c)
            IDLE    :   mosi <= 1'b0 ;
            INSTRUCT:   case (cnt_byte)
            0   :   if(cnt_bit == 0)
                        mosi <= COMD_REA[7] ;
                    else if(cnt_20_ns && sck)
                        mosi <= COMD_REA[7 - cnt_bit] ;
                    else 
                        mosi <= mosi ;
            1   :   if(cnt_bit == 0)
                        mosi <= ADDR_SEC[7] ;
                    else if(cnt_20_ns && sck)
                        mosi <= ADDR_SEC[7 - cnt_bit] ;
                    else 
                        mosi <= mosi ;
            2   :   if(cnt_bit == 0)
                        mosi <= ADDR_PAG[7] ;
                    else if(cnt_20_ns && sck)
                        mosi <= ADDR_PAG[7 - cnt_bit] ;
                    else 
                        mosi <= mosi ;
            3   :   if(cnt_bit == 0)
                        mosi <= ADDR_BYT[7] ;
                    else if(cnt_20_ns && sck)
                        mosi <= ADDR_BYT[7 - cnt_bit] ;
                    else 
                        mosi <= mosi ;
            default :   mosi <= 1'b0 ;
            endcase
            READ    :   mosi <= 1'b0 ;
            SEND    :   mosi <= 1'b0 ;
            default :   mosi <= 1'b0 ;
            endcase
        end
    end
    // po_flag     ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n)
            po_flag <= 1'b0 ;
        else 
            po_flag <= flag_out_fifo_reg ;
    end
    // wire     [7:0]    po_data ;// 直接连接到fifo的输出端口。     
    // */
/***********************例化FIFO***************************************/
    assign flaOutFif = flag_out_fifo_reg ;
fifo_1024x8 fifo_1024x8_inst(
	.clock              ( sys_clk   ) ,
	.data               ( datInFifo ) ,
	.rdreq              ( flaOutFif ) ,
	.wrreq              ( flaInFifo ) ,
	.empty              ( empty     ) ,
	.full               ( full      ) ,
	.q                  ( po_data   ) ,
	.usedw              ( usedw     )
);

endmodule

仿真波形: 

上版验证成功。

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

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

相关文章

Java实现微信支付、退款(小程序支付JSAPI-V3-整合微信sdk开发)

一、废话不多说&#xff0c;直接上教程&#xff1a; 写代码之前首先要明白微信支付的支付流程。 二、支付流程&#xff1a; 小程序调用后端预支付接口 > 预支付接口调用成功返回给小程序支付凭证id > 小程序拿到支付凭证调用微信后台支付接口 > 小程序支付成功后&am…

JOSEF约瑟 多档切换式漏电(剩余)继电器JHOK-ZBL1 30/100/300/500mA

系列型号&#xff1a; JHOK-ZBL多档切换式漏电&#xff08;剩余&#xff09;继电器&#xff08;导轨&#xff09; JHOK-ZBL1多档切换式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBL2多档切换式漏电&#xff08;剩余&#xff09;继电器 JHOK-ZBM多档切换式漏电&#xf…

自己写spring boot starter问题总结

1. Unable to find main class 创建spring boot项目写自己的starterxi写完之后使用install出现Unable to find main class&#xff0c;这是因为spring boot打包需要一个启动类&#xff0c;按照以下写法就没事 <plugins><plugin><groupId>org.springframewo…

嵌入式系统学习路径:

嵌入式系统学习路径&#xff1a; 00001. 确保扎实的C语言基础&#xff0c;包括高级编程知识和数据结构算法。 00002. 00003. 学习Linux应用层开发&#xff0c;包括并发程序设计、网络编程和数据库开发。 00004. 00005. 探索无线通信领域&#xff0c;如Zigbee、低功…

OpenHarmony创新赛|赋能直播第四期

开放原子开源大赛OpenHarmony创新赛进入了中期评审环节&#xff0c;为了解决开发者痛点&#xff0c;本期以三方库移植、MQTT移植案例、开发工具介绍的3节系列技术课程&#xff0c;帮助开发者提升开发效率&#xff0c;为作品的创新能力奠定坚实基础。 扫描下方长图二维码&#x…

手把手教学mfc140u.dll丢失的解决方法,快速解决mfc140u.dll丢失

不知道大家有没有有没有遇到过mfc140u.dll丢失的情况。今天手把手教学mfc140u.dll丢失的解决方法&#xff0c;快速解决mfc140u.dll丢失&#xff0c;这么详细的步骤&#xff0c;我不信这你还不能解决mfc140u.dll丢失的问题。 一.解决mfc140u.dll丢失的方法 解决办法一&#xff…

centos7.3无法使用ping命令提示connect: Resource temporarily unavailable

centos7.3无法使用ping命令 问题描述linux版本解决方法 问题描述 有一台linux服务器&#xff0c;因网络策略开通所需&#xff0c;要登录服务器进行ping测试。结果登录后使用ping命令提示&#xff1a;connect: Resource temporarily unavailable linux版本 查看版本文件得知…

半导体产业链解析:晶圆厂、无晶圆厂与代工厂的比较与作用

半导体产业一直是全球科技发展的关键驱动力&#xff0c;在半导体产业中&#xff0c;晶圆厂、无晶圆厂公司和代工厂是三个重要的参与者。它们在产业环节、生产方式、经营模式和市场竞争等方面存在一些显著差异。本文将探讨半导体晶圆厂、无晶圆厂公司和代工厂之间的区别&#xf…

从零到一完成Midway.js登录、注册、鉴权功能

您好&#xff0c;如果喜欢我的文章&#xff0c;可以关注我的公众号「量子前端」&#xff0c;将不定期关注推送前端好文~ 前言 本文将从项目搭建到实现从零到一开发一个登录、注册、鉴权的简易版注册登录系统&#xff0c;主要功能和技术选型如下&#xff1a; 服务端框架———…

mac 版本 Lightroom Classic 2024 正式版来了 七个有趣的新功能值得更新

mac 版本 Lightroom Classic 2024 正式版终于来了&#xff01;此次更新有七大功能&#xff1a;新增高动态范围编辑和输出、智能 AI 交互式镜头模糊、全局和局部焦点颜色、预设搜索、支持新型相机和镜头等功能。本文将做详细解读&#xff0c;看看这七个有趣的新功能值得去更新吗…

RK3568驱动指南|第六篇-平台总线-第54章 点亮LED灯实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

流量渠道分析

文章目录 流量渠道分析一、为什么需要流量渠道分析1.了解流量来源&#xff0c;制定营销策略2.发现流量缺失点&#xff0c;提高转化率3.提高用户体验&#xff0c;增加用户留存 二、流量渠道分析方法1.确定分析目标2.选择分析工具3.设置分析参数4.收集数据5.数据分析6.制定优化方…

2024上海国际智慧城市展览会(世亚智博会)智慧城市,数字中国

在数字化、智能化的时代背景下&#xff0c;智慧城市成为了全球瞩目的焦点。而作为智慧城市领域的重要盛会&#xff0c;2024上海国际智慧城市展览会&#xff08;简称&#xff1a;世亚智博会&#xff09;则将再次汇聚全球目光。此次展览将于2024年3月26日至28日在上海跨国采购会展…

解决java.lang.IllegalArgumentException: servlet映射中的<url pattern>[demo1]无效

当我使用tomcat启动使用servlet项目时&#xff0c;出现了报错&#xff1a; java.lang.IllegalArgumentException: servlet映射中的<url pattern>[demo1]无效 显示路径错误&#xff0c;于是去检查Web.xml中的配置&#xff0c;发现是配置文件的路径写错了&#xff0c;少写了…

【Python第三方包】快速获取硬件信息和使用情况(psutil、platform)

文章目录 前言一、psutil包1.1 安装psutil包1.2 psutil 使用方式获取CPU使用率获取内存使用情况将内存的获取的使用情况变成GB和MB获取磁盘使用情况磁盘内存进行转换获取网络信息网络info 二、platform2.1 platform的介绍2.2 platform 使用方式获取操作系统的名称获取架构的名称…

unapp项目发布h5 详细操作流程以及注意事项 (hash模式)

首先需要在manifest.json文件中的web配置中 这里因为公司项目都是hash模式 所以写的./ 接下来看源码视图会发现多了一个配置项&#xff1a; 接下来点击hbx上面的 发行》网站-PC Web或手机H5(仅适用于uni-app)(H) 此时查看控制台会显示打包后的存放路径 接下来就直接给后端同…

Windows下Redis3.0主从模式架构搭建

redis版本&#xff1a;Redis-x64-3.0.504 复制相同文件 修改文件夹下redis.windows.conf 文件配置(注意&#xff1a;主有密码&#xff0c;从必须有密码且跟主相同) 修改端口&#xff1a; 主库&#xff1a;端口号6379 从库1&#xff1a;修改端口号为6380 从库2&#xff1a;修…

金融用户实践|分布式存储支持数据仓库业务系统性能验证

作者&#xff1a;深耕行业的 SmartX 金融团队 闫海涛 估值是指对资产或负债的价值进行评估的过程&#xff0c;这对于投资决策具有重要意义。每个金融公司资管业务人员都期望能够实现实时的业务估值&#xff0c;快速获取最新的数据和指标&#xff0c;从而做出更明智的投资决策。…

【学习笔记】RabbitMQ01:基础概念认识以及快速部署

参考资料 RabbitMQ官方网站RabbitMQ官方文档噼咔噼咔-动力节点教程 文章目录 一、认识RabbitMQ1.1 消息中间件&#xff08;MQ Message Queue 消息队列1.2 主流的消息中间件1.3 MQ的应用场景1.3.1 异步处理1.3.2 系统解耦1.3.3 流量削峰1.3.4 日志处理 二、RabbitMQ运行环境搭建…

Windows10不常用操作(录屏、开启超级管理员、关闭自动IP配置、Edge崩溃等)

Win10家庭版开启超级管理员 Win10家庭版开启或禁用超级管理员账户步骤如下&#xff1a; 在搜索框中输入CMD&#xff0c;右键以管理员方式运行。 开启 net user administrator /active:yes禁用 net user administrator /active:no Win10关闭自动IP配置 win10设置完静态ip&am…