基于FPGA的SPI FLASH控制器设计

基于FPGA的SPI FLASH控制器设计

基于FPGA的SPI FLASH控制器设计

1 摘要

在FPGA开发中,“存储”是绕不开的需求——无论是保存硬件配置、存储用户数据,还是固化应用程序,FLASH闪存都是最常用的选择。而SPI协议,作为一种高速、简洁的同步通信总线,几乎是FPGA与FLASH通信的“标配”。今天就带大家从SPI协议,结合W25Q256FV FLASH芯片,梳理FPGA控制器的设计思路。更多源码请关注公众号:搬砖的骡子toonyhe

2 SPI协议概述

2.1 SPI 引脚
SPI(Serial Peripheral Interface),即串行外设接口,是一种高速、全双工、同步的通信总线。它最大的优势的是“简洁”——只需要4根线,就能实现主从设备间的高速通信,极大节约了芯片管脚和PCB布局空间,这也是它被广泛应用的核心原因。所有SPI设备都离不开这四根线,主从设备通过它们建立通信,分工明确、互不干扰:
①MISO:主设备输入,从设备输出(Master Input, Slave Output)——从设备(如FLASH)向主设备(如FPGA)发送数据。

②MOSI:主设备输出,从设备输入(Master Output, Slave Input)——主设备向从设备发送指令、地址或数据。

③SCLK:串行时钟(Serial Clock)——由主设备产生,为数据传输提供时序基准,决定通信速度。

④CS:片选信号(Chip Select)——由主设备控制,用于选择要通信的从设备(低电平有效,默认高电平)。同一SPI总线上可挂多个从设。

在这里插入图片描述

2.2 SPI 四大模式
SPI通信有四种不同的模式,不同的从设备可能在出厂时就已经配置为某种模式。通信的双方必须是工作在同一模式下,所以我们可以对主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来控制我们主设备的通信模式。
mode0:CPOL=0,CPHA=0;
mode1:CPOL=0,CPHA=1;
mode2:CPOL=1,CPHA=0;
mode3:CPOL=1,CPHA=1;
时钟极性CPOL是用来配置SCLK在空闲时,应该处于的状态;时钟相位CPHA用来配置在第几个边沿进行采样。
CPOL=0,表示在空闲状态时,时钟SCLK为低电平。CPOL=1,表示在空闲状态时,时钟SCLK为高电平。CPHA=0,表示数据采样是在第1个边沿。CPHA=1,表示数据采样是在第2个边沿。
CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。

在这里插入图片描述

CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。

在这里插入图片描述

CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。

在这里插入图片描述

CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。

在这里插入图片描述


在设计中选用的Mode 0(CPOL=0,CPHA=0),也是最常用的模式:空闲时SCLK为低电平,数据在SCLK的上升沿被采样(从设备读MOSI数据),在下降沿被发送(从设备向MISO输出数据)。

3 FLASH 存储器

3.1 FLASH的基本结构

在这里插入图片描述


W25Q256FV 由Block0-Block511共512个Block组成,容量大小为51264KB=5126410248bit/1024/1024=256M-bit=32M-Byte。每个Block由Sector0-Sector15共16个Sector组成,每个Sector大小为4KB,由16个Page组成。以第一个Sector为例,第1个Page地址从xx0000h-xx00FF开始,第2个Page地址从xx0100-xx01FF开始,第3个Page地址从xx0200-xx02FF开始,以此类推…,第16个Page地址从xx0F00~xx0FFF开始。每个Page的大小为256个Byte组成,后面会看到Page Programd最大支持256个Byte。

3.2 FLASH 指令
W25Q256FV的指令可以分为指令码后面没有地址和数据、指令码后面只有地址没有数据、指令码后面只有数据没有地址、指令码后面既有地址又有数据的情况。W25Q256FV的标准/双路/四路SPI指令集包含48条基本指令,这些指令完全通过SPI总线进行控制。指令由片选信号CS的下降沿触发启动,通过DI输入端时钟输入的第一个字节为指令码。DIN输入端的数据在时钟上升沿采样,且采用高位优先MSB的传输方式。

