FPGA 通过 SPI 模式读写 SD 卡:实现与移植探索

FPGA以SPI模式读写SD卡,已经下板验证通过。 可移植到任何FPGA之中。

在数字电路设计领域,FPGA(现场可编程门阵列)凭借其灵活性和强大的并行处理能力,成为众多项目的首选。而 SD 卡作为常用的存储介质,实现 FPGA 对其以 SPI 模式的读写,具有广泛的应用前景。今天就来分享一下我在这方面完成的工作,并且已经成功下板验证通过,而且这个方案可移植到任何 FPGA 之中。

SPI 协议与 SD 卡

SPI(Serial Peripheral Interface)是一种高速、全双工、同步的通信总线,常用于微控制器与各种外围设备之间的通信。SD 卡支持 SPI 模式,这为 FPGA 与之交互提供了便利。

在 SPI 模式下,SD 卡有几个关键引脚与 FPGA 连接:

  • CS(Chip Select):片选信号,低电平有效,用于选择特定的 SD 卡。
  • SCK(Serial Clock):时钟信号,用于同步数据传输。
  • MOSI(Master Out Slave In):主机输出从机输入,FPGA 向 SD 卡发送数据。
  • MISO(Master In Slave Out):主机输入从机输出,SD 卡向 FPGA 发送数据。

FPGA 代码实现

下面以 Verilog 语言为例,展示部分关键代码实现。

初始化模块

module sd_card_init ( input wire clk, input wire rst, output reg spi_cs, output reg spi_sck, output reg spi_mosi, input wire spi_miso, output reg init_done ); // 状态机状态定义 typedef enum reg [2:0] { INIT_IDLE = 3'b000, INIT_CMD0 = 3'b001, INIT_CMD8 = 3'b010, INIT_ACMD41 = 3'b011, INIT_WAIT_READY = 3'b100 } sd_init_state; sd_init_state current_state, next_state; // 发送命令的字节数组 reg [7:0] cmd_bytes [0:5]; reg [2:0] byte_index; reg [7:0] current_byte; always @(posedge clk or posedge rst) begin if (rst) begin current_state <= INIT_IDLE; spi_cs <= 1'b1; spi_sck <= 1'b0; spi_mosi <= 1'b0; byte_index <= 3'b000; init_done <= 1'b0; end else begin current_state <= next_state; end end always @(*) begin next_state = current_state; case (current_state) INIT_IDLE: begin spi_cs <= 1'b1; if (!rst) begin next_state = INIT_CMD0; end end INIT_CMD0: begin spi_cs <= 1'b0; // 填充CMD0命令字节 cmd_bytes[0] = 8'h40; cmd_bytes[1] = 8'h00; cmd_bytes[2] = 8'h00; cmd_bytes[3] = 8'h00; cmd_bytes[4] = 8'h00; cmd_bytes[5] = 8'h95; byte_index = 3'b000; current_byte = cmd_bytes[byte_index]; next_state = INIT_CMD8; end INIT_CMD8: begin // 发送CMD8命令及相关字节,类似CMD0处理 //... next_state = INIT_ACMD41; end INIT_ACMD41: begin // 发送ACMD41命令及相关字节,类似CMD0处理 //... next_state = INIT_WAIT_READY; end INIT_WAIT_READY: begin if (spi_miso == 1'b0) begin init_done <= 1'b1; spi_cs <= 1'b1; end end endcase end always @(posedge clk or posedge rst) begin if (rst) begin spi_sck <= 1'b0; end else begin spi_sck <= ~spi_sck; if (spi_sck == 1'b1) begin if (byte_index < 6) begin spi_mosi <= current_byte[7]; current_byte = {current_byte[6:0], 1'b0}; if (current_byte == 8'h00) begin byte_index = byte_index + 1; current_byte = cmd_bytes[byte_index]; end end end end end endmodule

这段代码是 SD 卡初始化模块,使用状态机控制初始化流程。在 INITIDLE 状态等待复位信号释放,然后进入 INITCMD0 状态发送 CMD0 命令,这是让 SD 卡进入空闲状态的关键命令。每个命令由多个字节组成,通过 byteindex 索引和 currentbyte 暂存来逐位发送。之后依次进入 CMD8 和 ACMD41 命令状态,完成一系列初始化操作,最后在 INITWAITREADY 状态等待 SD 卡准备好信号,当接收到准备好信号(spi_miso 为低)时,初始化完成。

