首页 » 通讯 » 正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据

正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据

admin 2025-01-21 05:07:06 0

扫一扫用手机浏览

文章目录 [+]

2)摘自《开拓者FPGA开拓指南》关注官方微旗子暗记"大众年夜众号,获取更多资料:正点原子

3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html

正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据 正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据 通讯

第三十九章 SD卡读写测尝尝验

正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据 正点原子开拓者FPGA开拓板资料连载第39章SD卡读写测尝尝验(1)_暗记_数据 通讯
(图片来自网络侵删)

SD存储卡是一种基于半导体快闪影象器的新一代影象设备。
它具有体积小、传输速率快、

支持热插拔等优点,在便携式装置领域得到了广泛的运用,如数码相机、多媒体播放器、条记

本电脑等。
本章我们将利用FPGA开拓板学习如何对SD卡进行读写操作并进行SD卡的读写测试实

验。

本章包括以下几个部分:

39.1 SD卡简介

39.2 实验任务

39.3 硬件设计

39.4 程序设计

39.5 下载验证

SD卡简介

SD卡的英文全称是Secure Digital Card,即安全数字卡(又叫安全数码卡),是在MMC卡

(Multimedia Card,多媒体卡)的根本上发展而来,紧张增加了两个特色:更高的安全性和

更快的读写速率。
SD卡和MMC卡的长度和宽度都是32mm x 24mm,不同的是,SD卡的厚度为2.1mm,

而MMC卡的厚度为1.4mm,SD卡比MMC卡略厚,以容纳更大容量的存贮单元,同时SD卡比MMC卡触

点引脚要多,且在侧面多了一个写保护开关。
SD卡与MMC卡保持着向上兼容,也便是说,MMC卡

可以被新的SD设备存取,兼容性则取决于运用软件,但SD卡却不可以被MMC设备存取。
SD卡和

MMC卡可通过卡片上面的标注进行区分,如下图左侧图片上面标注为“MultiMediaCard”字母

样式的为MMC卡,右侧图片上面标注为“SD”字母样式的为SD卡。

图 39.1.1 MMC外不雅观图(左)和SD卡外不雅观图(右)

上图中右侧图片的SD卡实际上为SDHC卡,SD卡从存储容量上分为3个级别,分别为:SD卡、

SDHC卡(Secure Digital High Capacity,高容量安全数字卡)和SDXC卡(SD eXtended Capacity,

容量扩大化的安全存储卡)。
SD卡在MMC卡的根本上发展而来,利用FAT12/FAT16文件系统,SD

卡采取SD1.0协议规范,该协议规定了SD卡的最大存储容量为2GB;SDHC卡是大容量存储SD卡,

利用FAT32文件系统,SDHC卡采取SD2.0协议规范,该协议规定了SDHC卡的存储容量范围为2GB

至32GB;SDXC卡是新提出的标准,不同于SD卡和SDHC卡利用的FAT文件系统,SDXC卡利用exFAT

文件系统,即扩展FAT文件系统。
SDXC卡采取SD3.0协议规范,该协议规定了SDXC卡的存储容量

范围为32GB至2TB(2048GB),一样平常用于中高端单反相机和高清摄像机。

下表为不同类型的SD卡采取的协议规范、容量等级及支持的文件系统。

表 39.1.1 SD卡的类型、协议规范、容量等级及支持的文件系统

不同协议规范的SD卡有着不同速率等级的表示方法。
在SD1.0协议规范中(现在用的较少),

利用“X”表示不同的速率等级;在SD2.0协议规范中,利用SpeedClass表示不同的速率等级;

SD3.0协议规范利用UHS(Ultra High Speed)表示不同的速率等级。
SD2.0规范中对SD卡的速

度等级划分为普通卡(Class2、Class4、Class6)和高速卡(Class10);SD3.0规范对SD卡的

速率等级划分为UHS速率等级1和3。
不同等级的读写速率和运用如下图所示。

图 39.1.2 SD卡不同速率等级表示法

SD卡共有9个引脚线,可事情在SDIO模式或者SPI模式。
在SDIO模式下,共用到CLK、CMD、

DAT[3:0]六根旗子暗记线;在SPI模式下,共用到CS(SDIO_DAT[3])、CLK(SDIO_CLK)、MISO

(SDIO_DAT[0])、MOSI(SDIO_CMD)四根旗子暗记线。

SD卡接口定义以及各引脚功能解释如图 39.1.3

所示。

图 39.1.3 SD卡接口定义以及各引脚功能解释

市情上除标准SD卡外,还有MicroSD卡(原名TF卡),是一种极眇小的快闪存储器卡,是

由SanDisk(闪迪)公司发明,紧张用于移动手机。
MicroSD卡插入适配器(Adapter)可以转换成SD卡,其操作时序和SD卡是一样的。
MicroSD卡接口定义以及各引脚功能解释如图 39.1.4所

