FPGA 外挂的硬盘主要是 SATA 和 NVMe 协议盘,应用 SATA 盘与 NVMe 盘的相关特征对比如下;FPGA 实现 SATA 和 NVMe 协议主要是借助 SerDes 实现物理层。
| 特征类型 | SATA 盘 | NVMe 盘 |
|---|---|---|
| 热插拔 | 支持 | 不支持 |
| 双工 | 半双工 | 全双工 |
| 速率 | Gen1:1.5Gbps(150MB/S) Gen2:3.0Gbps(300MB/S) Gen3:6.0Gbps(600MB/S) | PCIe Gen2 x4 : 2GB/S PCIe Gen3 x4 : 4GB/S |
| gt_clock | 150MHz | 100Mhz |
| lane 数 | 1 对 | 4 对(最大 4,可 1,2,4) |
| 多 sector 读写顺序 | 按指令的扇区顺序进行 | 写:按指令的扇区顺序进行 读:page 内按扇区顺序进行,page 间可能不按 page 顺序读 |
主要参考:《Serial ATA specifications》,《ATA8-ACS》
一、SATA 介绍
SATA 是 Serial ATA(Serial Advanced Technology Attachment)串行 ATA,由 Intel、IBM、Dell、APT、Maxtor 和 Seagate 公司共同提出的硬盘接口规范。
1.1、SATA 硬盘
目前常用的 SATA 接口为 7 针数据接口和 15 针电源接口。其接口包含数据接口和电源接口。
数据接口:1 对收发差分信号和 GND,host 是硬盘读写控制器(FPGA 板卡/电脑),device 就是 SATA 硬盘,它们之间用两对差分对连接,其中 (SATA_A+, SATA_A-) 差分对是 host 发送、device 接收,(SATA_B+, SATA_B-) 差分对是 device 发送、host 接收。
电源接口定义如下:(2.5 寸硬盘只需 5V 供电)
1.2、FPGA 开发 SATA 硬盘
基于 FPGA 开发 SATA 硬盘的框架如下:
SATA 协议主要包含:物理层 (Physical Layer, PHY)、链路层 (Link Layer)、传输层 (Transport Layer)、应用层/命令层 (Command Layer)。
物理层的串行差分信号对连接 SATA device 和 FPGA SerDes,与链路层之间传输并行信号。物理层的主要功能:时钟恢复、串并转换、字节对齐(ALIGN 原语)、OOB 建链。
链路层主要实现:8B/10B、原语封装和检测、加扰/解扰、CRC 生成和检测、流控。
传输层主要实现:封装/解封 FIS。
应用层/命令层:主要涉及发起 SATA 设备信息查询 Identify 命令、读数据请求命令、写数据请求命令。
数据/控制的流程如下:
二、物理层
物理层的主要功能:时钟恢复、串并转换、字节对齐(ALIGN 原语),FPGA 侧主要借助 SerDes 实现。此外,物理层还有一项重要功能 OOB 的产生与检测,当 OOB 功能实现后,FPGA 开发 SATA 硬盘的工作完成了近 1/3 左右。
OOB(Out of Band signals)带外信号,用于在正常的通信链路建立之前进行 SATA 设备识别,完成链路建立(复位、初始化/速率协商、建链)。OOB 只用于识别硬盘是否存在,不进行数据传输,所以对于正常的数据传输信号(in-band)来说叫带外信号,通过 PHY 层直接控制差分线路(TXP/TXN)将差分对驱动到相同的公共电压,即不对应逻辑 0 也不对应逻辑 1。
差分线电平不同(逻辑 0 或逻辑 1)为 SIGNAL,差分线电平相同为 NOSIGNAL。OOB 信号是通过物理层发送的特定电压脉冲序列(Burst),然后是一段静默时间,主要包括下表 3 种;通过 OOB 信号时间及间隔约定,保证了收发双方即便在不同速率也可以收发,便于建链及速率协商。
| OOB 类型 | 发起方 | 用途 | 描述 |
|---|---|---|---|
| COMRESET | Host | 复位 | 用于复位设备(保证了热插拔),表示建链开始。 |
| COMINIT | Device | 响应 COMRESET | 响应 Host 的 COMRESET,重新连接开始信号。 持续发送 6 个 SIGNAL,每个 SIGNAL 持续 106ns,相邻两个 SIGNAL 间持续 320ns 的 NOSIGNAL。 |
| COMWAKE | Host/Device | 建链 | 向对方表示:已准备好建立链路。 持续发送 6 个 SIGNAL,每个 SIGNAL 持续 106ns,相邻两个 SIGNAL 间持续 106ns 的 NOSIGNAL。 |
链路初始化示例过程时序图和交互图如下所示:(通过 OOB handshake 及原语对齐,host 与 device 可以协商速率为 Gen x 做后续数据传输)
① 系统上电后/热插拔后,Host 向 Device 发送 COMRESET 信号,等待对方回复 COMINIT 信号;在收到 COMINIT 信号前,持续发送 COMRESET(即支持热插拔);
② 当 Device 检测到 Host 发送的 COMRESET 信号,会响应一个 COMINIT 信号;如果 Device 晚启动于 Host,即便没收到 COMRESET 信号,Device 也发送 COMINIT 信号;
③ 当 Host 检测到 Device 发来的 COMINIT 信号后,Host 会进行校准,并在校准完成后发出 COMWAKE 信号;
④ 当 Device 检测到 COMWAKE 信号,并校准,发送长度为 6 的 COMWAKE;并以其协议支持的最高速率进行对齐 (ALIGN) 原语的不断发送,当对齐原语持续发送 54.6us,而没有接收到 Host 发送过来的 ALIGN 后,进行降速发送 ALIGN,依旧是 54.6us,直至最低速度仍无法接收到 Host 的 ALIGN 后,设备将进入错误状态;
⑤ 当 Host 检测到 Device 发送的 COMWAKE 信号后,Host 将以最低速度传输 D10.2(0101010101...这样 0 和 1 交替的波形);同时,Host 锁定 Device 发送的对齐原语,并以相同的速率将对齐原语发送给 Device。Host 应在检测到 COMWAKE 信号释放后的 873.8us 内检测到第一个对齐原语 ALIGN,否则 Host 将重新启动上电序列。
⑥ 当 Device 锁定到对齐原语序列后,发送 SYNC 原语,指示做好普通操作的准备
⑦ 当 Host 接收到三个连续的 non-ALIGN 原语,通信链路正式建立完成;可准备收发 FIS。
⑧ 链路建立好后,双方都在互发 SYNC 原语;等待正常数据通信。
Device 与 Host 连接是首先从 Device 支持的最高速开始的,如果最高速不满足则用较低速率再次匹配,直到最低速率也不能匹配后 Device 将进入 error 状态; 换速等待时间为 54.6us(2048 个 ALIGN DWORD 传输时间)。
下图为借鉴的 SATA 协议分析仪抓到的建链 Trace:
三、链路层
SATA 链路层在 Host 与 SATA 盘间的通信中负责数据帧(FIS)的封装与传输控制,通过使用控制符(如 SYNC、ALIGN)来维持链路稳定,并通过 CRC 检测错误等。链路层主要对接收的 FIS/物理层的并行数据实现如下操作:8B/10B、原语封装和检测、加扰/解扰、CRC 生成和检测。
8B/10B 编码、加扰/解扰、CRC 生成和检测在之前的文章已介绍,这里不再赘述。SATA 协议中的 CRC、加/解扰的多项式如下:
链路层的帧结构如下:各类原语、帧结构(SOF、FIS、CRC、EOF、流控原语、对齐原语)
接下来逐步介绍该图中相关部分。
3.1、原语
上述建链过程中有原语的使用。SATA 协议中的原语以 DW(4 字节)中的低字节为标志,表示不同功能的原语。K28.5 表示该 DW 为 ALIGN 原语,K28.3 表示其他功能原语,SATA 协议采用 ALIGN 原语进行字节对齐。是否为 K 码在 FPGA 中通过相关标志位进行表示。
| 类型 | DW 内容 | K 码标志 | 含义 |
|---|---|---|---|
| ALIGN | 7B4A4ABC | 是 (K28.5) | 字节对齐 |
| CONT | 9999AA7C | 是 (K28.3) | 重复原语加扰/解扰 |
| SYNC | B5B5957C | 是 (K28.3) | 空闲 (不传输 FIS) |
| R_RDY | 4A4A957C | 是 (K28.3) | 准备好接收 FIS |
| R_IP | 5555B57C | 是 (K28.3) | 正在接收 FIS |
| R_OK | 3535B57C | 是 (K28.3) | 接收 FIS 成功 |
| R_ERR | 5656B57C | 是 (K28.3) | 接收 FIS 出错 |
| X_RDY | 5757B57C | 是 (K28.3) | 准备好发送 FIS |
| SOF | 3737B57C | 是 (K28.3) | 发送 FIS 开头 |
| EOF | D5D5B57C | 是 (K28.3) | 发送 FIS 结尾 |
| WTRM | 5858B57C | 是 (K28.3) | 发送 FIS 结束 |
| HOLD | D5D5AA7C | 是 (K28.3) | 流控 |
| HOLDA | 9595AA7C | 是 (K28.3) | 流控 |
| DIAL-TONE | 4A4A4A4A | 否 | 链路初始化时使用 |
| DATA | XXXXXXXX | 否 | FIS 数据或垃圾数据 |
链路初始化所使用的 DIAL-TONE 的首 byte 并不是 K,不是原语。在链路初始化前遇到的的 0x4A4A4A4A 为 DIAL-TONE,在链路初始化后的 0x4A4A4A4A 为普通数据。
在链路初始化过程中使用 ALIGN 原语进行速率协商,ALIGN 原语采用 K28.5,其它原语采用 K28.3;物理层接收方以此判断是否处于一个 10bit 的边界,进而识别字节边界。
收发两端时钟频率存在误差,在遇到 ALIGN 后的一段时间内,接收方仍能正确地界定 10bit 的边界,但是时间足够长后,还是会丢失边界,因此 SATA 要求双方都周期性地发送 ALIGN 原语,ALIGN 插入机制:
SATA 规范规定每最多发送 256 个 DW 至少插入 2 个连续的 ALIGN 原语。
链路初始化后,ALIGN 插入机制便要启用,无论当前在发送的是原语还是数据。在发送方,插入 ALIGN 的工作由链路层完成;在接收方,用 ALIGN 来界定 10bit 边界的工作由物理层完成。链路层也会收到 ALIGN 原语,直接忽略即可。
不能因为要插入 ALIGN 原语,就替换掉当前想要发送的 FIS 数据、SOF 原语、EOF 原语。举例如下(其中"DATA"是 FIS 数据 dword),比如在要发送 EOF 时刚好需要插入 2 个连续的 ALIGN 原语,不能把 EOF 替代掉,只能是推迟发送 EOF,否则接收方将无法界定 FIS 的结尾。
// 插入 ALIGN 举例 插入 ALIGN 前 : X_RDY X_RDY SOF DATA DATA DATA DATA DATA EOF WTRM WTRM WTRM ... 插入 ALIGN 后 : X_RDY X_RDY SOF DATA DATA DATA DATA DATA ALIGN ALIGN EOF WTRM WTRM WTRM,...
3.2、FIS 数据包结构
除了 ALIGN 和 CONT 原语外,其它原语都是为了控制 FIS(SATA 协议的传输层包)收发过程。FIS 数据帧的类型如下:常用的类型为 0x27、0x34、0x39、0x46。
| FIS Type | FIS ID | Discription | Size |
|---|---|---|---|
| H2D | 27h | Send command to drive | 5 DWs |
| D2H | 34h | Responds status to host | 5 DWs |
| DMA Activate | 39h | Activate a DMA data transfer | 1 DW |
| DATA | 46h | Data packet | 2~2049DWs |
不同的类型具有不同的帧结构,每种帧结构至少含有 1DW 的帧头,最长的数据帧为 1DW+N DW,N 最大为 2048。
以下为 DMA 读硬盘的 SATA 协议分析仪抓取的过程:DMA 读请求命令、DMA 读数据命令、状态响应命令、源语状态。
3.2.1、Host 的请求命令 FIS
比如 0x27 帧的结构如下:共 5DW,host 向 device 发送,常用于获取设备信息 identify 命令,数据写请求命令,数据读命令请求。
发送 identify 命令:00EC8027 00000000 00000000 00000000 00000000
发送 DMA 写数据请求命令:0x00358027, 0xE0xxxxxx, 0x00yyyyyy, 0x000000zz, 0x00000000(xxxxxx:LBA[23:0],yyyyyy:LBA[47:24] 操作扇区的起始位置;zz:扇区的个数)
发送 DMA 读数据请求命令:0x00258027, 0xE0xxxxxx, 0x00yyyyyy, 0x000000zz, 0x00000000(xxxxxx:LBA[23:0],yyyyyy:LBA[47:24] 操作扇区的起始位置;zz:扇区的个数)
3.2.2、Device 响应 DMA 写请求命令 FIS
比如 0x39 帧的结构如下:共 1DW,device 向 host 发送,常用于响应 host 的 DMA 写命令请求。
当硬盘发送 00000039,表示硬盘准备好可以接收 host 的 DMA 写数据命令了。
3.2.3、Host/Device 的 DMA 写/读命令
比如 0x46 帧的结构如下:共 1DW 头部 + N DW 数据(N:1~2048),host 向 device 发送 DMA 写数据命令,device 向 host 发送 DMA 读数据命令,device 向 host 发送设备信息 identify 信息(N=128 DW)。
3.2.4、Device 状态响应命令 FIS
比如 0x34 帧的结构如下:共 5DW,device 向 host 发送,常用于状态响应,比如响应 identify 命令,响应 DMA 写数据完成后的状态,响应 DMA 读数据完成后的状态。
其首个 DW 中的 bit16 指示状态是否有问题,值为 0 表示正常。
3.3、FIS 的发送
FIS 的发送过程如下:
当双方都空闲时,都在持续发送 SYNC 原语,这种状态称为空闲状态(IDLE)。
发送方想要发起 FIS 发送,它开始持续发送 X_RDY 原语。
经过一段延迟后,接收方收到了 X_RDY,此时如果接收方准备好接收 FIS 了,就持续发送 R_RDY 原语。
发送方收到了 R_RDY 原语,就发送一个 SOF 原语,随后紧跟着逐个发送 FIS 数据包的 dword(包括 FIS-type,Payload,CRC),最后一个 dword (CRC) 发送完后要紧跟一个 EOF 原语,然后持续发送 WTRM 原语。
接收方收到 SOF 后,开始持续发送 R_IP 原语,指示接受正在进行 (receiving in progress) 。完整地收完 FIS 后进行 CRC 检查。在收到 WTRM 原语后,如果 CRC 检查正确,就持续发送 R_OK 原语,否则持续发送 R_ERR 原语。
发送方收到 R_OK 或 R_ERR 后,开始持续发送 SYNC。
接收方收到 SYNC 后,也开始持续发送 SYNC,至此回到空闲状态,FIS 传输结束。
从该过程我们可以看到,当一个通道发送 FIS 时,另一个通道在发送 R_RDY,R_IP,R_OK,R_ERR 这四种原语来控制对方发送 FIS 的过程,因此在一个时间点上 FIS 不可能双向发送。SATA 在物理上是全双工,应用上是半双工。
由于 Host 和 device 都有发起 FIS 发送的可能,SATA 规定 device 的发送 FIS 优先级最高:当 host 和 device 都在发送 X_RDY,同时试图启动 FIS 发送时,host 只要检测到了 device 发来的 X_RDY,就要放弃当前的发送进程,转而发送 R_RDY,准备接收 device 发来的 FIS。
3.4、原语的封装/解封
原语的解封在解扰之前,原语的封装在加扰之后;当处于空闲状态时,双方互发 SYNC 原语,可能引起 EMI;SATA 协议规定了重复原语的加入 CONT 原语。对于收发过程中相关重复原语用 CONT 替换。发端可以不进行原语重复替换,接收方一定要遵守协议能解析出符合此规定的数据流和不按此规定的数据流。
SATA 规定了 4 类原语,从上图 CONT 的替换过程:
不可重复原语:SOF, EOF, CONT
可重复原语 (最后一次重复无需保留):SYNC, R_RDY, R_IP, R_OK, R_ERR, X_RDY, WTRM
可重复原语 (最后一次重复必须保留):HOLD, HOLDA
完全不影响重复加扰的原语:ALIGN
对于可重复原语,如果连续重复出现三次以上,SATA 要求把第 3 个重复的原语替换为 CONT,然后从第 4 个重复原语开始替换为垃圾数据。
举个例子如下(其中 "DATA" 代表一个 FIS 数据 dword,"GARB" 代表一个垃圾数据 dword):
// 重复加扰举例 (忽略 ALIGN 的插入) 重复加扰前 : SYNC SYNC SYNC SYNC X_RDY X_RDY X_RDY SOF DATA DATA DATA DATA EOF WTRM WTRM WTRM WTRM WTRM SYNC SYNC SYNC SYNC SYNC 重复加扰后 : SYNC SYNC CONT GRAB X_RDY X_RDY CONT SOF DATA DATA DATA DATA EOF WTRM WTRM CONT GARB GARB SYNC SYNC CONT GARB GARB
链路初始化后,SATA 上实际传输的每个 DW 只可能分为三种:原语、FIS 数据、或者 CONT 原语后的垃圾数据。有两个特殊的可重复原语:HOLD 和 HOLDA,它们在重复最后一次时必须保留,不能被替换为 CONT 或垃圾数据。
3.5、原语的流控
Flow Control (流量控制) 在 SATA 协议中用于在主机和存储设备之间协调数据传输速度,防止数据溢出或丢失。通过流量控制,链路层可以根据双方的接收能力调整数据的传输速率,确保通信。需要 Flow Control 有以下两种情况:发送端 Tx Buffer 接近空/满的时;接收端 Rx Buffer 接近满/空的时。
流控依赖于 HOLD 和 HOLDA 原语,如下交互过程中流控原语的使用:
比如当发送方暂未准备好待发送的 FIS 数据时,发送方可以插入 HOLD 原语来填空,这样就能支持'断断续续'地发送数据。发送方发送 FIS 数据时,如果暂时没准备好下一个 dword 数据,就发送 HOLD,直到准备好数据为止。接收方如果检测到 HOLD,就发送 HOLDA,告知对方'我知道了你没准备好'。反之如果检测到的是 FIS 数据,就正常发送 R_IP。
// 发送方流控举例 (忽略 ALIGN 的插入和 原语的重复加扰) 发送方发送 : X_RDY SOF DATA DATA DATA HOLD DATA DATA DATA HOLD HOLD HOLD HOLD DATA EOF WTRM WTRM 接收方发送 : R_RDY R_RDY R_RDY R_IP R_IP R_IP R_IP HOLDA R_IP R_IP R_IP HOLDA HOLDA HOLDA HOLDA R_IP R_OK
// 接收方流控举例 (忽略 ALIGN 的插入和 原语的重复加扰) 发送方发送 : SOF DATA DATA DATA DATA DATA DATA DATA HOLDA HOLDA HOLDA HOLDA HOLDA DATA DATA EOF WTRM WTRM WTRM 接收方发送 : R_RDY R_RDY R_RDY R_IP R_IP HOLD HOLD HOLD HOLD HOLD HOLD R_IP R_IP R_IP R_IP R_IP R_IP R_IP R_OK
四、传输层
传输层主要实现:封装/解封 FIS。
关于各类 FIS 相关字段结构已在 3.2 章节描述了,这里不再重复。
五、应用层
关于各类 FIS 已在 3.2 章节描述了,这里不再重复。
建链成功后,在 FPGA 读写硬盘的过程中,主要涉及 0x27、0x34、0x39、0x46 四种类型的 FIS 命令。
本次开发测试没有使用 NCQ 功能 (Native Command Queuing),每次一条命令请求/执行,使能硬盘 NCQ 功能允许可以发送多条指令到硬盘,NCQ 优化完成这些指令的顺序,比如 FPDMA。
5.1、查询硬盘信息
① FPGA 向 SATA 硬盘发送 identify 命令:00EC8027 00000000 00000000 00000000 00000000;
② SATA 盘向 FPGA 响应状态 5DW 的 0x34 FIS;
③ 之后 SATA 向 FPGA 发送 129DW 的 0x46 FIS,其中后 128DW 为硬盘信息。
《Serial ATA specifications》中硬盘相关信息如下:
76 字的 bit[3:1]定义了 SSD 支持的 SATA Gen,77 字的 bit[3:1]定义了协商后运行的线速率:
关于硬盘的容量,可查询 60、61 字和 100--103 字;如果 60 和 61 字内容为 0x0FFFFFFF,则硬盘为 48 位的 LB 地址表示(市面上的大多硬盘),该 48 位的 LB 数目由 100--103 字表示;如果 60 和 61 字内容不为 0x0FFFFFFF,则该硬盘为 28 位的 LB 数目,具体值为 60 和 61 字。
5.2、DMA 写硬盘
以 DMA 写速率较快,写之前需要发 DMA 写请求,待硬盘响应请求后方可写数据。以 48 位的 LB 硬盘为例。
① FPGA 向 SATA 硬盘发送 5DW 的 DMA 写请求;0x00358027, 0xE0xxxxxx, 0x00yyyyyy, 0x000000zz, 0x00000000(xxxxxx:LBA[23:0],yyyyyy:LBA[47:24] 操作扇区的起始位置;zz:扇区的个数)
② SATA 盘向 FPGA 响应 1DW 的 0x39 的 FIS(DMA activate),比如 00000039,表示硬盘准备好可以接收 host 的 DMA 写数据命令了。
③ FPGA 向 SATA 盘发送 0x46 的数据 FIS;如果 zz 个扇区的长度超过 2048DW,需要拆分成多个 0x46 的数据 FIS 进行发送;
④ SATA 每收到 0x46 的数据 FIS 后,都向 FPGA 发送 1DW 的 0x39 的 FIS DMA activate;
⑤ SATA 接收完所有的 0x46 的数据 FIS 后,向 FPGA 发送 5 DW 的 0x34 状态响应 FIS。
5.3、DMA 读硬盘
以 DMA 读速率较快,读之前需要发 DMA 读请求,硬盘读完请求的数据后发送状态 FIS。以 48 位的 LB 硬盘为例。
① FPGA 向 SATA 硬盘发送 5DW 的 DMA 读请求;0x00258027, 0xE0xxxxxx, 0x00yyyyyy, 0x000000zz, 0x00000000(xxxxxx:LBA[23:0],yyyyyy:LBA[47:24] 操作扇区的起始位置;zz:扇区的个数)
② SATA 盘向 FPGA 发送 0x46 的数据 FIS;如果 zz 个扇区的长度超过 2048DW,需要拆分成多个 0x46 的数据 FIS 进行发送;
③ SATA 发送完所有的 0x46 的数据 FIS 后,向 FPGA 发送 5 DW 的 0x34 状态响应 FIS。
六、工程测试
准备好相关硬件:带 SATA 接口的 FPGA 板卡、SATA 接口硬盘、SATA 电源线和数据线。
6.1、文件系统
SATA 硬盘支持 NTFS、exFAT 等文件系统。
在之前的文章中分析了实现了 SD 卡 FAT32 文件系统中的文件读写,感兴趣的可以参考。exFAT 文件系统是 FAT32 系统的扩展。
FPGA 纯逻辑实现文件系统中的文件读写,难度不大,但很繁琐。
本文测试不包含文件系统;对于很多应用场景,比如数据采集回放、记录仪等不使用文件系统也可以完成,只需记录每次的数据量 LBA 的地址范围即可,数据回放时根据 LB 号对应读取即可。
6.2、硬盘信息测试
本次测试的硬盘信息可以通过将硬盘连接上位机经 SSD-Z 软件查询,也可以通过 FPGA 板卡发送 Identify 命令获取。
6.2.1、SSD-Z 查询的硬盘信息
在经 SSD-Z 查询该盘信息如下:三星 870、能力(LBA 48bit 等)、支持 USB 和 SATA 接口、速率、容量 1.819TB、扇区 sector 大小 512B 等。具体信息:
比如 49 字 bit8 支持 DMA:
76 字:该盘支持 SATA1、SATA2、SATA3;77 字 bit[3:1]=1 表示该盘通过 USB 口连接 PC 协商到的速率为 Gen1 最大读写速率 150MB/S。
100-103 字表明该盘扇区数目为 0xE8E088B0,每个扇区 512B,共计 1.8193TB。
6.2.2、FPGA 板卡获取硬盘信息
FPGA 向 SATA 硬盘发送 identify 命令,解析 128DW 的 FIS 数据部分,得到的 LB 数目,支持的速率以及协商速率信息如下,与通过 SSD-Z 查询信息一致。
上图中 LB 数目为 0xE8E088B0,与 SSD-Z 查询信息一致。
支持的 SATA GEN:7 表示支持 SATA1、SATA2、SATA3。
sata_negotitate_gen 为 3 即 77 字的 bit[3:1]定义了协商后运行的线速率为 Gen3。
6.3、DMA 读写速率测试
为了测试硬盘读写速率,考虑一次读写请求最多操作 0xFF(255) 个扇区,如果每次访问 1 个扇区,请求及响应时间会影响速率;可以考虑每次的读写请求访问多个扇区,提高读写测速。
读写测试采用 VIO 控制:lb_num 表示本次操作的扇区数目,比如 1GB 对应扇区数为 0x20000;lb_start_addr 表示本次操作的 LB 起始地址;最后通过 wr_en_flag/rd_en_flag 发起读写使能。由于 SATA 不像 NVMe 可以全双工通信,SATA 的读写操作不能同时进行。
进行 1GB、10GB、20GB 的读写测试,计数以发起读写请求开始,经过对应数据访问完成,硬盘发回响应状态结束为止;用户时钟为 300Mhz。经测试汇总如下(为节省时间每种容量只做 1 次实验,不再进行多次比对):
| 测试数据量 | 写速率 | 读速率 |
|---|---|---|
| 1GB | 238MB/S | 422MB/S |
| 10GB | 240MB/S | 279MB/S |
| 20GB | 221MB/S | 419MB/S |
写 1GB 的测试:根据用户时钟(300Mhz)计数的时间为 1291664613 x 3.33ns,写速率为 238MB/S。
读 1GB 的测试:根据用户时钟(300Mhz)计数的时间为 728681644 x 3.33ns,写速率为 422MB/S。


