> ## Content Index
> Fetch the complete content index at: https://cms.yufeiran.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# SPI FLASH 读取模块[verilog]
- URL: https://cms.yufeiran.com/spi-flash-du-qu-mo-kuai/
- Published: 2021-03-04T00:22:52.000Z
- Updated: 2026-10-05T14:57:37.000Z
- Author: Feiran Yu
- Tags: 作品, #legacy-import

## 需求分析

在这里实现一个一次读取4Bytes的flash控制器。  
在 [用Nexys4 DDR 制作一台计算机\[1\] 硬件](https://yufeiran.com/yong-nexys4ddr-zhi-zuo-yi-tai-ji-suan-ji-1/?ref=cms.yufeiran.com)里提过，需要一个“硬盘”，用于读取只读数据。

## 原理分析

nexys4ddr 使用的spi flash芯片具体型号是S25FL128S芯片。  
**线路图如下**  

![pic 1](https://yufeiran.com/content/images/2021/03/QQ--20210304162150.png)

### 什么是spi协议

简单起见，仅介绍最基础的，详细的请参考[wiki](https://zh.wikipedia.org/wiki/%E5%BA%8F%E5%88%97%E5%91%A8%E9%82%8A%E4%BB%8B%E9%9D%A2?ref=cms.yufeiran.com)  
spi协议是一种串行总线，即数据用一根线一位一位的传，这里需要用的的有**sck，cs\_n,si,so**四根信号线  
**sck**是时钟线，用来做信号的同步，频率在工作范围内随意  
**cs\_n**是片选信号，"\_n" 的意思是低电平有效，故当cs\_n信号被拉低的时候，这个芯片才开始工作  
**si**是输入到主设备的信号线，flash芯片读取数据的时候需要靠它  
**so**是输入到flash的信号线，flash芯片写入数据的时候需要靠它

### 什么是flash芯片

简单来说，它是一种有一堆可读可写的颗粒（[EEPROM](https://zh.wikipedia.org/wiki/%E9%9B%BB%E5%AD%90%E6%8A%B9%E9%99%A4%E5%BC%8F%E5%8F%AF%E8%A4%87%E5%AF%AB%E5%94%AF%E8%AE%80%E8%A8%98%E6%86%B6%E9%AB%94?ref=cms.yufeiran.com)）和一个[控制器](https://zh.wikipedia.org/wiki/%E9%97%AA%E5%AD%98%E6%8E%A7%E5%88%B6%E5%99%A8?ref=cms.yufeiran.com)组成的，这个控制器封装了许多指令来操作那些颗粒。于是要想使用flash芯片，最主要的是对flash控制器发出正确的指令。  
flash 芯片的结构如下图  

![pic 2](https://yufeiran.com/content/images/2021/03/QQ--20210304164500.png)

  
关于flash芯片的指令，每个厂商有些许不同，但由于有标准化，大多常用的指令都相同，可以参考每种芯片的文档。  
[S25FL128S芯片的文档](https://www.cypress.com/file/448601/download?ref=cms.yufeiran.com)

### 时序

#### flash芯片时序

由于仅仅需要读取数据，我们这里仅介绍用到的唯一一条指令：READ  
根据S25FL128S的文档，我们可以看到读取指令的时序为  

![pic 3](https://yufeiran.com/content/images/2021/03/QQ--20210304165224.png)

  
从图上看，我们要想读取数据，需要做的是  
1.先将cs\_n拉低，  
2.再保持sck在工作范围内，查阅文档可知，READ指令最大工作频率是50MHz，故sck可选的频率在（0，50M\]之间，由于Nexys4 DDR的板载晶振频率是100MHz，于是这里用50MHz会比较好分频，  

![pic 4](https://yufeiran.com/content/images/2021/03/QQ--20210304165930.png)

  
3.然后通过so信号线一位一位的输入指令READ(03H)，读取地址（24位），  
4.最后flash芯片就会通过si信号线一位一位的输出数据

#### wishbone总线读时序

作为一个外设需要连接到总线上，接口需要满足总线的要求。  
这台计算机用的是Wishbone总线,它的时序比较简单，这里介绍下总线读操作的信号  

![pic 5](https://yufeiran.com/content/images/2021/03/QQ--20210305171717.png)

  
简单来说工作的时候需要把STB\_O和CYC\_O同时拉高,地址输入到ADR\_O中，再保持CLK\_I的周期，之后总线就开始等待外设，当外设处理完成信号之后，就将ACK\_I拉高，完成整个传输过程。  
主机在接受完数据后将STB\_O与CYC\_O同时拉低，外设此时便知道整个访问结束，将ACK\_I拉低。

## 设计

### 状态机设计

这部分主要参考了[这篇文章](https://blog.csdn.net/qimoDIY/article/details/86770745?ref=cms.yufeiran.com)  
如图所示  

![pic 6](https://yufeiran.com/content/images/2021/03/-----.png)