示。

图 39.1.4 MicroSD卡接口定义以及各引脚功能解释

标准SD卡2.0版本中,事情时钟频率可以达到50Mhz,在SDIO模式下采取4位数据位宽,理

论上可以达到200Mbps(50Mx4bit)的传输速率;在SPI模式下采取1位数据位宽,理论上可以

达到50Mbps的传输速率。
因此SD卡在SDIO模式下的传输速率更快,同时其操作时序也更繁芜。

对付利用SD卡读取音乐文件和图片来说,SPI模式下的传输速率已经能够知足我们的需求,因

此我们本章采取SD卡的SPI模式来对SD卡进行读写测试。

SD卡在正常读写操作之前,必须先对SD卡进行初始化,SD卡的初始化过程便是向SD中写入

命令,使其事情在预期的事情模式。
在对SD卡进行读写操作时同样须要先发送写命令和读命令,

因此SD卡的命令格式是学习SD卡的主要内容。
SD卡的命令格式由6个字节组成,发送数据时高

位在前,SD卡的写入命令格式如下图所示:

图 39.1.5 SD卡命令格式

Byte1:命令字的第一个字节为命令号(如CMD0、CMD1等),格式为“0 1 x x x x x x”。

命令号的最高位始终为0,是命令号的起始位;次高位始终为1,是命令号的发送位;低6位为

详细的命令号(如CMD55,8’d55 = 8’b0011_0111,命令号为 0 1 1 1 0 1 1 1 = 0x77)。

Byte2~Byte5:命令参数,有些命令参数是保留位,没有定义参数的内容,保留位应设置

为0。

Byte6:前7位为CRC(循环冗余校验)校验位,末了一位为停滞位0。
SD卡在SPI模式下默

认不开启CRC校验,在SDIO模式下开启CRC校验。
也便是说在SPI模式下,CRC校验位必须要发,但是SD卡会在读到CRC校验位时自动忽略它,以是校验位全部设置为1即可。
须要把稳的是,SD

卡上电默认是SDIO模式,在吸收SD卡返回CMD0的响应命令时,拉低片选CS,进入SPI模式。

以在发送CMD0命令的时候,SD卡处于SDIO模式,须要开启CRC校验。
其余CMD8的CRC校验是始终

启用的,也须要启用CRC校验。
除了这两个命令,其它命令的CRC可以不用做校验。

SD卡的命令分为标准命令(如CMD0)和运用干系命令(如ACMD41)。
ACMD命令是分外命令,

发送方法同标准命令一样,但是在发送运用干系命令之前,必须先发送CMD55命令,见告SD卡

接下来的命令是运用干系命令,而非标准命令。
发送完命令后,SD卡会返回响应命令的信息,

不同的CMD命令会有不同类型的返回值,常用的返回值有R1类型、R3类型和R7类型(R7类型是

CMD8命令专用)。
SD卡的常用命令解释如下表(表 39.1.2)所示。

表 39.1.2 SD卡常用命令解释

SD卡返回类型R1数据格式如下图所示:

图 39.1.6 SD卡返回类型R1数据格式

由上图可知,SD卡返回类型R1格式共返回1个字节,最高位固定为0,其它位分别表示对应

状态的标志,高电平有效。

SD卡返回类型R3数据格式如下图所示:

图 39.1.7 SD卡返回类型R3数据格式

由上图可知,SD卡返回类型R3格式共返回5个字节,首先返回的第一个字节为前面先容的

R1的内容,别的字节为OCR(Operation Conditions Register,操作条件寄存器)寄存器的内

容。

SD卡返回类型R7数据格式如下图所示:

图 39.1.8 SD卡返回类型R7数据格式

由上图可知,SD卡返回类型R7格式共返回5个字节,首先返回的第一个字节为前面先容的

R1的内容,别的字节包含SD卡操作电压信息和校验字节等内容。
个中电压范围是一个比较主要

的参数,其详细内容如下所示:

Bit[11:8]:操作电压反馈

0:未定义

1:2.7V~3.6V

2:低电压

4:保留位

8:保留位

其它:未定义

SD卡在正常读写操作之前,必须先对SD卡进行初始化,使其事情在预期的事情模式。
SD卡

1.0版本协议和2.0版本协议在初始化过程中有差异,只有SD2.0版本协议的SD卡才支持CMD8命

令,以是相应此命令的SD卡可以判断为SD2.0版本协议的卡,否则为SD1.0版本协议的SD卡或者

MMC卡;对付CMD8无相应的情形,可以发送CMD55 + ACMD41命令,如果返回0,则表示SD1.0协

议版本卡初始化成功,如果返回缺点,则确定为MMC卡;在确定为MMC卡后,连续向卡发送CMD1