(1)指令集表1

在这里插入图片描述


(2)指令集表2

在这里插入图片描述


(3)指令集表3

在这里插入图片描述

3.3 常用指令描述
①写使能指令(06h)
写使能指令将状态寄存器中的写使能锁存WEL位置为1。在执行每一次页编程、四页编程、扇区擦除、块擦除、整片擦除、写状态寄存器以及擦除/编程安全寄存器指令之前,必须先置位WEL位。写使能指令的执行流程如下:将片选信号CS拉低,在时钟CLK的上升沿将指令码“06h”移入数据输入端DIN,之后将片选信号CS拉高。

在这里插入图片描述

②写禁止指令(04h)
写禁止指令将状态寄存器中的写使能锁存WEL位复位为0。写禁止指令的执行流程如下:将片选信号CS拉低,将指令码“04h”移入数据输入端DI,之后将片选信号/CS拉高。

在这里插入图片描述


注意:上电后,以及写状态寄存器、擦除/编程安全寄存器、页编程、四页编程、扇区擦除、块擦除、整片擦除和复位指令执行完成后,WEL位会自动复位。
③状态寄存器 (05h)
读状态寄存器指令允许读取8位状态寄存器。该指令的执行流程如下:将片选信号(/CS)拉低,在时钟(CLK)的上升沿,将对应状态寄存器的指令码移入数据输入端(DI)——状态寄存器1(Status Register-1)对应指令码“05h”、状态寄存器2(Status Register-2)对应指令码“35h”、状态寄存器3(Status Register-3)对应指令码“15h”。

在这里插入图片描述


④ 页编程指令(02h)
页编程指令允许向之前已擦除状态为FFh的存储单元中编程1字节至256字节1页的数据。在器件接收页编程指令之前,必须先执行写使能指令状态寄存器WEL位=1。该指令的启动是先将片选信号CS拉低,然后将指令码“02h”、24位/32位地址A23/A31-A0以及至少1个数据字节依次移入数据输入端D)。在向器件发送数据的整个指令执行期间,必须保持片选信号CS为低电平。

在这里插入图片描述

⑤ 读数据(03h)
读数据指令允许从存储器中顺序读取一个或多个数据字节。该指令的启动流程如下:将片选信号CS拉低,然后将指令码“03h”以及24位地址A23-A0或32位地址A31-A0依次移入数据输入端DI。指令码和地址位在时钟(CLK)的上升沿被锁存。接收完地址后,被寻址存储单元的数据字节会在时钟CLK的下降沿从数据输出端DO移出,且采用高位优先MSB的传输方式。每移出一个数据字节后,地址会自动递增到下一个更高地址,从而实现连续的数据读取。这意味着,只要时钟持续提供,仅需一条指令即可访问整个存储器。将片选信号CS拉高,即完成该指令的执行。

在这里插入图片描述

4 操作流程

1.Read Manufacturer / Device ID (90h),读取厂商ID和设备ID;

2.Write Enable (06h),置位WEL位;

3.Read Status Register-1 (05h),判断WEL位是否置位;

4.Sector Erase (20h),擦除第一个Sector(4KB);

5.Read Status Register-1 (05h),判断Sector Erase是否完成(轮询BUSY位,直到BUSY位为0,表示完成);

6.Write Disable (04h),复位WEL位;

7.Read Status Register-1 (05h),判断WEL是否复位;

8.Write Enable (06h),置位WEL位;

9.Read Status Register-1 (05h),判断WEL位是否置位;

10.Page Program (02h),将1个Page(256个字节)的数据写入flash;

11.Read Status Register-1 (05h),判断.Page Program是否完成(轮询BUSY位,直到BUSY位为0,表示完成);

12.Write Disable (04h),复位WEL位;

13.Read Status Register-1 (05h),判断WEL是否复位;

14.Read Data (03h),读出写入的256个字节。

5 设计实现

