记录此刻:历时两月,初步实现基于FPGA的NVMe SSD固态硬盘存储控制器设计!

ops/2025/3/5 12:29:43/

背景

为满足实验室横向项目需求,在2024年12月中下旬导师提出基于FPGA的NVMe SSD控制器研发项目。项目核心目标为:通过PCIe 3.0 x4接口实现单盘3000MB/s的持续读取速率。

实现过程

调研

花了半个月的时间查阅了一些使用FPGA实现NVME SSD控制器的论文、博客,确认了实现思路和路线,主要明确以下几点:
1、架构角色转换:区别于传统FPGA作为Endpoint设备(如数据采集卡),本项目需将FPGA配置为Root Complex(RC),主动管理作为Endpoint(EP)的NVMe SSD设备
2、协议栈解析:建立NVMe协议与PCIe协议的层级关系认知,确认需基于Xilinx AXI PCIe IP核构建Root Port架构
3、PCIe配置空间:重点研究BAR寄存器组的地址映射机制,在实现过程中,FPGA需要对SSD的PCIE 配置空间进行配置。
4、学习NVMe协议队列机制实现:参考《蛋蛋读NVMe》技术博客,构建基于门铃寄存器的SQ/CQ队列管理系统。NVMe寄存器组:深入学习CAP(控制器能力)、CC(控制器配置)、CSTS(控制器状态)等核心寄存器

硬件选择

自己想了两个方案,第一种是通过PCIE金手指转M.2接口。类似于下图这种(该图来源于一篇硕士论文)
在这里插入图片描述
我当时买的那个转接板不知道哪里有问题,PCIE链路建立不起来。

第二种方案是使用FMC转M.2接口,此方案可以正常建立起PCIE链路连接。
在这里插入图片描述

FPGA逻辑设计

由于课题组并没有相关的设计参考,所以不得不从零开始,在AXI PCIE IP官方给的example design的基础上进行“魔改”。

1、学习AXI PCIE IP使用,知道IP核的接口是干嘛用的,主要是以下接口:S_AXI、S_AXI_CTRL、M_AXI。
在这里插入图片描述
2、学习IP核的配置,AXI BAR选项卡比较重要,涉及到AXI地址到PCIE地址的转换。
在这里插入图片描述
3、配置SSD PCIE 配置空间的相关寄存器,比如BAR0、BAR1寄存器、Command寄存器等。设置IP核使能。
4、读取SSD中和NVME协议寄存器,寄存器的偏移量是相对于PCIE BAR寄存器的地址偏移的。比较关键的是CAP寄存器。
5、进行NVME SSD的初始化,设置管理和完成队列的深度、基地址等,并设置CC.EN=1,等待CSTS.RDY为1。
6、发送Admin命令,进行SSD的识别、配置I/O队列数,以及对应的I/O完成队列和提交队列的ID、基地址、深度等。命令的实现方式和流程按照协议要求来就行了,基于状态机进行设计。
7、发送I/O命令,进行数据读写,要确认好SSD一次传输的最大数据量是多少,以及一个扇区的大小。
在这里插入图片描述
在这里插入图片描述

总结

碎碎念:说真的,刚开始做的时候,我是没有想到自己能做出来的,而且这个控制器方案也没有太多可借鉴的开源的设计,该方案都是被拿来售卖的。没想到自己能用两个月的时间给初步实现出来。不过,目前这个方案还不够完善,后续还需要进行优化调整,使其更加易用。比如,通过几个简单的控制信号,就能完成大批量的数据读取,这方面我打算参考商业 IP 的接口设计思路。

后面有时间可以用一个专栏讲解一下实现思路,但是应该不会免费开源,因为该项目完全可以作为一个高端项目供大家深入学习研究,我并不希望它因为过度传播而失去其独特性 ,变得过于泛滥(烂大街)。


http://www.ppmy.cn/ops/163297.html

相关文章

调用链追踪(Trace ID)

前言: 在 Java 中实现 调用链追踪(Trace ID) 通常用于分布式系统中跟踪请求的完整链路,常见的实现方式包括手动编码或使用开源框架(如 SkyWalking、Zipkin、Spring Cloud Sleuth 等)。以下是具体实现方法及…

AI企业流程自动化(BPA - Business Process Automation)

目前市场上确实有一些 AI 解决方案,能够覆盖公司多个业务流程,实现 端到端的企业流程自动化(BPA - Business Process Automation)。不过,想要 完全自动化所有岗位(财务、出纳、管理、产品、研发、销售、营销…

系统架构设计师—软件工程基础篇—系统运维与维护

文章目录 软件维护分类遗留系统 软件维护分类 在系统运行过程中,软件需要维护的原因是多样的。根据维护的原因不同,可以讲软件维护分为以下4种: 改正性维护 修改软件错误、改正软件性能上的缺点、排除实施中的错误使用。 适应性维护 在使用…

表达式求值(后缀表达式)

后缀表达式 后缀表达式是给计算机去看的,一个个压进栈中; 遇到操作符就计算再将计算出的结果压到栈中;最后弹出结果。 1.栈的初始化(动态存储) typedef struct {ElemType* data;int top; }Stack; //初始化 Stack* initStack() {Stack* s (Stack*)malloc(sizeof(Stack));s->…

【蓝桥】常用库函数

1、memset()函数 1.1 基本介绍 定义在头文件<cstring>中主要作用是对一块内存区域进行设置值的操作 1.2 函数原型 void *memset(void *str, int c, size_t n);str&#xff1a;指向要填充的内存块的指针c&#xff1a;要设置的值。该值以int形式传递&#xff0c;但函数在…

玩转顺序表:用 C 语言实现数据的插入与删除

目录 顺序表的定义 插入元素 删除元素 查找元素 主函数 打印顺序表 完整代码 总结 在这篇博客中&#xff0c;我们将探讨如何使用 C 语言实现一个简单的顺序表&#xff08;也称为动态数组&#xff09;&#xff0c;并实现一些基本操作&#xff0c;包括插入、删除和查找…

ldap放大 DDOS.c

ldap放大汉化源码 安装环境指令: 乌班图/Debian系统: apt install gcc -y centos系统: yum install gcc -y 编译指令: gcc ldap.c -o ldap -pthread -stdgnu99 最后输入 ./ldap 查看使用方法 注意:本脚本完全开源免费,请勿使用任何已编译版本,使用本脚本必须拥有roo…

京东一面:为什么 IDEA 建议去掉 StringBuilder,而要使用 “+” 拼接字符串?

本文已收录至Java面试网站&#xff1a;https://topjavaer.cn 今天咱们来聊聊一个很常见的开发场景&#xff1a;字符串拼接。在日常开发中&#xff0c;字符串拼接几乎是每个 Java 开发者都会用到的操作。但最近&#xff0c;有朋友在面试时被问到一个问题&#xff1a;“为什么 ID…