命令,如果返回0,则MMC卡初始化成功,否则判断为缺点卡。

由于市情上大多采取SD2.0版本协议的SD卡,接下来我们仅先容SD2.0版本协议的初始化流

程,以下提到的SD卡均代表基于SD2.0版本协议的SDHC卡,其详细初始化步骤如下:

1、 SD卡完成上电后,主机FPGA先对从机SD卡发送至少74个以上的同步时钟,在上电同

步期间,片选CS引脚和MOSI引脚必须为高电平(MOSI引脚除发送命令或数据外,其

余时候都为高电平);

2、 拉低片选CS引脚,发送命令CMD0(0x40)复位SD卡,命令发送完成后等待SD卡返回相应数据;

3、 SD卡返回相应数据后,先等待8个时钟周期再拉高片选CS旗子暗记,此时判断返回的相应

数据。
如果返回的数据为复位完成旗子暗记0x01,在吸收返复书息期间片选CS为低电平,

此时SD卡进入SPI模式,并开始进行下一步,如果返回的值为其它值,则重新实行第

2步;

4、 拉低片选CS引脚,发送命令CMD8(0x48)查询SD卡的版本号,只有SD2.0版本的卡才

支持此命令,命令发送完成后等待SD卡返回相应数据;

5、 SD卡返回相应数据后,先等待8个时钟周期再拉高片选CS旗子暗记,此时判断返回的相应

数据。
如果返回的电压范围为4’b0001即2.7V~3.6V,解释此SD卡为2.0版本,进行下一

步,否则重新实行第4步;

6、 拉低片选CS引脚,发送命令CMD55(0x77)见告SD卡下一次发送的命令是运用干系

命令,命令发送完成后等待SD卡返回相应数据;

7、 SD卡返回相应数据后,先等待8个时钟周期再拉高片选CS旗子暗记,此时判断返回的相应

数据。
如果返回的数据为空闲旗子暗记0x01,开始进行下一步,否则重新实行第6步。

8、 拉低片选CS引脚,发送命令ACMD41(0x69)查询SD卡是否初始化完成,命令发送完

成后等待SD卡返回相应数据;

9、 SD卡返回相应数据后,先等待8个时钟周期再拉高片选CS旗子暗记,此时判断返回的相应

数据。
如果返回的数据为0x00,此时初始化完成,否则重新实行第6步。

SD卡上电及复位命令时序如下图所示:

图 39.1.9 SD卡上电及复位命令时序图

至此,SD卡完成了复位以及初始化操作,进入到SPI模式的读写操作。
须要把稳的是:SD

卡在初始化的时候,SPI_CLK的时钟频率不能超过400KHz,在初始化完成之后,再将SPI_CLK的

时钟频率切换至SD卡的最大时钟频率。
只管目前市情上的很多SD卡支持以较快的时钟频率进行

初始化,为了能够兼容更多的SD卡,在SD卡初始化的时候时钟频率不能超过400KHz。

SD卡读写一次的数据量必须为512字节的整数倍,即对SD卡读写操作的最少数据量为512个

字节。
我们可以通过命令CMD16来配置单次读写操作的数据长度,以使每次读写的数据量为

(n512)个字节(n≥1),本次SD卡的读写操作利用SD卡默认配置,即单次读写操作的数据

量为512个字节。

SD卡初始化完成后,即可对SD卡进行读写测试,SD卡的读写测试是先向SD卡中写入数据,

再从SD卡中读出数据,并验证数据的精确性。
SD卡的写操作时序图如下图所示:

图 39.1.10 SD卡写操作时序图

SD卡的写操作流程如下:

1、 拉低片选CS引脚,发送命令CMD24(0x58)读取单个数据块,命令发送完成后等待

SD卡返回相应数据;

2、 SD卡返回精确相应数据0x00后,等待至少8个时钟周期,开始发送数据头0xfe;

3、 发送完数据头0xfe后,接下来开始发送512个字节的数据;

4、 数据发送完成后,发送2个字节的CRC校验数据。
由于SPI模式下不对数据进行CRC校

验,直接发送两个字节的0xff即可;

5、 校验数据发送完成后,等待SD卡相应;

6、 SD卡返回相应数据后会进入写忙状态(MISO引脚为低电平),即此时不许可其它操

作。
当检测到MISO引脚为高电平时,SD卡此时退出写忙状态;

7、 拉高CS引脚,等待8个时钟周期后许可进行其它操作。

SD卡的读操作时序图如下图所示:

图 39.1.11 SD卡读操作时序图

SD卡的读操作流程如下:

1、 拉低片选CS引脚,发送命令CMD17(0x51)读取单个数据块,命令发送完成后等待

SD卡返回相应数据;

2、 SD卡返回精确相应数据0x00后,准备开始解析SD卡返回的数据头0xfe;