读写模块

module sd_card_rw ( input wire clk, input wire rst, input wire init_done, input wire [7:0] write_data, input wire write_en, output reg [7:0] read_data, output reg read_done, output reg spi_cs, output reg spi_sck, output reg spi_mosi, input wire spi_miso ); // 状态机状态定义 typedef enum reg [2:0] { RW_IDLE = 3'b000, RW_CMD17 = 3'b001, RW_CMD24 = 3'b010, RW_READ = 3'b011, RW_WRITE = 3'b100 } sd_rw_state; sd_rw_state current_state, next_state; // 发送命令的字节数组 reg [7:0] cmd_bytes [0:5]; reg [2:0] byte_index; reg [7:0] current_byte; always @(posedge clk or posedge rst) begin if (rst) begin current_state <= RW_IDLE; spi_cs <= 1'b1; spi_sck <= 1'b0; spi_mosi <= 1'b0; byte_index <= 3'b000; read_done <= 1'b0; end else begin current_state <= next_state; end end always @(*) begin next_state = current_state; case (current_state) RW_IDLE: begin spi_cs <= 1'b1; if (init_done) { if (write_en) { next_state = RW_CMD24; } else { next_state = RW_CMD17; } } end RW_CMD17: begin spi_cs <= 1'b0; // 填充CMD17(读命令)字节 cmd_bytes[0] = 8'h51; //...填充其他字节 byte_index = 3'b000; current_byte = cmd_bytes[byte_index]; next_state = RW_READ; end RW_CMD24: begin spi_cs <= 1'b0; // 填充CMD24(写命令)字节 cmd_bytes[0] = 8'h58; //...填充其他字节 byte_index = 3'b000; current_byte = cmd_bytes[byte_index]; next_state = RW_WRITE; end RW_READ: begin // 处理读操作,等待数据令牌,接收数据等 //... if (/* 数据接收完成条件 */) { read_done <= 1'b1; spi_cs <= 1'b1; } end RW_WRITE: begin // 处理写操作,发送数据令牌,发送数据等 //... if (/* 数据发送完成条件 */) { spi_cs <= 1'b1; } end endcase end always @(posedge clk or posedge rst) begin if (rst) { spi_sck <= 1'b0; } else { spi_sck <= ~spi_sck; if (spi_sck == 1'b1) { if (byte_index < 6) { spi_mosi <= current_byte[7]; current_byte = {current_byte[6:0], 1'b0}; if (current_byte == 8'h00) { byte_index = byte_index + 1; current_byte = cmd_bytes[byte_index]; } } // 读数据时接收数据处理 if (current_state == RW_READ && /* 接收数据条件 */) { read_data = {read_data[6:0], spi_miso}; } } } end endmodule

读写模块也是基于状态机工作。在 RWIDLE 状态等待初始化完成,根据 writeen 信号决定进入读命令(CMD17)状态还是写命令(CMD24)状态。在读写状态中,按照 SPI 协议规定,发送命令字节、等待响应、处理数据传输。例如读操作时,等待数据令牌后逐位接收数据并存入 readdata 寄存器,当满足数据接收完成条件时,设置 readdone 信号。

移植性分析

为什么说这个方案可移植到任何 FPGA 呢?首先,Verilog 作为一种硬件描述语言,具有很好的通用性。不同的 FPGA 厂商可能提供不同的开发工具,但 Verilog 代码主体逻辑无需大的改动。其次,SPI 协议是标准的通信协议,与 FPGA 具体型号无关。只要确保 FPGA 有可用的 I/O 引脚用于连接 SD 卡的 SPI 接口,并且时钟资源能够满足 SPI 通信速率要求,就可以轻松移植。

比如,从 Xilinx 的 FPGA 移植到 Altera 的 FPGA,只需要在开发工具中重新分配一下引脚,根据新 FPGA 的特性设置一下时钟频率等参数,核心的 Verilog 代码基本不用修改。

通过上述的代码实现和分析,我们成功实现了 FPGA 以 SPI 模式读写 SD 卡,并且具备良好的移植性,希望能给大家在相关项目开发中带来一些启发。

以上就是本次分享的全部内容啦,欢迎各位在评论区交流讨论。

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

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

