FPGA解析串口指令控制spi flash完成连续写、读、擦除数据

前言

最近在收拾抽屉时找到一个某宝的spi flash模块,如下图所示,我就想用能不能串口来读写flash,大致过程就是,串口向fpga发送一条指令,fpga解析出指令控制flah,这个指令协议目前就是:
55 + AA + CMD + LEN_h + LEN_m + LEN_l + DATA
CMD:01 写;02 读;03 擦除(片擦除);
LEN_h/m/l:三个字节表示读写长度,高字节在前低字节灾后;
DATA:如果是写flah,DATA则为需要写入的数据,其它两种状态可以不填;
spi flash模块

1. 串口指令解析

软件使用序列式状态机完成串口指令解析,最后解析出三个使能信号,以及相应的数据、长度、地址。
在这里插入图片描述

always@(posedge clk,negedge rst_n)if(!rst_n)state<=S0;else begincase(state)S0:if(uart_vld)beginif(uart_dat == 8'h55)state<=S1;elsestate<=S0;					end else state<=S0;					S1:if(uart_vld)beginif(uart_dat == 8'hAA)state<=S2;elsestate<=S0;					end else state<=S1;S2:if(uart_vld)state<=S3;elsestate<=S2;S3://命令字if(uart_vld)state<=S4;elsestate<=S3;		S4://长度hif(uart_vld)state<=S5;elsestate<=S4;	S5://长度mif(uart_vld)state<=S6;elsestate<=S5;S6://长度lif(uart_vld)state<=S7;elsestate<=S6;S7:state<=S7;default:state<=S0;	endcaseend

2. flash 控制

对于flash三个功能(读、写、擦书)分别设计了三个模块,每个模块完成对应功能以及输出flash的cs、sclk、sdi等信号,但是flash接口只有一组控制信号,因此需要对三个模块输出的flash控制信号进行选择输出,如下所示。

always@(posedge clk,negedge rst_n)if(!rst_n)begino_spi_cen	<=1'b1;		o_spi_sclk	<=1'b0; 		o_spi_sdi	<=1'b0; 	end else begincase(work_state)3'b001:begin//xieo_spi_cen	<= wr_flash_csn		;o_spi_sclk	<= wr_flash_sclk		;o_spi_sdi	<= wr_flash_sdi		;end3'b010:begin//duo_spi_cen	<= rd_flash_csn		;o_spi_sclk	<= rd_flash_sclk		;o_spi_sdi	<= rd_flash_sdi		;end	3'b100:begin//cachuo_spi_cen	<= er_flash_csn		;o_spi_sclk	<= er_flash_sclk		;o_spi_sdi	<= er_flash_sdi		;end	default:begino_spi_cen	<=1'b1;		o_spi_sclk	<=1'b0; 		o_spi_sdi	<=1'b0; endendcaseendassign 	work_state	={spi_flash_erctl,spi_flash_rdctl,spi_flash_wrctl};			

2.1 flash写控制

软件对flash写控制的基本方法是收到一个串口数据就写进flash,并不是先缓存256个字节然后直接进行页编程,这样搞控制逻辑比较复杂。方法确定后就是软件实现,上级输出了vld和data(vld和data上上沿对齐,vld只有一个时钟宽度),使用vld作为触发条件,完成数据写入。
同样软件使用序列式状态机器进行流程控制。然后先写使能,然后正常写指令(02)、地址数据。
在这里插入图片描述

always@(posedge clk,negedge rst_n)if(!rst_n)state<=S0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2] && vld_zk)state<=S1;elsestate<=S0;S1://xieshineng  function code 06if(&cnt && cnt_bit=='d7)state<=S2;else	state<=S1;S2://delayif(&cnt && cnt_bit==WIDTH-1)state<=S3;else	state<=S2;S3://xie gongneng ma 02if(&cnt && cnt_bit=='d7)state<=S4;else state<=S3;S4://xie dizhiif(&cnt && cnt_bit=='d23)state<=S5;else state<=S4;S5://xie shuju if(&cnt && cnt_bit=='d7)state<=S6;else state<=S5;S6:if(&cnt)state<=S7;else state<=S6;S7:if(cnt_byte == wr_len)state<=S8;elsestate<=S0;S8:state<=S8;default:state<=S0;endcaseend

写

2.2 flash擦除

直接在写控制上面改,前面有个写使能,下图是擦除指令(C7/60)
在这里插入图片描述

always@(posedge clk,negedge rst_n)if(!rst_n)state<=S0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2:1]==2'b01)state<=S1;elsestate<=S0;S1://xieshineng  function code 06if(&cnt && cnt_bit=='d7)state<=S2;else	state<=S1;S2://delayif(&cnt && cnt_bit==WIDTH-1)state<=S3;else	state<=S2;S3://if(&cnt && cnt_bit=='d7)state<=S6;else state<=S3;S6:if(&cnt)state<=S7;else state<=S6;S7:state<=S8;S8:state<=S8;default:state<=S0;endcaseend

