最近学了野火FPGA基于SPI协议的Flash驱动控制,在连续写的实验中,有两种方式实现
如下图 (在野火FPGA Verilog实战指南截的图)
在野火的教学视频里,只教了第一种实现方式。所以我想自己用方式2实现,顺便当成练习题哈!
完整工程再下面的链接里,需要的可以下载查看。
链接:https://pan.baidu.com/s/1RRtb9yo2tdnQK9RvLP-odw
提取码:j1dn
这是系统框图
综合出来的RTL视图和上面系统框图一致
由于绘制的时序图太大了,截图不了,这里只放用到的变量
(需要看完整的,可以下载前面放置的链接内容)
仿真:我这里传给fifo 599个数据,内容是00H~63H循环6组,最后一组为00H~62H。
这样一共需要3页(0,1,2) ,最后一页87个数据。(2*256+87 = 599)
1、仿真结果图 , 可以看到mosi_flag 只进行了3次跳变,说明共执行了3次页写操作。
前面这么长的时间是fifo在接收uart_rx传过来的数据。接收完毕后,才把fifo里缓存的数据写入flash中。
注意点:我这里设置了一个1s的计数器,每遇到一个pi_flag,这个计数器会归0,从新计数,直到两个相邻的pi_flag时间间隔超过了1s,这样表示串口发送数据完毕。经过计算,每个数据帧包括10bit,在9600波特率下,bit和bit之间的间隔时间为 1/波特率,我这里波特率是9600 ,所以间隔是104160ns,而完成一帧数据的发送需要104160ns*10 ,所以我这里选择1s 是完全足够,不管你选择更慢的波特率都是适用的。
2、这是第0页的开头部分,可以看到仿真和实际想要的结果是一致的
3、这是第0页的结尾部分,可以看到当cnt_byte = 8 + 256 = 264 时,写入最后一位数据,即第256个数据,由上面写入fifo的数据内容可知是55,这里仿真出来的结果也一致。并且当第0页内容写完后,cs信号也失效了,和我们想要的结果一致。
4、 这是第0页结束后,CS片选信号失效期间,会开启3ms的计数,当计数结束后,会再次拉高mosi_flag,进行地址的换页,开始新的一页数据写入。
疑惑:有小伙伴可能不知道为什么这里定时3ms
解答:我们找到这个flash对应的数据手册,找到页写操作,可以看到,页写操作是在tpp时间内开始执行的,提示我们看AC特性
在AC特性表中,我们可以看到这个Tpp最大值就是3ms,为确保页写操作有足够时间,所以我这里设置为3ms
5、这是第1页的开头部分,可以看到地址进行了页+1操作,并且换页后,写入的数据正是写入fifo的第257个数据56。
6、这是第1页结束,第2页开头部分,可以看到和前面换页结果一样。
7、最后来看下最后一个数据的写入 ,可以看到第599个数据正是我们输入的98 (62H),并且经过一定延时后,CS信号也失效了。符合我们的预期结果。
上板验证
先对flash进行全擦除,然后烧录这个sof文件,用串口调试助手发送599个数据,再烧录读flash程序,可以看到读出601个数据, 其中第600位和601位是FF,并且其他数据和发送的一样,符合结果。
个人的一些总结:
在一开始做这个的时候,总是不能像野火小哥那样,一开始就可以较完整的画出时序图,还是得经过大量的仿真,修改程序,才可以实现功能,然后才画出得时序图。0.0