相关文章

G-Star 精选开源项目推荐|第四期

本期 G-Star 推荐&#xff0c;主要涵盖 文档协作与知识库管理、网络安全审计、开源字体设计、多模态大模型训练与推理、低代码开发框架、量子计算应用开发 等领域。 G-Star 开源摘星计划&#xff0c;简称 G-Star 计划&#xff0c;是 AtomGit 平台推出的针对开源项目成长全流程的…

Halcon 定位加二位测量找直线

图像&#xff1a;代码&#xff1a;dev_close_window () dev_open_window (0, 0, 512, 512, black, WindowHandle) *加载图像 read_image (Image,//DESKTOP-V21FG2T/Share/2.bmp)threshold(Image,Region, 50, 100) connection(Region, ConnectedRegions) select_shape(Connected…

Thinkphp-Laravel微信小程序的社区后勤报修系统

目录摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理摘要 ThinkPHP-Laravel微信小程序社区后勤报修系统是一款基于Web和移动端的综合性服务平台&#xff0c;旨在为社区居民提供便捷的报修、投诉及后勤管理功能。系统采用ThinkPHP和Laravel双框…

正交电感的频率特性测量

01 正交电感频率特性 空心正交电感两路线圈信号极值偏移方向 初步测量结果 设置扫描范围&#xff0c; 从100kHz 到 200kHz&#xff0c;  这是扫描小型工字型正交电感对应的结果。 他的谐振峰小于 150kHz。  可以看到在 150kHz的时候 两个通道之间有 23dB 的衰减。  这是大型…

ThingsBoard - APP图片更改为彩色(失败)

问题描述 在手机APP中&#xff0c;登录窗口的LOGO图片没有彩色。问题分析 原始资源图片是彩色的&#xff0c;这肯定是代码中做了处理。已知该图片文件名为thingsboard_big_logo.svg。 //\flutter_thingsboard_app\lib\constants\assets_path.dart abstract class ThingsboardIm…

EI会议推荐!早鸟价!2026年先进电子与自动化技术国际学术会议(AEAT 2026)

✔AEAT2026 已上线长春理工大学电子信息工程学院官网 01 重要信息 会议官网&#xff1a;https://www.yanfajia.com/action/p/JLKRKQRB 会议时间&#xff1a;2026年4月24-26日 会议地点&#xff1a;中国长春 截稿日期&#xff1a;2026年2月27日&#xff08;一轮截稿&#x…

用Nginx日志风格复刻《黑客帝国》代码雨:终端里的赛博朋克特效

前言&#xff1a;《黑客帝国》的绿色数字雨是赛博朋克经典符号&#xff0c;也是不少人对“代码之美”的初印象。出于对这个经典画面的喜爱&#xff0c;我决定复刻一款数字雨脚本。 网上现存版本多有痛点&#xff1a;单系统适配、易闪烁乱码、依赖第三方库。因此我用Python内置库…

Thinkphp-Laravel微信小程序积分商城购物系跑腿配送系统_09ok4

目录摘要内容项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理摘要内容 Thinkphp-Laravel微信小程序积分商城购物跑腿配送系统&#xff08;项目代号09ok4&#xff09;是一套基于PHP框架开发的综合性电商解决方案&#xff0c;整合了会员积分、商品交…

网安校招不踩坑!3 类岗位薪资拆解(10-50 万)+ 技能要求,应届生精准匹配指南

网络安全校招&#xff1a;3 类入门岗位薪资 技能要求&#xff0c;清晰对标 2025 年网络安全人才缺口已突破 150 万&#xff0c;北京、深圳等城市企业甚至开出 “应届生年薪 30 万 ” 的高薪抢人。但对高校应届生而言&#xff0c;“岗位类型繁杂、技能要求模糊” 往往成为求职路…

MR2A08A-4Mb 8位I/O并行接口MRAM

在需要高速读写与数据永久保存的工业、汽车及高可靠性系统中&#xff0c;存储器的选择至关重要。MR2A08A-4Mb磁阻随机存取存储器&#xff08;MRAM&#xff09;凭借其SRAM兼容的性能、真正的非易失特性以及无限的读写耐久性&#xff0c;成为替代传统Flash、SRAM或电池备份SRAM&a…

部署CA证书

