Verilog学习(SPI协议的Flash驱动控制)

news2025/1/11 0:08:44

目录

一、SPI通信协议

1.1 SPI物理层 

1.2 SPI协议层

二、实战

2.1 SPI控制FLASH实现全擦除代码编写

2.2 上板验证


一、SPI通信协议

1.1 SPI物理层 

SPI通信模式为主-从模式 ,分为一主一从、一主多从:

 

 

片选线CS用于主机选择对应的从机进行通信,片选线置低电平为通信开始信号,被拉高则为开始信号。

1.2 SPI协议层

SPI协议有四种通信模式(通过CPOL和CPHA控制),

 

其中CPOL控制当没有数据传输的时候SCK的电平状态;CPHA控制数据采样位置,为0的时候位置为奇数边沿,为1的时候为偶数边沿。

 

 

下图传输为高位在前,先传输高位,每次传输数据的个数没有限制。

 

二、实战

2.1 SPI控制FLASH实现全擦除代码编写

程序的固化流程:

生成jic文件:

 选择生成好的jic文件烧录:

固化后的程序即使断电也不会丢失,如果想去除flash中的固化程序,可以进行全擦除操作。

第一种方法可以到下载器中进行全擦除:

第二种方法就是我们要讲的,自己编写程序对flash芯片进行全擦除。

首先打开flash芯片的手册:

找到全擦除对应的指令BE(Bulk Erase): 

然后找到BE指令的介绍:

从介绍里面可以知道:

  • BE指令会把flash芯片中的所有位设置为1。
  • 在执行全擦除指令之前,需要先执行一个写使能指令WREN。
  • 在BE指令发送的时候需要将片选信号\overline{S}拉低(如上图),指令发送完毕后需要把\overline{S}拉高,拉高片选信号后才会开始执行BE指令。

然后查看一下写使能指令的信息:

 还有一个要注意的地方就是输入时序的问题,tSLCH、tCHSH、tSHSL这三个时间要注意:

tSLCH为从片选信号\overline{S}拉低到第一个bit到来的时间间隔,最小值为5ns(如下图)。

tCHSH为从最后一个bit写入完成到片选信号\overline{S}拉高的时间间隔,最小值为5ns。

tSHSL为两个指令之间需要等待的时间,最小值为100ns。

基于上面的内容我们可以得到我们实验的时序图: 

 

实验顶层模块框图:

 内部结构:

 按键消抖子模块(为了简单这个按键消抖模块我就不做了,直接使用key_in控制):

全擦除控制子模块:

全擦除控制模块波形:

flash_be_ctrl模块verilog代码:

module flash_be_ctrl(
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    input   wire    key_in      , //按键信号
    output  reg     cs_n        , //片选信号,低电平有效
    output  reg     sck         , //spi通信时钟信号,采用的是12.5Hz
    output  reg     mosi          //主机输出的数据
);
parameter WREN_INS = 8'b0000_0110;
parameter BE_INS = 8'b1100_0111;

reg           key_en;
reg           key_flag;
reg   [2:0]   state; //状态机,0为闲置状态
reg   [4:0]   cnt_clk;
reg   [2:0]   cnt_byte;
reg   [1:0]   cnt_sck;
reg   [2:0]   cnt_bit;

//检测按键是否按下,生成key_flag信号,并且只检测一次
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        key_en <= 1'b1;
        key_flag <= 1'b0;
    end
    else if(key_in == 1'b0 && key_en == 1'b1) begin
        key_en <= 1'b0;
        key_flag <= 1'b1;
    end
    else begin
        key_en <= key_en;
        key_flag <= 1'b0;
    end
end

