FPGA project : flash_continue_write
本实验学习了通过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_readADDR_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 + 256CNT_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_bytereg flagBreg ;reg flag_R_S ; // flag_bytereg flag_RSr ;reg [7:0] datInFifo ; // data_in_fiforeg flag_data ; // flag_data 采样标志信号reg flaInFifo ; // flag_in_fiforeg [19:0] cnt_send ; // uart_tx模块发送1byte数据的等待时间。reg flaSenEnd ; // 计数器cnt_send计数到CNT_MAX_SEND - 2 拉高一个时钟周期,reg flag_out_fifo_reg ;// wire signal definewire 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) beginif(~sys_rst_n) state_c <= IDLE ;else state_c <= state_n ;endalways @(*) begincase (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 ;endcaseendassign IDLEtoINSTRUCT = (state_c == IDLE ) && (key_flag) ;assign INSTRUCTto_READ = (state_c == INSTRUCT) && (flagBreg) ; // 指令的的最后1byte发送完毕assign READtoSEND = (state_c == READ ) && (flag_RSr) ; // 读完想要的最后1byteassign SENDtoIDLE = (state_c == SEND ) && (flaSenEnd && empty) ;// reg cnt_20_ns ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~sys_rst_n)cnt_bit <=3'd0 ;elsecase (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 ; endcaseend// reg [10:0] cnt_byte ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~sys_rst_n) beginflag_b <= 1'b0 ;flag_R_S <= 1'b0 ;endelsecase (state_c)IDLE : beginflag_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 ;endREAD : beginif(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 ;endSEND : beginflag_b <= 1'b0 ;flag_R_S <= 1'b0 ;end default : beginflag_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) beginif(~sys_rst_n)flagBreg <= 1'b0 ;else flagBreg <= flag_b ;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n)flag_RSr <= 1'b0 ;else flag_RSr <= flag_R_S ;end// reg [7:0] datInFifo ; // data_in_fifoalways @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~sys_rst_n)flag_data <= 1'b0 ;else if(state_c == READ) beginif(cnt_20_ns && !sck)flag_data <= 1'b1 ;else flag_data <= 1'b0 ;end else beginflag_data <= 1'b0 ;endend// reg flaInFifo ; // flag_in_fifoalways @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~sys_rst_n) cnt_send <= 20'd0 ;else if(state_c == SEND) beginif(cnt_send == CNT_MAX_SEND - 1) cnt_send <= 20'd0 ;else cnt_send <= cnt_send + 1'b1 ;endelse cnt_send <= 20'd0 ;end// reg flag_out_fifo_reg ;always @(posedge sys_clk or negedge sys_rst_n) beginif(~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) beginif(~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) beginif(~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 ;endcaseend// sck ,always @(posedge sys_clk or negedge sys_rst_n) beginif(~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 ; endcaseend// mosi ,always @(posedge sys_clk or negedge sys_rst_n) beginif(~sys_rst_n) beginmosi <= 1'b0 ;end else begincase (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 ;endcaseREAD : mosi <= 1'b0 ;SEND : mosi <= 1'b0 ;default : mosi <= 1'b0 ;endcaseendend// po_flag ,always @(posedge sys_clk or negedge sys_rst_n) beginif(~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
仿真波形:

上版验证成功。
相关文章:
FPGA project : flash_continue_write
本实验学习了通过spi通信协议,驱动flash;完成连续写操作。 连续写: 本质上还是页编程指令,两种连续写的方式: 1,每次只写1byte的数据。 2,每次写满1页数据,计算剩余数据够不够写…...
论文阅读:Rethinking Range View Representation for LiDAR Segmentation
来源ICCV2023 0、摘要 LiDAR分割对于自动驾驶感知至关重要。最近的趋势有利于基于点或体素的方法,因为它们通常产生比传统的距离视图表示更好的性能。在这项工作中,我们揭示了建立强大的距离视图模型的几个关键因素。我们观察到,“多对一”…...
本地配置免费的https咋做?
大家好这里是tony4geek。 今天和公司的小伙伴对接项目,因为涉及到https的权限调用。所以在服务器本地localhost 要配置https用来测试 。现在把过程中遇到的问题记录下来。 • 因为是测试用所以生成https的证书用免费的就可以了。 openssl req -x509 -nodes -days …...
微信小程序框架---详细教程
🎬 艳艳耶✌️:个人主页 🔥 个人专栏 :《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 ,越幸运。 目录 1.框架 1.1响应的数据绑定 1.2.页面管理 1.3.基础组件 1.4.丰富的 API 2.视图层 View 2.1.介绍 …...
【LeetCode刷题(数组and排序)】:存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 示例 1: 输入:nums [1,2,3,1] 输出:true 示例 2: 输入:nums [1,2…...
半导体产业链解析:晶圆厂、无晶圆厂与代工厂的比较与作用
半导体产业一直是全球科技发展的关键驱动力,在半导体产业中,晶圆厂、无晶圆厂公司和代工厂是三个重要的参与者。它们在产业环节、生产方式、经营模式和市场竞争等方面存在一些显著差异。本文将探讨半导体晶圆厂、无晶圆厂公司和代工厂之间的区别…...
Apipost一键压测已支持导入CSV文件
最近更新中Apipost对UI页面进行了一些调整,另外一键压测功能支持参数化!本篇文章将详细介绍这些改动! API调试页面的细节改动 在请求区填入请求参数或脚本时会有相应的标识 如在Query中填入多个参数时上方会展示数量 在预、后执行脚本中写…...
RabbitMQ的5种模式——再探RabbitMQ的模式,简单、工作,发布订阅(广播),路由、主题 页面分析
前言 RabbitMQ作为一款常用的消息中间件,在微服务项目中得到大量应用,其本身是微服务中的重点和难点,有不少概念我自己的也是一知半解,本系列博客尝试结合实际应用场景阐述RabbitMQ的应用,分析其为什么使用࿰…...
初识华为云数据库GaussDB for openGauss
01 前言 GaussDB是华为自主创新研发的分布式关系型数据库。该产品具备企业级复杂事务混合负载能力,同时支持分布式事务,同城跨AZ部署,数据0丢失,支持1000的扩展能力,PB级海量存储。同时拥有云上高可用,高可…...
深圳寄包裹到德国
深圳,作为全球最发达的城市之一,以其高效的物流服务在全球范围内享有盛名。如果你正在寻找一种方式将包裹从深圳寄送到德国,那么本文将为你提供详细的步骤和建议。 第一步:了解国际邮寄的基本信息 首先,你需要了解包裹…...
系统架构师备考倒计时22天(每日知识点)Redis篇
Redis篇 1.Redis与Memcache能力对比 工作MemCacheRedis数据类型简单 key/value 结构丰富的数据结构持久性不支持支持分布式存储客户端哈希分片/一致性哈希多种方式,主从、Sentinel、Cluster 等多线程支持支持支持(Redis5.0及以前版本不支持)内存管理私有内存池/内…...
现有库存(on-hand inventory),库存水平(inventory level),库存位置(inventory position)
库存管理中,这几个名词特别容易混,干脆写一篇博客总结下。 现有库存(on-hand inventory),是指持有的真实库存量 库存水平(inventory level),现有库存减去延迟交付的订单 inventory level on-hand inventory − backorder quant…...
智慧空开让用电更安全、管理更智能——电脑APP远程控制开合闸
安科瑞 崔丽洁 01 什么是低压断路器?低压断路器的定义是:能够接通、承载及分断正常电路条件下的电流,也能在规定的非正常电路条件(过载、短路、特别是短路)下接通、承载一定时间和分断电流的开关电器。 断路器的分类&…...
PyTorch 中张量运算广播
TLDR 右对齐,空补一,从左往右依维运算 [m] [x, y] [m x, m y] 正文 以如下 a b 两个 tensor 计算为例 a torch.tensor([[1],[2],[3], ]) b torch.tensor([[[1, 2, 3],],[[4, 5, 6],],[[7, 8, 9],], ]) # a.shape (3, 1) # b.shape (3, 1, 3)首先…...
Blender:使用立方体制作动漫头像
好久没水文章 排名都掉到1w外了 ~_~ 学习一下blender,看能不能学习一点曲面变形的思路 一些快捷键 ctrl 空格:区域最大化,就是全屏 ctrl alt 空格:也是区域最大化 shift b:框选区域然后最大化显示该范围 shift 空…...
【ppt技巧】ppt里的图片如何提取出来?
之前分享过如何将PPT文件导出成图片,今天继续分享PPT技巧,如何提取出PPT文件里面的图片。 首先,我们将PPT文件的后缀名,修改为rar,将文件改为压缩包文件 然后我们将压缩包文件进行解压 最好是以文件夹的形式解压出来…...
Python学习基础笔记七十三——调试程序
为什么要调试? 我们发现程序运行的结果和我们预期的不符。 程序运行的错误,我们通常叫做bug。 有两种类型的bug:语句错误和逻辑错误。 所谓语句错误,就是执行代码的时候,解释器就可以直接发现的代码错误,…...
BOSHIDA DC电源模块关于电容器的电解液位置
BOSHIDA DC电源模块关于电容器的电解液位置 DC电源模块中的电容器扮演着一个非常重要的角色,它们能够对电路提供稳定的电源电压,同时也可以作为电路中的滤波器,去除电路中的噪声和纹波。在DC电源模块中使用的电容器通常是电解型电容器&#…...
如何实现 Es 全文检索、高亮文本略缩处理(封装工具接口极致解耦)
如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口(支持父类属性的复杂映射)Trans 接口可优化的点高亮全局配置类如下真实项目落地效果为什么不用 numOfFragments、fragm…...
C++多线程编程(第四章 案例1,C++11和C++17 多核并行计算样例)
目录 4.1手动实现多核base16编码4.1.1 实现base16编码4.1.2无多线程代码4.1.3 C 11多线程代码4.1.4 C 17多线程并发4.1.5 所有测试代码汇总 4.1手动实现多核base16编码 4.1.1 实现base16编码 二进制转换为字符串 一个字节8位,拆分为两个4位字节(最大值…...
SwitchyOmega+Burp无感抓包实战:解决HTTPS拦截与流量路由难题
1. 为什么“无感抓包”是BurpSuite日常使用的分水岭刚接触Web安全测试的朋友常有个错觉:装上Burp Suite,配好代理,打开浏览器,点几下网页——流量就该自动进来了。结果现实是:首页打不开、登录态丢失、HTTPS报错满屏、…...
如何删除论文脚注横线的方法——视图-草稿-引用——显示备注——删除脚注分隔符-即可。
如何删除论文脚注横线的方法——视图-草稿-引用——显示备注——删除脚注分隔符-即可。 Word中脚注线不会删?这里有妙招!,教育,职业教育,好看视频...
基于ESP8266与MQTT的家庭水压自动控制系统设计与实现
1. 项目概述与核心需求解析家里水压不稳、供水时断时续,这大概是很多朋友都遇到过的烦心事。我所在的城市供水情况就很不理想,为了解决这个问题,我不得不自己动手,搭建了一套基于ESP8266微控制器的家庭水压增压与储水自动控制系统…...
招行+工行:ReAct(Reasoning + Acting) 讲清楚,并结合 金融场景(含自进化智能体) 给出可直接用的案例
下面我把 ReAct(Reasoning Acting) 讲清楚,并结合 ** 金融场景(含自进化智能体)** 给出可直接用的案例与话术,适合分享 / 汇报。一、ReAct 是什么(一句话)ReAct 推理(T…...
观察Token消耗明细,Taotoken用量看板如何帮助控制预算
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 观察Token消耗明细,Taotoken用量看板如何帮助控制预算 对于个人开发者或项目管理者而言,在使用大模型API时…...
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 还在为传统魔兽争霸III编辑器缓慢的加载速度和复杂的操作界面而烦恼吗?Hive…...
基于特征工程的电力系统虚假数据注入攻击检测方案
1. 项目概述与核心挑战在电力系统这个庞大而精密的“交响乐团”中,自动发电控制(AGC)系统扮演着指挥家的角色。它的核心任务是根据电网频率和联络线功率的微小波动,实时调整各发电机的出力,确保整个电网的频率稳定在50…...
程序员的物理级打字肌肉记忆训练指南:从一指禅到无意识盲打的科学路径
程序员的物理级打字肌肉记忆训练指南:从一指禅到无意识盲打的科学路径 在日常写代码或重构时,你是否遇到过这种场景: 脑子里已经构思好了完美的重构逻辑,但在输入 >、{} 或 _ 时,手指本能地一顿,视线不…...
C语言--day19
第十章 内存管理当./a.out 运行起来后,系统会给a.out分配一段内存区域1、code ,存放编写好的c语言代码。 只读特性,在运行期间不能修改2、data 数据段。 存储全局变量,和被static 修改的变量细分:data 数据段ÿ…...
别再乱用Bool和Enum了!用UE5的Gameplay Tags重构你的角色状态机(GAS避坑指南)
别再乱用Bool和Enum了!用UE5的Gameplay Tags重构你的角色状态机(GAS避坑指南)当你的ARPG角色同时陷入眩晕、灼烧和减速状态时,传统状态机往往会暴露出致命缺陷——布尔值互相覆盖、枚举组合爆炸、条件判断嵌套成灾。而UE5的Gamepl…...