3、 解析到数据头0xfe后,接下来吸收SD卡返回的512个字节的数据;

4、 数据解析完成后,接下来吸收两个字节的CRC校验值。
由于SPI模式下不对数据进行

CRC校验,可直接忽略这两个字节;

5、 校验数据吸收完成后,等待8个时钟周期;

6、 拉高片选CS引脚,等待8个时钟周期后许可进行其它操作。

在前面先容的SD卡读写操作中,利用的是SD卡的SPI模式,即采取SPI协议进行读写操作。

SPI和IIC都是芯片上常用的通信协议,SPI比较于IIC具有更高的通信速率,但同时占用更多的

引脚线,接下来我们理解一下SPI的协议及传输时序。

SPI(Serial Peripheral interface)是由摩托罗拉公司定义的一种串行外围设备接口,

是一种高速、全双工、同步的通信总线,只须要四根旗子暗记线即可,节约引脚,同时有利于PCB

的布局。
正是出于这种大略易用的特性,现在越来越多的芯片集成了SPI通信协议,如FLASH、

AD转换器等。

SPI的通信事理比较大略,它以主从办法事情,常日有一个主设备(此处指FPGA)和一个或多个从设备(此处指SD卡)。
SPI通信须要四根线,分别为SPI_CS、SPI_CLK、SPI_MOSI和

SPI_MISO。
个中SPI_CS、SPI_CLK和SPI_MOSI由主机输出给从机,而SPI_MISO由从机输出给主

机。
SPI_CS用于掌握芯片是否当选中,也便是说只有片选旗子暗记有效时(对付SD卡来说是低电平

有效),对芯片的操作才有效;SPI_CLK是由主机产生的同步时钟,用于同步数据;SPI_MOSI

和SPI_MISO是主机发送和吸收的数据脚。

一样平常而言,SPI通信有4种不同的模式,不同的从设备在出厂时被厂家配置为个中一种模式,

模式是不许可用户修正的。
主设备和从设备必须在同一模式下进行通信,否则数据会吸收缺点。

SPI的通信模式是由CPOL(时钟极性)和CPHA(时钟相位)来决定的,四种通信模式如下:

模式0:CPOL = 0,CPHA = 0;

模式1:CPOL = 0,CPHA = 1;

模式2:CPOL = 1,CPHA = 0;

模式3:CPOL = 1,CPHA = 1。

CPOL掌握着SPI_CLK的时钟极性,时钟极性变革如下图所示:

图 39.1.12 SPI_CLK时钟极性

由上图可知,当CPOL = 1时,SPI_CLK在空闲时为高电平,发起通信后的第一个时钟沿为

低落沿;CPOL = 0时,SPI时钟旗子暗记SPI_CLK空闲时为低电平,发起通信后的第一个时钟沿为上

升沿。

CPHA用于掌握数据与时钟的对齐模式,其不同模式下的时序图如下图所示:

图 39.1.13 不同CPHA模式下的时序图

由上图可知,当CPHA = 1时,时钟的第一个变革沿(上升沿或者低落沿)数据开始改变,

那么也就意味着时钟的第2个变革沿(与第一个变革沿相反)锁存数据;当CPHA = 0时,数据

在时钟的第一个变革沿之前就已经改变,并且保持稳定,也就意味着在时钟的第一个变革沿锁

存数据。

对付SD卡的SPI模式而言,采取的SPI的通信模式为模式3,即CPOL = 1,CPHA = 1,在SD

卡2.0版本协议中,SPI_CLK时钟频率可达50Mhz。

以上是SD卡简介部分的全部内容,在这里还须要补充下FAT文件系统的知识。
如果对SD卡

的读写测试像EEPROM一样仅仅是写数据,读数据并验证数据的精确性的话,是不须要FAT文件

系统的。
而SD卡常常被用来在Windows操作系统上存取数据,必须利用Windows操作系统支持的

FAT文件系统才能在电脑上正常利用。

FAT(File Allocation Table,文件分配表)是Windows操作系统所利用的一种文件系统,

它的发展过程经历了FAT12、FAT16、FAT32三个阶段。
FAT文件系统用“簇”作为数据单元,一

个“簇”由一组连续的扇区组成,而一个扇区由512个字节组成。
簇所包含的扇区数必须是2的

整数次幂,其扇区个数最大为64,即32KB(512Byte 64 = 32KB)。
所有的簇从2开始进行编

号,每个簇都有一个自己的地址编号,用户文件和目录都存储在簇中。

FAT文件系统的基本构造依次为:分区勾引记录、文件分配表(FAT表1和FAT表2)、根目

录和数据区。
分区勾引记录:分区勾引记录区常日占用分区的第一个扇区,共512个字节。
包含四部分

