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顺序读 |
主要参考:
sata相关文档:《Serial ATA specifications》,《ATA8-ACS》
网上相关文档:存储随笔《SATA科普教程》
知网相关文献:《基于FPGA的SATA硬盘访问控制技术的研究》
相关博文:古猫先生 SATA系列博文转载 - 咸鱼书生 - 博客园等系列文章
一、SATA介绍
SATA是Serial ATA(Serial Advanced Technology Attachment)串行ATA,由Intel、IBM、Dell、APT、Maxtor和Seagate公司共同提出的硬盘接口规范。
1.1 、SATA硬盘
目前常用的SATA接口为7针数据接口和15针电源接口。其实物如下:

经SSD-Z查询该盘信息如下:三星870、能力(LBA 48bit等)、支持USB和SATA接口、速率、容量1.819TB、扇区sector大小512B等。

其接口包含数据接口和电源接口,如下图示:


数据接口: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设备识别,完成链路建立(复位、初始化/速率协商、建链)。00B只用于识别硬盘是否存在,不进行数据传输,所以对于正常的数据传输信号(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的发送过程如下:


// FIS 发送进程举例 (忽略ALIGN的插入和原语的重复加扰)
发送方发送 : SYNC SYNC X_RDY X_RDY X_RDY X_RDY X_RDY SOF DATA DATA DATA DATA EOF WTRM WTRM WTRM WTRM SYNC SYNC SYNC SYNC SYNC
接收方发送 : SYNC SYNC SYNC SYNC SYNC R_RDY R_RDY R_RDY R_RDY R_RDY R_IP R_IP R_IP R_IP R_IP R_OK R_OK R_OK R_OK R_OK SYNC SYNC
当双方都空闲时,都在持续发送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等文件系统。
在之前的文章中FPGA实现SD卡内文件的读写功能(FAT32文件系统),分析实现了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。

FPGA光通信系列4 --- 基于64b/66b编码的自定义协议
FPGA光通信系列3 --- 基于8b/10b编码的自定义协议应用
FPGA光通信系列2------Aurora 64B/66B的使用
FPGA实现Aurora光通信应用(8B/10B)
FPGA外挂存储器应用3------NVMe协议 M.2硬盘的读写功能测试
FPGA外挂存储器应用2------QSPI Flash读写等功能
JESD204B的使用系列------3、DAC的应用(AD9164 9.6GSPS)