本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q256FV。支持3种通信方式,SPI、Dual SPI和Quad SPI。FLASH的存储单元无法写入bit 1,只能写入bit 0,所以写入数据之前要将原来的数据擦除(FFh),遇到写入bit 1的情况不作处理。

5.1 主程序

module flash_top ( input i_rst_n, input i_clk , //50MHz output o_flash_cs , output o_flash_clk, output o_flash_din, input i_flash_dout ); reg [ 3:0] r_cmd_type; reg [ 7:0] r_flash_cmd; reg [23:0] r_falsh_addr; 

Read more

AI绘画R18提示词实战指南:从基础原理到安全实践

快速体验 在开始今天关于 AI绘画R18提示词实战指南:从基础原理到安全实践 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 AI绘画R18提示词实战指南:从基础原理到安全实践 背景痛点分析 1. 伦理风险与合规挑战 在AI绘画领域,R18内容创作面临着多重挑战。平台审核机制日益严格,违规内容可能导致账号封禁甚至法律风险。同时,不同地区对数字内容的法律界定存在差异,开发者需要特别注意合规边界。

Python 实现 AI 图像生成:调用 Stable Diffusion API 完整教程

Python 实现 AI 图像生成:调用 Stable Diffusion API 完整教程

从零开始学习使用 Python 调用 Stable Diffusion API 生成图像,涵盖本地部署、API 调用、ControlNet、图生图等进阶技巧。 1. 技术架构 Python 客户端 Stable Diffusion API 本地部署 SD WebUI / ComfyUI 云端 API Replicate / Stability AI Stable Diffusion 模型 文生图 txt2img 图生图 img2img 局部重绘 inpainting 超分辨率 upscale 输出图像 后处理管道 存储 本地/OSS 2. 图像生成方式对比 50%25%15%10%

系统开发成本为何居高不下:低代码的工程化降本路径

在企业信息系统建设中,开发成本长期处于高位,往往并非源于单一技术选择,而是由需求不确定性、交付周期拉长、重复性开发以及后期维护复杂化等多重因素共同叠加所致。传统定制开发模式在复杂业务场景下,容易陷入人力密集、协同成本高企和工程可控性不足的问题。 低代码并非通过简化操作来“替代”工程能力,而是尝试以模型驱动、自动化生成与结构化配置为核心,重构系统开发与交付的工程路径。在这一框架下,成本的降低更多体现在重复劳动的压缩、交付链条的收敛以及系统演进过程的可控化,而非单纯的开发速度提升。 理解低代码在工程体系中的作用边界与技术前提,是判断其是否具备真实降本能力的关键。 可视化工作流 流程功能 流程功能清单 流程使用示例 系统界面 流程参数设置 流程示例 流程设计(请假申请) 流程设计(主管审批) 流程设计(完整请假流程) 可视化开发:应用构建技术分析 1.组件化设计:模块化与复用 组件化设计是可视化开发的核心基础,通过将界面元素与业务逻辑拆解为独立可组合单元,实现开发效率、可维护性和系统复用性的提升。在实际应用中,组件化不仅涉及前

【无人机源码】低空无人机智能管控、AI 无人机智慧巡检平台,20+AI场景智能识别,赋能低空一网通飞新

【无人机源码】低空无人机智能管控、AI 无人机智慧巡检平台,20+AI场景智能识别,赋能低空一网通飞新

# 空域数智通:县域低空一体化AI巡检平台 ## 源码交付|1+1+X空地一体架构|60+智能算法|县域低空经济落地解决方案 🛰️卫星:BNBJKJK --- ### 平台核心定位:打通低空经济“最后一公里” 在国家-省-市三级低空监管体系下,县域平台承担着**关键落地执行单元**的角色。我们专注于解决县域低空管理“看得见、管得住、用得好”的实践难题,将顶层设计转化为基层可执行、可运营的数字化能力。 --- ### 双核驱动:数字基座+数据智能 **数字孪生基座** - 真实映射县域“场、站、机”等物理设施 - 集成“通、导、监”等数字基础设施 - 构建全域可视、可管、可控的数字空间 **数据智能中枢** - 汇聚空域、