在这里插入图片描述

2.3 flash读控制

从falsh读数据比较简单,接口时序如下图,软件实现同样还是序列式状态机,根据传入的长度决定读取的字节数。
因为数据从flash读出后需要通过串口发送,因此为了减少工作量,从flash读出一个数据,串口就发送一个数据,因此为了避免flash两个数据都读出来了串口一个都没发完,需要控制flash读数间隔,使得这个间隔大于串口发完一个字节的时间,举个栗子,假设现在串口波特率为115200,那么发完一个字节的时间约为86.8us(10位),那么flash读数间隔要大于86.9us。
在这里插入图片描述

always@(posedge clk,negedge rst_n)if(!rst_n)state<=S0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2:1]==2'b01)state<=S1;elsestate<=S0;S1:state<=S2;S2://cs xian ladi 		if(&cnt)	state<=S3;else state<=S2;S3://xie gongneng ma 02if(&cnt && cnt_bit=='d7)state<=S4;else state<=S3;S4://xie dizhiif(&cnt && cnt_bit=='d23)state<=S5;else state<=S4;S5://xie shuju if(&cnt && cnt_bit=='d7)state<=S6;else state<=S5;S6:if(&cnt)state<=S7;else state<=S6;S7:if(cnt_byte == rd_len)state<=S8;elsestate<=S9;S9:if(dly_end)state<=S1;else state<=S9;S8:state<=S8;default:state<=S0;endcaseend

在这里插入图片描述

3. 实物测试

开始我设置的波特率为921600,擦除和写没问题,至少在时序上是很完美的,但是回读出来的数据如下图前十个字节一样,本来写入是01~0a,现在读出的数据中第2、3、5、7、9都是FF,后来我把波特率降到9600,然后就好了,下图最后10个字节。中间10个ff是擦除完后读出来数据。
软件工程链接:
软件工程、源码、仿真、数据手册、fllash仿真模型
在这里插入图片描述
最后来张全家福
在这里插入图片描述

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

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

相关文章

剑指offer(C++)-JZ64:求1+2+3+...+n(算法-位运算)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&…

QT使用QXlsx实现对Excel的创建与文字的存取 QT基础入门【Excel的操作】

准备:搭建环境引用头文件QT中使用QtXlsx库的三种方法 QT基础入门【Excel的操作】_吻等离子的博客-CSDN博客 #include "xlsxdocument.h"const QString ExcelName="./test.xlsx"; QTXLSX_USE_NAMESPACE // 添加Xlsx命名空间 1、初始化excel表格 注意!两…

行业首家·合规典范|昂首资本携手菲律宾警察局,树立经纪商合规经营典范

Anzo Capital 昂首资本携手菲律宾达沃市警察局长阿尔贝托P卢帕兹受邀参加由 AFP-PNP Southern Mindanao Press Corps( 菲律宾武装部队(AFP)和菲律宾国家警察(PNP)南部棉兰老岛记者团)举办的新闻发布会。 本次新闻发布会在菲律宾达沃市皇家曼达亚酒店举行&#xff0c;Anzo Cap…

前端、后端、运维、产品等开发技术在面试之前,如何做好一份完美的自我介绍

1. 文章引言 我们都知道,不论是前端开发、后端开发、产品设计、运维开发等,在面试之前,都要做自我介绍。 虽然我们都有简历,但对方仍要求做自我介绍。 那么,你怎么做一份完美的自我介绍,给面试官一个良好的印象呢? 接下来,我便详细介绍,如何做一份完美的自我介绍。…

React创建组件的三种方式及其区别是什么?

在React中&#xff0c;创建组件的三种主要方式是函数式组件、类组件和使用React Hooks的函数式组件。以下是对每种方式的详细解释以及它们之间的区别&#xff1a; 1、函数式组件&#xff1a; 函数式组件是使用纯粹的JavaScript函数来定义的。它接收一个props对象作为参数&…

Leetcode每日一题:2337. 移动片段得到字符串(2023.8.21 C++)

目录 2337. 移动片段得到字符串 题目描述&#xff1a; 实现代码与解析&#xff1a; 双指针 原理思路&#xff1a; 2337. 移动片段得到字符串 题目描述&#xff1a; 给你两个字符串 start 和 target &#xff0c;长度均为 n 。每个字符串 仅 由字符 L、R 和 _ 组成&#x…

网络渗透day1-Windows Server相关

-建议收藏至手机&#xff0c;每天顺道几分钟学一下。掌握别人掌握不了的知识&#xff0c;赢在起跑线。 1.Windows Server操作系统是以下哪个公司开发的&#xff1f; A.Microsoft B.Apple C.Google D.IBM 正确答案&#xff1a;A 答案解析&#xff1a;Windows Server操作系…