内容:BIOS参数记录块BPB(BIOS Parameter Block)、磁盘标志记录表、分区勾引记录代码

区和结束标志0x55AA。

文件分配表(FAT表1和FAT表2):文件在磁盘上以簇为单位存储,但是同一个文件的数据

并不一定完全地存放在磁盘的一个连续的区域内,每每会分成多少簇,FAT表便是记录文件存

储中簇与簇之间连接的信息,这便是文件的链式存储。
对付FAT16文件系统来说,每个簇用16Bit

来表示文件分配表,而对付FAT32文件系统,利用32Bit来表示文件分配表,这是两者之间的最

主要差异。

根目录:根目录是文件或者目录的首簇号。
在FAT32文件系统中,不再对根目录的位置做

硬性规定,可以存储在分区内可寻址的任意簇内。
不过常日根目录是最早建立的(格式化就生

成了)目录表,以是我们看到的情形基本上都是根目录首簇紧邻FAT2,占簇区顺序上的第1个簇

(即2号簇)。

数据区:数据区紧跟在根目录后面,是文件等数据存放的地方,占用大部分的磁盘空间。

实验任务

本节实验任务是利用FPGA开拓板向SD卡指定的扇区地址中写入512个字节的数据,写完后

将数据读出,并验证数据是否精确。

硬件设计

我们的开拓者FPGA开拓板上有一个SD卡插槽,用于插入SD卡,其事理图如图 39.3.1所示:

图 39.3.1 SD卡接口事理图

由上图可知,在SD卡的SPI模式下,只用到了SDIO_D3(SPI_CS)、SDIO_CMD(SPI_MOSI)、

SDIO_SCK(SPI_SCK)和SDIO_D0(SPI_MISO)引脚,而其它两个引脚是在SD卡的SDIO模式下用

到的。

本实验中,各端口旗子暗记的管脚分配如下表所示。

表 39.3.1 SD卡读写测尝尝验管脚分配

程序设计

通过前面先容的SD卡初始化、写操作以及读操作可知,SD卡的这个三个操作是相互独立且

不能同时进行的,因此我们可以将SD卡的初始化、写操作以及读操作分别划分为三个独立的模

块,末了将这三个模块例化在SD卡的掌握器模块中,便于在其它工程项目中利用。
图 39.4.1

是本章实验的系统框图,PLL时钟模块(PLL)为各个模块供应驱动时钟,SD卡测试数据产生模

块产生测试数据写入SD卡,写完后从SD卡中读出数据,终极读写测试结果由LED显示模块通过

掌握LED灯的显示状态来指示。

图 39.4.1 SD卡读写测试系统框图

顶层模块的事理图如下图所示:

图 39.4.2 顶层模块事理图

由上图可知,SD卡测试数据产生模块产生的开始写入旗子暗记(wr_start_en)及数据(wr_data)

连接至SD卡掌握器模块,数据写完后输出开始读出旗子暗记(rd_start_en)即可从SD卡掌握器中

读出数据(rd_data),数据测试的结果error_flag连接至LED显示模块,完成各模块之间的数

据交互。

FPGA顶层模块(top_sd_rw)例化了以下四个模块:PLL时钟模块(pll_clk)、SD卡测试

数据产生模块(data_gen)、SD卡掌握器模块(sd_ctrl_top)和LED显示模块(led_alarm)。

顶层模块(top_sd_rw):顶层模块完成了对其它四个模块的例化,SD卡测试数据产生模

块产生的开始写入旗子暗记及数据连接至SD卡掌握器模块,数据写完后从SD卡掌握器中读出数据,

并验证数据的精确性,将验证的结果连接至LED显示模块。

PLL时钟模块(pll_clk):PLL时钟模块通过调用锁相环(PLL)IP核来实现,统共输出两

个时钟,频率都是50Mhz,但两个时钟相位相差180度。
我们知道,SD卡的SPI通信模式为CPOL=1,

CPHA=1;即SPI_CLK在空闲时为高电平,数据发送是在时钟的第一个边沿,也便是SPI_CLK由高

电平到低电平的跳变,以是数据采集是在上升沿,数据发送是不才降沿。
为了在程序代码中统

一利用上升沿,我们利用两个相位相差180度的时钟来对SD卡进行操作。

SD卡测试数据产生模块(data_gen):SD卡测试数据产生模块产生的开始写入旗子暗记和数据

写入SD卡掌握器模块中,数据写完后从SD卡掌握器中读出数据,并验证数据的精确性,将验证

的结果发送给LED显示模块。

SD卡掌握器模块(sd_ctrl_top):SD卡掌握器模块例化了SD卡初始化模块(sd_init)、

SD卡写数据模块(sd_write)和SD卡读数据模块(sd_read)。
SD卡初始化模块完成对SD卡的