//cs_n片选信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        cs_n <= 1'b1;
    end
    else if(key_flag == 1'b1 || (cnt_clk == 5'd31 && cnt_byte == 3'd3)) begin
        cs_n <= 1'b0; //拉低
    end
    else if((cnt_clk == 5'd31 && cnt_byte == 3'd2) || (cnt_clk == 5'd31 && cnt_byte == 3'd6)) begin
        cs_n <= 1'b1; //拉高
    end
    else begin
        cs_n <= cs_n;
    end
end

//cnt_clk计数信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        cnt_clk <= 5'd0;
    end
    else if(cnt_clk == 5'd31 || state == 3'd0) begin
        cnt_clk <= 5'd0;
    end
    else begin
        cnt_clk <= cnt_clk + 1'b1;
    end
end

//cnt_byte计数信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        cnt_byte <= 3'd0;
    end
    else if(cnt_byte == 3'd6 && cnt_clk == 5'd31) begin
        cnt_byte <= 3'd0;
    end
    else if(cnt_clk == 5'd31) begin
        cnt_byte <= cnt_byte + 1'b1;
    end
    else begin
        cnt_byte <= cnt_byte;
    end
end

//cnt_sck计数信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        cnt_sck <= 2'd0;
    end
    else if(cnt_byte == 3'd1 || cnt_byte == 3'd5) begin
        cnt_sck <= cnt_sck + 1'b1;
    end
    else begin
        cnt_sck <= 2'd0;
    end
end

//cnt_bit计数信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        cnt_bit <= 3'd0;
    end
    else if(cnt_byte != 3'd1 && cnt_byte != 3'd5) begin
        cnt_bit <= 3'd0;
    end
    else if(cnt_sck == 2'd2) begin
        cnt_bit <= cnt_bit + 1'b1;
    end
    else begin
        cnt_bit <= cnt_bit;
    end
end

//state状态机
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        state <= 3'd0; //IDLE
    end
    else if(key_flag == 1'd1) begin
        state <= 3'd1; //WREN
    end 
    else if(cnt_clk == 5'd31 && cnt_byte == 3'd2) begin
        state <= 3'd2; //DELAY
    end
    else if(cnt_clk == 5'd31 && cnt_byte == 3'd3) begin
        state <= 3'd3; //BE
    end
    else if(cnt_clk == 5'd31 && cnt_byte == 3'd6) begin
        state <= 3'd0; //IDLE
    end
    else begin
        state <= state;
    end
end

//输出sck时钟信号
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        sck <= 1'b0;
    end
    else if(cnt_sck == 2'd2 || (cnt_sck == 2'd0 && sck == 1'b1)) begin
        sck <= ~sck;
    end
    else begin
        sck <= sck;
    end
end

//输出mosi数据
always@(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        mosi <= 1'b0;
    end
    else if(cnt_byte != 3'd1 && cnt_byte != 3'd5) begin
        mosi <= 1'b0;
    end
    else if(cnt_byte == 3'd1 && cnt_sck == 2'd0) begin
        //WREN信号
        case(cnt_bit)
            3'd0: mosi <= WREN_INS[7];
            3'd1: mosi <= WREN_INS[6];
            3'd2: mosi <= WREN_INS[5];
            3'd3: mosi <= WREN_INS[4];
            3'd4: mosi <= WREN_INS[3];
            3'd5: mosi <= WREN_INS[2];
            3'd6: mosi <= WREN_INS[1];
            3'd7: mosi <= WREN_INS[0];
        endcase
    end
    else if(cnt_byte == 3'd5 && cnt_sck == 2'd0) begin
        //BE信号
        case(cnt_bit)
            3'd0: mosi <= BE_INS[7];
            3'd1: mosi <= BE_INS[6];
            3'd2: mosi <= BE_INS[5];
            3'd3: mosi <= BE_INS[4];
            3'd4: mosi <= BE_INS[3];
            3'd5: mosi <= BE_INS[2];
            3'd6: mosi <= BE_INS[1];
            3'd7: mosi <= BE_INS[0];
        endcase
    end
    else begin
        mosi <= mosi;
    end
end
endmodule

testbench代码:

module tb_flash_be_ctrl();

reg sys_clk;
reg sys_rst_n;
reg key_in;
wire cs_n;
wire sck;
wire mosi;

always #10 sys_clk = ~sys_clk;

initial begin
    sys_clk = 1'b1;
    sys_rst_n <= 1'b0;
    key_in <= 1'b1;
    #20
    sys_rst_n <= 1'b1;
end

initial begin
    #200
    key_in <= 1'b0;
    #100
    key_in <= 1'b1;
end

flash_be_ctrl flash_be_ctrl_inst(
    .sys_clk(sys_clk)     ,
    .sys_rst_n(sys_rst_n)   ,
    .key_in(key_in)      , //按键信号
    .cs_n(cs_n)       , //片选信号,低电平有效
    .sck(sck)         , //spi通信时钟信号,采用的是12.5Hz
    .mosi(mosi)          //主机输出的数据
);

endmodule

仿真波形:

如果想额外添加flash仿真文件可以在如下窗口添加:

代码编写完成后我们就可以上板验证了。

2.2 上板验证

各个端口绑定的引脚如下: 

下面介绍一下怎么找到对应的引脚。首先找到flash的原理图:

FLASH_NCE为片选信号,对应的端口为D2: 

key_in信号对应M1端口:

并且按下时为低电平: 

 

 EPCS_ASDO为flash芯片的输入mosi,对应引脚C1:

 

 EPCS_CLK为传入flash芯片的同步时钟信号sck,对应引脚为H1:

其余两个是系统时钟和系统复位信号,这个我就不作说明了。

配置好引脚后,重新编译,发现报错信息:

 这些要修改io口的配置:

改成如下内容:

三个位置对应三个错误,改完后重新编译通过。

然后就是上板测试,首先要烧录一个测试程序到板子上(要进行固化),然后再烧录我们的spi全擦除程序到板子上,烧录完成后按下key1,等待一段时间后再重新上电,重新上电后就可以看到之前固化的程序消失了,全擦除实现成功!

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

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

相关文章

html爱情表白神器,回忆纪念册(附源码)

文章目录 1.设计来源1.1 主界面1.2 相关界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/131022313 html爱情表白神器&#xff0c;回忆纪念册 html爱情表白神器&#x…

【JavaEE初阶】万字详解TCP/IP协议!!!(一)

文章目录 1. 应用层和传输层的联系2. UDP协议3. TCP协议3.1 TCP报头介绍3.2 TCP实现可靠传输的核心机制&#xff08;1&#xff09;确认应答&#xff08;2&#xff09;超时重传&#xff08;3&#xff09;连接管理建立连接&#xff08;三次握手&#xff09;断开连接(四次挥手) &a…

测试人挣破年入20万的束缚,从第一个python+selenium项目开始!

今天整理一下实战项目的代码共大家学习。&#xff08;注:项目是针对我们公司内部系统的测试&#xff0c;只能内部网络访问&#xff0c;外部网络无法访问&#xff09; 问&#xff1a; 1.外部网络无法访问&#xff0c;代码也无法运行&#xff0c;那还看这个项目有啥用 2.如何学…

English Learning - L3 作业打卡 Lesson4 Day28 2023.6.1 周四

English Learning - L3 作业打卡 Lesson4 Day28 2023.6.1 周四 引言&#x1f349;句1: Something may appear to be free of charge, but there may be a hidden cost.成分划分弱读连读爆破语调 &#x1f349;句2: When we fail to see problems at work, my supervisor tells …

一文了解0欧电阻的奥秘:它不是导线,也不是真的0欧

目录 一、0欧电阻的定义 二、 0欧电阻和导线的区别 三、0欧电阻的选型 四、0欧电阻长什么样 五、0欧姆电阻的用途 1.调试和兼容设计&#xff1a; 2.预留电阻位置&#xff1a; 3.方便布线&#xff1a; 4.方便测试电流&#xff1a; 5.噪声抑制&#xff1a; 6.信号隔离…

学习stm32f103c8t6,如何从正点原子官网下载资料及资料使用

学习stm32f103c8t6&#xff0c;如何从正点原子官网下载资料及资料使用 一、下载资料 用百度搜索“正点原子” 点击进入后找我们需要的芯片型号的资料&#xff0c;选择stm32f103-mini开发板的资料进行下载&#xff0c;其他的像stm32f103的精英版&#xff0c;战舰开发板啥的&am…

代码随想录二刷 day11 | 栈与队列 之 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

day11 20. 有效的括号1047. 删除字符串中的所有相邻重复项150. 逆波兰表达式求值 20. 有效的括号 题目链接 解题思路&#xff1a; 有三种不匹配的情况&#xff1a; 第一种情况&#xff0c;字符串里左方向的括号多余了 。 第二种情况&#xff0c;括号没有多余&#xff0c;但是…

大专毕业,从6个月开发转入测试岗位的一些感悟——写在测试岗位3年之际

时光飞逝&#xff0c;我从前端开发岗位转入测试岗位已经三年了&#xff0c;这期间从迷茫到熟悉&#xff0c;到强化&#xff0c;到熟练&#xff0c;到总结&#xff0c;感受还是很深的&#xff01; 三年前的某一个晚上&#xff0c;我正准备下班回家&#xff0c;我们的项目经理把…

Selenium UI自动化测试入门

1.先下载Pycharm编辑器&#xff0c; 网站&#xff1a;下载地址 2.安装python环境包 地址&#xff1a;Download Python | Python.org 安装的时候记住勾选自动配置环境变量 3.在pycharm中配置python执行器路径 4.安装selenium库 pip install selenium4.1.1 查看当前selenium版…

Flutter架构——线程模型

Flutter的架构分为框架、引擎和嵌入器层(Embedder)&#xff0c;其中嵌入器层将Flutter嵌入各个平台。Flutter完整的架构图如下&#xff1a; Flutter中的隔离是通过引擎层的一个线程来实现的&#xff0c;但是Flutter引擎线程的创建与管理又是由嵌入器负责的&#xff0c;也就是说…

Qt个人项目——天气预报,内带QListWidget自定义组件,支持全球城市天气

个人项目&#xff0c;自己制作了一个天气预报&#xff0c;还有选择城市列表&#xff0c;列表分大洲区域选择&#xff0c;具体选择后再进行选择城市&#xff0c;可以更新城市数据&#xff0c;自定义了QListWidget&#xff0c;总体来说完成度比较高&#xff0c;难度也不大&#x…

【Linux】Linux环境基础开发工具使用(gcc/g++使用)

⭐博客主页&#xff1a;️CS semi主页 ⭐欢迎关注&#xff1a;点赞收藏留言 ⭐系列专栏&#xff1a;Linux ⭐代码仓库&#xff1a;Linux 家人们更新不易&#xff0c;你们的点赞和关注对我而言十分重要&#xff0c;友友们麻烦多多点赞&#xff0b;关注&#xff0c;你们的支持是我…

【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要)

【Python】猎聘网招聘数据爬虫&#xff08;Python网络爬虫课设简要&#xff09; 注&#xff1a; 本文仅供学习交流使用&#xff01; 合肥学院-20信管-20302211009 项目文件可自行前往博客主页下载或联系作者qq&#xff08;3416252112&#xff09;。 爬取数据耗时约50分钟&am…

网络安全工程师面试题(附答案解析)

前言 有不少小伙伴面临跳槽或者找工作&#xff0c;本文总结了常见的安全岗位面试题&#xff0c;方便各位复习。祝各位事业顺利&#xff0c;财运亨通。在网络安全的道路上越走越远&#xff01;。 注&#xff1a;所有的资料都整理成了PDF&#xff0c;面试题和答案将会持续更新&a…

路径规划算法:基于黄金正弦优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于黄金正弦优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于黄金正弦优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

Springboot事件监听

Springboot事件监听中主要有以下对象&#xff1a; 1、事件&#xff08;event&#xff09;可以封装和传递监听器中要处理的参数&#xff0c;如对象或字符串&#xff0c;并作为监听器中监听的目标。 2、监听器&#xff08;listener&#xff09;具体根据事件发生的业务处理模块&am…

机器学习 day14 ( 神经网络 )

神经网络的发展 最开始的动机&#xff1a;是通过构建软件来模拟大脑&#xff0c;但今天的神经网络几乎与大脑的学习方式无关 我们依据大脑中的神经网络&#xff0c;来构建人工神经网络模型。左图中&#xff1a;一个神经元可以看作一个处理单元&#xff0c;它有很多的输入/树突…

如何解决企业客户签收回执慢,缩短回款周期?

方案应用领域及行业 本方案适用于快消品行业的供应链管理和财务管理 方案应用背景 由于动产物权的政策变化&#xff0c;物权转移从交付时才开始发生效力。也就是说&#xff0c;新政之前&#xff0c;企业发出商品&#xff0c;开出销售发票&#xff0c;即可申请货物回款&#…

LLM 系列 | 05:ChatGPT Prompt的迭代优化

简介 梅子留酸软齿牙&#xff0c;芭蕉分绿与窗纱。日长睡起无情思&#xff0c;闲看儿童捉柳花。小伙伴们好&#xff0c;我是微信公众号 《小窗幽记机器学习》 的小编&#xff1a;卖冰棍的小男孩。 更多、更新文章欢迎关注微信公众号&#xff1a;小窗幽记机器学习。后续会持续…

Ubuntu的安装教程

文章目录 一、Ubuntu 的安装教程1、Ubuntu的镜像下载2、服务器版的安装教程2.1.1、允许 root 远程登录 3、桌面版的安装教程3.1.1、允许 root 远程登录 一、Ubuntu 的安装教程 1、Ubuntu的镜像下载 ​ 这里我选择阿里云的镜像下载你也可以选择Ubuntu的官网下载 Ubuntu官网 如…