【LeetCode-中等题】189. 轮转数组

题目 题解一&#xff1a;开辟数组 取模运算寻找位置(ik)mod n 新位置 思路&#xff1a;通过&#xff0c;开辟数组 取模运算寻找新位置------位置(ik)mod n 新位置 int[] newNums new int[nums.length];for(int i 0;i<nums.length;i){newNums[(ik)%nums.length] nums[i…

微信小程序|步骤条

![在这里插入图片描述]() 步骤条是现代用户界面设计中常见的元素之一,它能够引导用户按照预定顺序完成一系列任务或步骤。在小程序中,实现步骤条可以为用户提供更好的导航和引导,使用户体验更加流畅和直观。本文将介绍如何在小程序中实现步骤条,并逐步展示实现的过程和关键…

时序预测 | Matlab实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元时间序列预测

时序预测 | Matlab实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元时间序列预测 目录 时序预测 | Matlab实现SO-CNN-BiGRU蛇群算法优化卷积双向门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 | Matlab实现SO-CNN-BiGRU蛇群算法优化…

Docker容器与虚拟化技术:Docker consul 实现服务注册与发现

目录 一、理论 1.Docker consul 二、实验 1.consul部署 2. consul-template部署 三、总结 一、理论 1.Docker consul &#xff08;1&#xff09;服务注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&…

在Ubuntu 22.04上配置静态IP地址

在Ubuntu 22.04上配置静态IP地址需要进行以下步骤&#xff1a; 打开终端&#xff1a;在桌面上&#xff0c;按下Ctrl Alt T 组合键&#xff0c;或者在应用程序搜索栏中键入“终端”。 编辑网络配置文件&#xff1a;使用文本编辑器&#xff08;例如nano或vim&#xff09;打开网…

微信小程序,封装身高体重选择器组件

wxml代码&#xff1a; // 微信小程序的插值语法不支持直接使用Math <wxs src"./ruler.wxs" module"math"></wxs> <view class"ruler-container"><scroll-view scroll-left"{{scrollLeft}}" enhanced"{{tru…

梳理系统学习R语言1-R语言实战-使用ggplot进行高阶绘图

以下为书中代码&#xff0c;会添加一些理解 library("ggplot2") ggplot(datamtcars,aes(xwt,ympg))geom_point()geom_point(pch17,color"blue",size2)geom_smooth(method"lm",color"red",linetype2)labs(title"Automobile Data&…

【SpringBoot】SpringBoot完整实现电子商务系统

一个完整的电子商务系统需要涉及到前台展示、后台管理、商品管理、订单管理、用户管理等各方面。这里提供一个简单的实现示例&#xff0c;供参考。 前端代码 前端使用Vue框架&#xff0c;以下是部分代码示例&#xff1a; 商品列表页&#xff1a; <template><div>…

vue中利用Echarts实现飞线(飞机)地图样式

实现效果 思想&#xff1a;主要是三个要素&#xff1a;1 地图样式 2散点图 3飞线 组合配置后就形成以下效果。 第一步&#xff1a;vue中引入Echarts npm install vue-echarts echarts第二步&#xff1a;导入代码 代码已经写好&#xff0c;直接引入运行就好了&#xff0c;关键…

信息安全面试题合集

0x00 前言 本篇会记录一些可能会遇到的面试题&#xff0c;持续更新 0x01 Web SQL注入 sql注入常见的闭合方式有哪些&#xff1f;Mysql5.0上下sql注入有什么区别&#xff1f;SQL注入空格被过滤&#xff0c;有什么绕过方式&#xff1f;过滤了逗号&#xff0c;有什么绕过方式&…

字节跳动 Git 的正确使用姿势与最佳实践

版本控制Git 黑马&尚硅谷 Git的前世今生 方向介绍 为什么要学习Git 1.0 Git是什么 1.1 版本控制 1.1.1 本地版本控制 1.1.2 集中版本控制 1.1.3 分布式版本控制 我们已经把三个不同的版本控制系统介绍完了&#xff0c;Git 作为分布式版本控制工具&#xff0c; 虽然目前来讲…

Django(4)-Django 管理页面

创建一个管理员账号 python manage.py createsuperuser运行项目&#xff0c;访问http://127.0.0.1:8080/admin&#xff0c;可以看到管理员界面 管理页面加上投票应用 polls/admin.py from django.contrib import admin# Register your models here. from .models import …

自动化测试之Junit

Junit引入注解参数化单参数多参数方法传参 测试用例执行顺序断言测试套件 Junit引入 Junit来编写和组织自动化测试用例&#xff0c;使用Selenium来实际模拟用户与Web应用程序的交互。也就是使用JUnit的测试功能来管理和运行Selenium测试。常见的做法是&#xff0c;使用JUnit作…