【国产FPGA高云GW1N-4系列开发板测评】FLASH操作
本帖最后由 怀揣少年梦 于 2021-12-28 14:12 编辑<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">一、目的</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">使用高云</font><font face="Calibri">GW1N-4</font><font face="宋体">系列开发板</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">来</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">擦除、页写</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">FLASH</font><font face="宋体">,</font><font face="Calibri">FLASH</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">使用的</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">型号为</font><font face="Calibri">W25Q</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">64JV</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">。</font></span></span></span></span></p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">二、</font><font face="Calibri">W25Q64JVSSIQ</font><font face="宋体">的特征</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">1</font><font face="宋体">、</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">支持</font><font face="Calibri">3</font><font face="宋体">种通信方式,</font><font face="Calibri">SPI</font><font face="宋体">、</font><font face="Calibri">Dual SPI</font><font face="宋体">和</font><font face="Calibri">Quad SPI</font><font face="宋体">。</font><font face="Calibri">FLASH</font><font face="宋体">的存储单元无法写入</font><font face="Calibri">bit 1</font><font face="宋体">,只能写入</font><font face="Calibri">bit 0</font><font face="宋体">,所以写入数据之前要将原来的数据擦除(</font><font face="Calibri">FFh</font><font face="宋体">),遇到写入</font><font face="Calibri">bit 1</font><font face="宋体">的情况不作处理。</font><font face="Calibri">W25QQ</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">64JV</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">的特征为如下图所示</font></span></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">:</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"> </p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">2</font><font face="宋体">、</font><font face="Calibri">FLASH</font><font face="宋体">的存储结构</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">W25Q64JV </font><font face="宋体">由</font><font face="Calibri">Block0~Block127</font><font face="宋体">共</font><font face="Calibri">128</font><font face="宋体">个</font><font face="Calibri">Block</font><font face="宋体">组成,容量大小为</font><font face="Calibri">64M-bit,</font><font face="宋体">即</font><font face="Calibri">64M=128*64*1024*8bit/1024/1024</font><font face="宋体">。每个</font><font face="Calibri">Block</font><font face="宋体">由</font><font face="Calibri">Sector0~Sector15</font><font face="宋体">共</font><font face="Calibri">16</font><font face="宋体">个</font><font face="Calibri">Sector</font><font face="宋体">组成,每个</font><font face="Calibri">Sector</font><font face="宋体">大小为</font><font face="Calibri">4KB</font><font face="宋体">,由</font><font face="Calibri">16</font><font face="宋体">个</font><font face="Calibri">Page</font><font face="宋体">组成。以第一个</font><font face="Calibri">Sector</font><font face="宋体">为例,第</font><font face="Calibri">1</font><font face="宋体">个</font><font face="Calibri">Page</font><font face="宋体">地址从</font><font face="Calibri">xx0000h~xx00FF</font><font face="宋体">开始,第</font><font face="Calibri">2</font><font face="宋体">个</font><font face="Calibri">Page</font><font face="宋体">地址从</font><font face="Calibri">xx0100~xx01FF</font><font face="宋体">开始,第</font><font face="Calibri">3</font><font face="宋体">个</font><font face="Calibri">Page</font><font face="宋体">地址从</font><font face="Calibri">xx0200~xx02FF</font><font face="宋体">开始,以此类推</font><font face="Calibri">...</font><font face="宋体">,第</font><font face="Calibri">16</font><font face="宋体">个</font><font face="Calibri">Page</font><font face="宋体">地址从</font><font face="Calibri">xx0F00~xx0FFF</font><font face="宋体">开始。每个</font><font face="Calibri">Page</font><font face="宋体">的大小为</font><font face="Calibri">256</font><font face="宋体">个</font><font face="Calibri">Byte</font><font face="宋体">组成,后面会看到</font><font face="Calibri">Page Programd</font><font face="宋体">最大支持</font><font face="Calibri">256</font><font face="宋体">个</font><font face="Calibri">Byte</font><font face="宋体">。说明框图如下:</font></span></span></span></span></p>
<p style="text-align:justify"> </p>
<ol start="3"><br />
<li><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">FLASH</font><font face="宋体">的相关操作时序图</font></span></span></span></span></li>
</ol>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">1</font><font face="宋体">)写使能时序</font></span></span></span></span><br />
</p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">2</font><font face="宋体">)全擦除时序</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">3</font><font face="宋体">)页写时序</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">根据以上的时序绘制波形图,也就是</font><font face="Calibri">SPI</font><font face="宋体">模拟时序波形图。因为</font><font face="Calibri">FPGA</font><font face="宋体">时钟</font><font face="Calibri">50MHz</font><font face="宋体">,所以把</font><font face="Calibri">50M</font><font face="宋体">进行四分频,并且</font><font face="Calibri">32</font><font face="宋体">个时钟周期延时</font><font face="Calibri">640ns</font><font face="宋体">。正好可以作为两次数据间隔的延时周期。</font></span></span></span></span></p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">三、程序编写</font></span></span></span></span></p>
<p align="justify" style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">1、全擦除程序</font></span></span></span></span></span></p>
<p align="justify" style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">1)全擦除波形图绘制</font></span></span></span></span></span></p>
<p align="justify" style="text-indent:21.0000pt; text-align:justify"></p>
<p align="justify" style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">2)编写代码</font></span></span></span></span></span></p>
<pre>
<code>//`timescale 1ns/1ns
/*
Module Name : flash_ce
Project Name : flash
Description : flash全擦除模块
把主时钟四分频成12.5MHz,作为spi的输入时钟。
写一次数据与下一次数据之间必须等待50ns,每个时钟周期只能写入1bit数据,写一个字节即需要8个spi时钟周期,即32个系统时钟周期,说明一条完整指令需要640ns
*/
module flash_ce(
input wire sys_clk, //系统时钟,频率50MHz
input wire sys_rst_n, //复位信号,低电平有效
input wire key, //按键输入信号
output reg spi_cs_n, //片选信号
output reg spi_clk, //串行时钟
output reg spi_mosi //主输出从输入数据
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter IDLE = 4'b0001 , //初始状态 状态机四个状态
WR_EN = 4'b0010 , //写状态
DELAY = 4'b0100 , //等待状态
CE = 4'b1000 ; //全擦除状态
parameter WR_EN_INST = 8'b0000_0110, //写使能指令 06
CE_INST = 8'b1100_0111; //全擦除指令 C7
//reg define
reg cnt_byte; //字节计数器 记录输出字节个数和等待时间
reg state ; //状态机状态
reg cnt_clk ; //系统时钟计数器,用以记录单子字节
reg cnt_sck ; //串行时钟计数器,生成系统时钟
reg cnt_bit ; //比特计数器,产生高低位,控制MOSI输出
//除了在空闲状态,其他状态都进行系统时钟计数器,如果只使用cnt_clk作为状态跳转的约束条件不充分,
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_clk <= 5'd0;
else if(state != IDLE)
cnt_clk <= cnt_clk + 1'b1;
end
//由于状态跳转的约束条件不充分,所以使用cnt_byte 计数器对cnt_clk的计数周期进行计数,同时使用cnt_byte增加一次表示延时640ns
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_byte <= 3'd0;
else if((cnt_clk == 5'd31) && (cnt_byte == 3'd6))//当写完擦除指令后,等待640ns,片选拉高,此时cnt_byte = 6,并且刚好cnt_clk进行一个计数循环,就清零
cnt_byte <= 3'd0;
else if(cnt_clk == 5'd31)//cnt_clk每完成一个循环周期cnt_byte就加1,其他不变
cnt_byte <= cnt_byte + 1'b1;
end
//在进行写使能指令以及全擦除指令,并且已经发送一个字节时,记录系统时钟的个数
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_sck <= 2'd0;
else if((state == WR_EN) && (cnt_byte == 1'b1)) // 当进行写使能时,先等待640ns,即cnt_byte =1
cnt_sck <= cnt_sck + 1'b1;
else if((state == CE) && (cnt_byte == 3'd5)) //当写完使能信号,等待640ns,再片选拉高,继续等待640ns,再片选拉低,继续等待640ns,此时cnt_byte =5,此时又开始写擦除指令
cnt_sck <= cnt_sck + 1'b1;
end
//进行四分频,产生12.5MHz时钟.根据cnt_sck 记录系统时钟的个数,2个cnt_sck为低,2个cnt_sck为高
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
spi_clk <= 1'b0;
else if(cnt_sck == 2'd0)
spi_clk <= 1'b0;
else if(cnt_sck == 2'd2)
spi_clk <= 1'b1;
end
//片选信号输出
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
spi_cs_n <= 1;
else if(key == 1'b1)
spi_cs_n <= 0;
else if((cnt_byte == 3'd2) && (cnt_clk == 5'd31) && (state == WR_EN))
spi_cs_n <= 1;
else if((cnt_byte == 3'd3) && (cnt_clk == 5'd31) && (state == DELAY))
spi_cs_n <= 0;
else if((cnt_byte == 3'd6) && (cnt_clk == 5'd31) && (state == CE))
spi_cs_n <= 1;
end
//cnt_bit 高低位对调,控制MOSI输出。用于输出MOSI的哪一位
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt_bit <= 3'd0;
else if(cnt_clk == 2'd2)
cnt_bit <= cnt_bit + 1'b1;
end
//state 状态机跳转
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
state <= IDLE;
else
case(state)
IDLE:if(key == 1'b1)
state <= WR_EN;
WR_EN:if((cnt_byte == 3'd2) && (cnt_clk == 5'd31))
state <= DELAY;
DELAY:if((cnt_byte == 3'd3) && (cnt_clk == 5'd31))
state <= CE;
CE:if((cnt_byte == 3'd6) && (cnt_clk == 5'd31))
state <= IDLE;
default:
state <= IDLE;
endcase
end
//MOSI输出
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
spi_mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte == 3'd2))
spi_mosi <= 1'b0;
else if((state == CE) && (cnt_byte == 3'd6))
spi_mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte == 3'd1) && (cnt_sck == 5'd0))
spi_mosi <= WR_EN_INST;
else if((state == CE) && (cnt_byte == 3'd5) && (cnt_sck == 5'd0))
spi_mosi <= CE_INST;
end
endmodule</code></pre>
<p> </p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体"> 3)和</font><font face="Calibri">Modelsim</font><font face="宋体">联合仿真。(联合仿真视频可以参考B站高云半导体视频教程</font></span></span></span></span><a href="https://www.bilibili.com/video/BV1UK4y1A7ak?p=4&share_medium=android&share_plat=android&share_session_id=a8efd765-9b16-4b7c-995f-ebb924bd1128&share_source=WEIXIN&share_tag=s_i&timestamp=1640671755&unique_k=OUMOKoO">高云半导体FPGA课程 - 软件篇_哔哩哔哩_bilibili</a></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">创建工程文件,把相关文件添加工程,取消优化。这个仿真使用了</font><font face="Calibri">M25P16</font><font face="宋体">仿真模块进行仿真。仿真波形如图:</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="宋体">写使能</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify">擦除指令</p>
<p style="text-indent:21.0000pt; text-align:justify">擦除完成</p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><font face="Calibri">4</font><font face="宋体">)在线逻辑仪波形</font></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">a</font><font face="宋体">、设置引脚时,</font></span></span></span><span style="color:#16a085;"><b><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="font-weight:bold"><font face="宋体">使用的是</font><font face="Calibri">MSPI</font><font face="宋体">引脚,所以注意在</font><font face="Calibri">Process</font><font face="宋体">页面右键选中</font><font face="Calibri">configraion</font><font face="宋体">,如图,在</font><font face="Calibri">Dual-purpose </font><font face="宋体">中选择</font><font face="Calibri">MSPI </font><font face="宋体">作为常规引脚</font></span></span></span></b></span><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="宋体">。否则编译时就会出现如图示错误。</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify">编译错误</p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">b</font><font face="宋体">、建立</font><font face="Calibri">GAO</font><font face="宋体">文件;详细步骤参考论坛大佬的教程。链接如下:</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><a href="https://bbs.eeworld.com.cn/thread-1189515-1-1.html#pid3113128">【国产FPGA高云GW1N-4系列开发板测评】——4、内嵌逻辑分析仪的使用 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)</a></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-size: 10.5pt;"><span style="color: rgb(0, 0, 0);"><font face="Calibri" style="font-family: 宋体;">c</font><font face="宋体" style="font-family: 宋体;">、在线逻辑分析页面,在这个自己犯了一个打错,就是提前把跳线帽跳到</font><font face="Calibri" style="font-family: 宋体;">JTAG</font><font face="宋体" style="font-family: 宋体;">模式,而此时还是使用</font><font face="Calibri" style="font-family: 宋体;">USB</font><font face="宋体" style="font-family: 宋体;">下载,结果出现下载不了程序,并且提示</font><font face="Calibri" style="font-family: 宋体;">code </font><font face="宋体" style="font-family: 宋体;">不匹配。实际上</font><font face="Calibri" style="font-family: 宋体;">GWIN1-4B MINI</font><font face="宋体" style="font-family: 宋体;">开发板已经有</font><font face="Calibri" style="font-family: 宋体;">JTAG</font><font face="宋体" style="font-family: 宋体;">下载,就是使用</font><font face="Calibri" style="font-family: 宋体;">FT232H</font><font face="宋体" style="font-family: 宋体;">芯片来支持</font><font face="Calibri" style="font-family: 宋体;">JTAG</font><font face="宋体" style="font-family: 宋体;">下载模式。这个错误让自己停滞了几天。感谢论坛大佬</font></span></span></span><span class="mentions"><a href="home.php?mod=space&uid=449420" target="_blank">@gs001588</a> </span> <span style="font-size:10.5pt"><span style="font-size: 10.5pt;"><span style="color: rgb(0, 0, 0);"><font face="宋体"><font style="font-family:宋体">提供了帮助</font></font><font face="宋体" style="font-family: 宋体;">。多谢大佬。</font></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">d</font><font face="宋体">、在线逻辑波形由于没有截图就不上传了</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">2</font><font face="宋体">、页写代码编写</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">1</font><font face="宋体">)页写波形图绘制,参考时序绘制</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">2</font><font face="宋体">)根据波形图进行代码编写</font></span></span></span></span></span></p>
<pre>
<code>module flash_pp_ctrl(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire key , //按键输入信号
output reg cs_n , //片选信号
output reg sck , //串行时钟
output reg mosi //主输出从输入数据
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter IDLE = 4'b0001 , //初始状态
WR_EN = 4'b0010 , //写状态
DELAY = 4'b0100 , //等待状态
PP = 4'b1000 ; //页写状态
parameter WR_EN_INST = 8'b0000_0110, //写使能指令
PP_INST = 8'b0000_0010; //页写指令
parameter SECTOR_ADDR = 8'b0000_0000, //扇区地址
PAGE_ADDR = 8'b0000_0100, //页地址
BYTE_ADDR = 8'b0010_0101; //字节地址
parameter NUM_DATA = 8'd100 ; //页写数据个数(0-99)
//reg define
reg cnt_byte ; //字节计数器
reg state ; //状态机状态
reg cnt_clk ; //系统时钟计数器
reg cnt_sck ; //串行时钟计数器
reg cnt_bit ; //比特计数器
reg data ; //页写入数据
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_clk:系统时钟计数器,用以记录单个字节
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_clk <= 5'd0;
else if(state != IDLE)
cnt_clk <= cnt_clk + 1'b1;
//cnt_byte:记录输出字节个数和等待时间
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_byte <= 8'd0;
else if((cnt_clk == 5'd31) && (cnt_byte == NUM_DATA + 8'd9))
cnt_byte <= 8'd0;
else if(cnt_clk == 5'd31)
cnt_byte <= cnt_byte + 1'b1;
//cnt_sck:串行时钟计数器,用以生成串行时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_sck <= 2'd0;
else if((state == WR_EN) && (cnt_byte == 8'd1))
cnt_sck <= cnt_sck + 1'b1;
else if((state == PP) && (cnt_byte >= 8'd5)
&& (cnt_byte <= NUM_DATA + 8'd9 - 1'b1))
cnt_sck <= cnt_sck + 1'b1;
//cs_n:片选信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cs_n <= 1'b1;
else if(key == 1'b1)
cs_n <= 1'b0;
else if((cnt_byte == 8'd2) && (cnt_clk == 5'd31) && (state == WR_EN))
cs_n <= 1'b1;
else if((cnt_byte == 8'd3) && (cnt_clk == 5'd31) && (state == DELAY))
cs_n <= 1'b0;
else if((cnt_byte == NUM_DATA + 8'd9) && (cnt_clk == 5'd31) && (state == PP))
cs_n <= 1'b1;
//sck:输出串行时钟
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sck <= 1'b0;
else if(cnt_sck == 2'd0)
sck <= 1'b0;
else if(cnt_sck == 2'd2)
sck <= 1'b1;
//cnt_bit:高低位对调,控制mosi输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_bit <= 3'd0;
else if(cnt_sck == 2'd2)
cnt_bit <= cnt_bit + 1'b1;
//data:页写入数据
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data <= 8'd0;
else if((cnt_clk == 5'd31) && ((cnt_byte >= 8'd9)
&& (cnt_byte < NUM_DATA + 8'd9 - 1'b1)))
data <= data + 1'b1;
//state:两段式状态机第一段,状态跳转
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
state <= IDLE;
else
case(state)
IDLE: if(key == 1'b1)
state <= WR_EN;
WR_EN: if((cnt_byte == 8'd2) && (cnt_clk == 5'd31))
state <= DELAY;
DELAY: if((cnt_byte == 8'd3) && (cnt_clk == 5'd31))
state <= PP;
PP: if((cnt_byte == NUM_DATA + 8'd9) && (cnt_clk == 5'd31))
state <= IDLE;
default: state <= IDLE;
endcase
//mosi:两段式状态机第二段,逻辑输出
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte== 8'd2))
mosi <= 1'b0;
else if((state == PP) && (cnt_byte == NUM_DATA + 8'd9))
mosi <= 1'b0;
else if((state == WR_EN) && (cnt_byte == 8'd1) && (cnt_sck == 5'd0))
mosi <= WR_EN_INST; //写使能指令
else if((state == PP) && (cnt_byte == 8'd5) && (cnt_sck == 5'd0))
mosi <= PP_INST; //页写指令
else if((state == PP) && (cnt_byte == 8'd6) && (cnt_sck == 5'd0))
mosi <= SECTOR_ADDR; //扇区地址
else if((state == PP) && (cnt_byte == 8'd7) && (cnt_sck == 5'd0))
mosi <= PAGE_ADDR; //页地址
else if((state == PP) && (cnt_byte == 8'd8) && (cnt_sck == 5'd0))
mosi <= BYTE_ADDR; //字节地址
else if((state == PP) && ((cnt_byte >= 8'd9)
&& (cnt_byte <= NUM_DATA + 8'd9 - 1'b1)) && (cnt_sck == 5'd0))
mosi <= data; //页写入数据
endmodule</code></pre>
<p> </p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="Calibri">3</font><font face="宋体">)</font><font face="宋体">在线逻辑图波形</font></span></span></span></span></span></p>
<p style="text-indent:21.0000pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><span style="font-size:10.5000pt"><span style="font-family:宋体"><span style="color:#000000"><font face="宋体">写使能</font></span></span></span></span></span></p>
<p> </p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify">写指令</p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p style="text-indent:21.0000pt; text-align:justify">写地址</p>
<p style="text-indent:21.0000pt; text-align:justify"></p>
<p> </p>
<p> </p>
<p style="text-indent:21.0000pt; text-align:justify"> </p>
<p> </p>
<p> </p>
<p>清晰明了,羡慕会fpga的</p> <p>不错,说干就干,这效率杠杠的呀!</p>
<p>时序图是用啥软件画的,效果很好啊</p>
<p>时序图很专业</p>
gs001588 发表于 2021-12-28 21:38
不错,说干就干,这效率杠杠的呀!
时序图是用啥软件画的,效果很好啊
<p>还是得益于大佬您的帮助啊。使用visio软件画的</p>
Jacktang 发表于 2021-12-29 07:17
时序图很专业
<p>过奖过奖</p>
怀揣少年梦 发表于 2021-12-29 08:12
还是得益于大佬您的帮助啊。使用visio软件画的
<p>赞,赞,评测文章帮助到其他坛友了:)</p>
页:
[1]