上电初始化操作;SD卡写数据模块完成对SD卡的写操作;SD卡读数据模块完成对SD卡的读操作。

由于这三个模块都操作了SD卡的引脚旗子暗记,且这三个模块在同一韶光内不会同时操作,以是此

模块实现了对其它三个模块的例化以及选择SD卡的引脚连接至个中某一个模块。

LED显示模块(led_alarm):LED显示模块将SD卡测试数据产生模块输出的验证结果值,

通过掌握LED灯的显示状态来指示。

顶层模块的代码如下:

1 module top_sd_rw(

2 input sys_clk , //系统时钟

3 input sys_rst_n , //系统复位,低电平有效

4

5 //SD卡接口

6 input sd_miso , //SD卡SPI串行输入数据旗子暗记

7 output sd_clk , //SD卡SPI时钟旗子暗记

8 output sd_cs , //SD卡SPI片选旗子暗记

9 output sd_mosi , //SD卡SPI串行输出数据旗子暗记

10 //LED

11 output [3:0] led //LED灯

12 );

13

14 //wire define

15 wire clk_ref ;

16 wire clk_ref_180deg ;

17 wire rst_n ;

18 wire locked ;

19

20 wire wr_start_en ; //开始写SD卡数据旗子暗记

21 wire [31:0] wr_sec_addr ; //写数据扇区地址

22 wire [15:0] wr_data ; //写数据

23 wire rd_start_en ; //开始写SD卡数据旗子暗记

24 wire [31:0] rd_sec_addr ; //读数据扇区地址

25 wire error_flag ; //SD卡读写缺点的标志

26

27 wire wr_busy ; //写数据忙旗子暗记

28 wire wr_req ; //写数据要求旗子暗记

29 wire rd_busy ; //读忙旗子暗记

30 wire rd_val_en ; //数据读取有效使能旗子暗记

31 wire [15:0] rd_val_data ; //读数据

32 wire sd_init_done ; //SD卡初始化完成旗子暗记

33

34 //

35 // main code

36 //

37

38 assign rst_n = sys_rst_n & locked;

39

40 //锁相环