目录 CA证书 PKI概念 PKI PKI体系能够实现的功能 PKI协议 X.509 对称加密 非对称加密 部署CA证书实验 实验准备&#xff1a;安装AD域 一&#xff0c;添加角色和功能向导 1&#xff0c;“服务器角色”里面&#xff0c;选择“Active Directory证书服务” 2&#xff…

Thinkphp-Laravel电子设备商品商城采购系统的研究与设计

目录摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理摘要 随着电子商务的快速发展&#xff0c;电子设备商品商城的采购系统成为企业提升运营效率的关键工具。本研究基于ThinkPHP和Laravel框架&#xff0c;设计并实现了一套高效、安全的电子设…

【收藏】1536维vs512维:低维嵌入模型如何实现RAG性能翻倍?颠覆认知的技术选型实践

本文分享了MyClone平台将OpenAI的1536维嵌入模型替换为512维Voyage 3.5 Lite的实践。尽管维度降低&#xff0c;但通过Matryoshka Representation Learning等技术创新&#xff0c;实现了存储成本减少66%、检索延迟降低50%、速度提升2倍的效果&#xff0c;同时保持了甚至提升了检…

从脚本小子到高手!黑客自学 5 本必读书,覆盖基础 / 实战 / 社会工程,附电子书

经常会有粉丝朋友私信我&#xff0c;想学黑客技术有什么书籍推荐&#xff0c;今天就给大家安利一波。 想自学黑客&#xff0c;看这五本书就够了 想要自学黑客却没人教怎么办&#xff0c;看完这五本书&#xff0c;你也能成为黑客大佬&#x1f4aa; ✅第一本《黑客攻防:从入门到…

空心正交电感两路线圈信号极值偏移方向

简 介&#xff1a; 摘要&#xff1a;实验研究了空心正交电感测量交变磁场时出现的左右不对称现象。通过对比顺时针和逆时针旋转测量结果&#xff0c;发现两组线圈信号极值存在固定方向的偏移&#xff0c;且该偏移与旋转方向、磁场方位及传感器位置均无关。测试包括改变电磁门方…

2026企业AI Agent规模化落地:四大核心趋势详解,收藏这份从0到1的实战指南

2026年将成企业级AI Agent落地关键拐点&#xff0c;企业从探索转向规模化应用。MCP构建统一连接层&#xff0c;GraphRAG实现精准知识响应&#xff0c;AgentDevOps保障可控可靠&#xff0c;RaaS让价值可衡量。在营销、招聘等场景已形成可复用落地样本&#xff0c;通过连接协议、…

网安工程师狂喜!8 款必备黑客工具 + 安装包,一次全分享,收藏即封神!

网络安全工程师在维护和保护信息系统的安全性方面扮演着至关重要的角色。为了有效地完成这一任务&#xff0c;他们需要掌握并使用多种工具。本文将详细介绍八款网络安全工程师必备的工具&#xff0c;包括Snort、Wireshark、Nmap、Metasploit、Nessus、OpenVAS、Firewall和Proxy…

收藏!AI、ML、DL和NLP的区别与联系,一篇彻底搞懂

文章系统解析了人工智能(AI)、机器学习(ML)、深度学习(DL)和自然语言处理(NLP)的层级关系与区别。ML作为最广泛的概念&#xff0c;是从数据中学习模式的方法&#xff1b;DL是ML的子集&#xff0c;基于多层神经网络实现自动特征学习&#xff1b;NLP则是将ML/DL应用于语言任务的应…

动态加载库:dlopen详解-deepseek

功能&#xff1a;dlopen 用于在运行时打开动态链接库&#xff0c;并返回一个句柄给调用进程。 基本语法&#xff1a;void* dlopen(const char* filename, int flag);&#xff0c;其中 filename 是库文件的路径&#xff0c;flag 是打开模式&#xff08;如 RTLD_NOW 或 RTLD_LAZ…

安川代码移植:基于瑞萨芯片且无PCB的主板原理图探索

安川代码移植的主板原理图 无pcb 采用瑞萨芯片在工业自动化领域&#xff0c;安川的技术一直有着广泛的应用。今天咱来聊聊安川代码移植到基于瑞萨芯片且无PCB设计的主板原理图相关的事儿。 瑞萨芯片的优势 瑞萨芯片在这类应用中有不少亮点。它以高性能、低功耗著称&#xff0c;…