41 pll_clk u_pll_clk(

42 .areset (1'b0 ),

43 .inclk0 (sys_clk ),

44 .c0 (clk_ref ),

45 .c1 (clk_ref_180deg),

46 .locked (locked )

47 );

48

49 //产生SD卡测试数据

50 data_gen u_data_gen(

51 .clk (clk_ref),

52 .rst_n (rst_n),

53 .sd_init_done (sd_init_done),

54 .wr_busy (wr_busy),

55 .wr_req (wr_req),

56 .wr_start_en (wr_start_en),

57 .wr_sec_addr (wr_sec_addr),

58 .wr_data (wr_data),

59 .rd_val_en (rd_val_en),

60 .rd_val_data (rd_val_data),

61 .rd_start_en (rd_start_en),

62 .rd_sec_addr (rd_sec_addr),

63 .error_flag (error_flag)

64 );

65

66 //SD卡顶层掌握模块

67 sd_ctrl_top u_sd_ctrl_top(

68 .clk_ref (clk_ref),

69 .clk_ref_180deg (clk_ref_180deg),

70 .rst_n (rst_n),

71 //SD卡接口

72 .sd_miso (sd_miso),

73 .sd_clk (sd_clk),

74 .sd_cs (sd_cs),

75 .sd_mosi (sd_mosi),

76 //用户写SD卡接口

77 .wr_start_en (wr_start_en),

78 .wr_sec_addr (wr_sec_addr),

79 .wr_data (wr_data),

80 .wr_busy (wr_busy),

81 .wr_req (wr_req),

82 //用户读SD卡接口

83 .rd_start_en (rd_start_en),

84 .rd_sec_addr (rd_sec_addr),

85 .rd_busy (rd_busy),

86 .rd_val_en (rd_val_en),

87 .rd_val_data (rd_val_data),

88

89 .sd_init_done (sd_init_done)

90 );

91

92 //led警示

93 led_alarm #(

94 .L_TIME (25'd25_000_000)

95 )

96 u_led_alarm(

97 .clk (clk_ref),

98 .rst_n (rst_n),

99 .led (led),

100 .error_flag (error_flag)

101 );

102

103 endmodule

SD卡掌握器模块输出的sd_init_done(SD卡初始化完成旗子暗记)连接至SD卡测试数据产生模

块,只有在SD卡初始化完成之后(sd_init_done为高电平),才能对SD卡进行读写测试。
SD卡

掌握器模块将SD卡的初始化以及读写操作封装成方便用户调用的接口,SD卡测试数据产生模块

只需对SD卡掌握器模块的用户接口进行操作即可完成对SD卡的读写操作。

在代码的第94行定义了一个参数(L_TIME),用于在读写测试缺点时掌握LED闪烁的韶光,

其单位是1个时钟周期。
由于输入的时钟频率为50Mhz,周期为20ns,以是20 25'd25_000_000

= 500ms,因此LED灯在读写缺点时每500ms闪烁一次。

SD卡掌握器模块的代码如下:

1 module sd_ctrl_top(

2 input clk_ref , //时钟旗子暗记

3 input clk_ref_180deg, //时钟旗子暗记,与clk_ref相位相差180度

4 input rst_n , //复位旗子暗记,低电平有效

5 //SD卡接口

6 input sd_miso , //SD卡SPI串行输入数据旗子暗记

7 output sd_clk , //SD卡SPI时钟旗子暗记

8 output reg sd_cs , //SD卡SPI片选旗子暗记

9 output reg sd_mosi , //SD卡SPI串行输出数据旗子暗记

10 //用户写SD卡接口

11 input wr_start_en , //开始写SD卡数据旗子暗记

12 input [31:0] wr_sec_addr , //写数据扇区地址

13 input [15:0] wr_data , //写数据

14 output wr_busy , //写数据忙旗子暗记

15 output wr_req , //写数据要求旗子暗记

16 //用户读SD卡接口

17 input rd_start_en , //开始读SD卡数据旗子暗记

18 input [31:0] rd_sec_addr , //读数据扇区地址

19 output rd_busy , //读数据忙旗子暗记

20 output rd_val_en , //读数据有效旗子暗记

21 output [15:0] rd_val_data , //读数据

22

23 output sd_init_done //SD卡初始化完成旗子暗记

24 );

25

26 //wire define

27 wire init_sd_clk ; //初始化SD卡时的低速时钟

28 wire init_sd_cs ; //初始化模块SD片选旗子暗记

29 wire init_sd_mosi ; //初始化模块SD数据输出旗子暗记

30 wire wr_sd_cs ; //写数据模块SD片选旗子暗记

31 wire wr_sd_mosi ; //写数据模块SD数据输出旗子暗记

32 wire rd_sd_cs ; //读数据模块SD片选旗子暗记

33 wire rd_sd_mosi ; //读数据模块SD数据输出旗子暗记

34

35 //

36 // main code

37 //

38

39 //SD卡的SPI_CLK

40 assign sd_clk = (sd_init_done==1'b0) ? init_sd_clk : clk_ref_180deg;

41

42 //SD卡接口旗子暗记选择

43 always @() begin

44 //SD卡初始化完成之前,端口旗子暗记和初始化模块旗子暗记相连

45 if(sd_init_done == 1'b0) begin

46 sd_cs = init_sd_cs;

47 sd_mosi = init_sd_mosi;

48 end

49 else if(wr_busy) begin

50 sd_cs = wr_sd_cs;

51 sd_mosi = wr_sd_mosi;

52 end

53 else if(rd_busy) begin

54 sd_cs = rd_sd_cs;

55 sd_mosi = rd_sd_mosi;

56 end

57 else begin

58 sd_cs = 1'b1;

59 sd_mosi = 1'b1;

60 end

61 end

62

63 //SD卡初始化

64 sd_init u_sd_init(

65 .clk_ref (clk_ref),

66 .rst_n (rst_n),

67

68 .sd_miso (sd_miso),

69 .sd_clk (init_sd_clk),

70 .sd_cs (init_sd_cs),

71 .sd_mosi (init_sd_mosi),

72

73 .sd_init_done (sd_init_done)

74 );

75

76 //SD卡写数据

77 sd_write u_sd_write(

78 .clk_ref (clk_ref),

79 .clk_ref_180deg (clk_ref_180deg),

80 .rst_n (rst_n),

81

82 .sd_miso (sd_miso),

83 .sd_cs (wr_sd_cs),

84 .sd_mosi (wr_sd_mosi),

85 //SD卡初始化完成之后相应写操作

86 .wr_start_en (wr_start_en & sd_init_done),

87 .wr_sec_addr (wr_sec_addr),

88 .wr_data (wr_data),

89 .wr_busy (wr_busy),

90 .wr_req (wr_req)

91 );

92

93 //SD卡读数据

94 sd_read u_sd_read(

95 .clk_ref (clk_ref),

96 .clk_ref_180deg (clk_ref_180deg),

97 .rst_n (rst_n),

98

99 .sd_miso (sd_miso),

100 .sd_cs (rd_sd_cs),

101 .sd_mosi (rd_sd_mosi),

102 //SD卡初始化完成之后相应读操作

103 .rd_start_en (rd_start_en & sd_init_done),

104 .rd_sec_addr (rd_sec_addr),

105 .rd_busy (rd_busy),

106 .rd_val_en (rd_val_en),

107 .rd_val_data (rd_val_data)

108 );

109

110 endmodule

SD卡掌握器模块例化了SD卡初始化模块(sd_init)、SD卡写数据模块(sd_write)和SD

卡读数据模块(sd_read)。
由于这三个模块都驱动着SD卡的引脚,因此在代码的第42行开始

的always块中,用于选择哪一个模块连接至SD卡的引脚。
在代码的第40行,init_sd_clk用于

初始化SD卡时供应较慢的时钟,在SD卡初始化完成之后,再将较快的时钟clk_ref_180deg赋值

给sd_clk。
sd_clk从上电之后,是一贯都有时钟的,而我们在前面说过SPI_CLK的时钟在空闲

时为高电平或者低电平。
事实上,为了简化设计,sd_clk在空闲时供应时钟也是可以的,其是

否有效紧张由片选旗子暗记来掌握。

在这里紧张先容下SD卡掌握器模块的利用方法。
当外部须要对SD卡进行读写操作时,首先

要判断sd_init_done(SD卡初始化完成)旗子暗记,该旗子暗记拉高之后才能对SD卡进行读写操作;在

对SD卡进行写操作时,只需给出wr_start_en(开始写SD卡数据旗子暗记)和wr_sec_addr(写数据

扇区地址),此时SD卡掌握器模块会拉高wr_busy旗子暗记,开始对SD卡发起写入命令;在命令发

起成功后SD卡掌握器模块会输出wr_req(写数据要求)旗子暗记,此时我们给出wr_data(写数据)

即可将数据写入SD卡中;待所有数据写入完成后,wr_busy旗子暗记拉低,即可再次发起读写操作。

SD卡的读操作是给出rd_start_en(rd_start_en)和rd_sec_addr(读数据扇区地址),此时

SD卡掌握器会拉高rd_busy(读数据忙)旗子暗记,开始对SD卡发起读出命令;在命令发起成功后

SD卡掌握器模块会输出rd_val_en(读数据有效)旗子暗记和rd_val_data(读数据),待所有数据

读完之后,拉低rd_busy旗子暗记。
须要把稳的是,SD卡单次写入和读出的数据量为512个字节,因

为接口封装为16位数据,以是单次读写操作会有256个16位数据。

SD卡初始化模块完成对SD卡的上电初始化操作,我们在SD卡的简介部分已经详细的先容了

SD卡的初始化流程,我们只须要按照SD卡的初始化步骤即可完成SD卡的初始化。
由SD卡的初始

化流程可知,其步骤非常适宜状态机编写,其状态跳转图如图 39.4.3所示。

图 39.4.3 SD卡初始化状态跳转图

由上图可知,我们把SD卡初始化过程定义为7个状态,分别为st_idle(初始状态)、

st_send_cmd0(发送软件复位命令)、st_wait_cmd0(等待SD卡相应)、st_send_cmd8(发送

CMD8命令)、st_send_cmd55(发送CMD55命令)、st_send_acmd41(发送ACMD41命令)以及

st_init_done(SD卡初始化完成)。
由于SD卡的初始化只须要上电后实行一次,以是在初始化

完成之后,状态机一贯处于st_init_done状态。

SD卡初始化模块的部分代码如下所示:

112 //吸收sd卡返回的相应数据

113 //在div_clk_180deg(sd_clk)的上升沿锁存数据

114 always @(posedge div_clk_180deg or negedge rst_n) begin

115 if(!rst_n) begin

116 res_en <= 1'b0;

117 res_data <= 48'd0;

118 res_flag <= 1'b0;

119 res_bit_cnt <= 6'd0;

120 end

121 else begin

122 //sd_miso = 0 开始吸收相应数据

123 if(sd_miso == 1'b0 && res_flag == 1'b0) begin

124 res_flag <= 1'b1;

125 res_data <= {res_data[46:0],sd_miso};

126 res_bit_cnt <= res_bit_cnt + 6'd1;

127 res_en <= 1'b0;

128 end

129 else if(res_flag) begin

130 //R1返回1个字节,R3 R7返回5个字节

131 //在这里统一按照6个字节来吸收,多出的1个字节为NOP(8个时钟周期的延时)

132 res_data <= {res_data[46:0],sd_miso};

133 res_bit_cnt <= res_bit_cnt + 6'd1;

134 if(res_bit_cnt == 6'd47) begin

135 res_flag <= 1'b0;

136 res_bit_cnt <= 6'd0;

137 res_en <= 1'b1;

138 end

139 end

140 else

141 res_en <= 1'b0;

142 end

143 end

标签:

相关文章

技能|电脑无法通电怎么解决_戴尔_电脑

如果按下电源按钮后戴尔打算机无法打开,不通电,请按照以下步骤打消故障。视频加载中...01检讨电源线、互换适配器与外设首先检讨电源...

通讯 2025-01-24 阅读1 评论0