FPGA控制NVME开发流程

发布时间:2026/7/10 7:54:49
FPGA控制NVME开发流程 基于XILINX IP-AXI Memory Mapped to PCIe Gen2一、使用S_AXI_CTL总线进行配置S_AXI_CTL总线主要用于配置PCIE的配置CFG空间寄存器。1、读取RC端FPGA的PCIE配置空间RC设备使用TYPE1类型配置空间先进行读操作可以验证S_AXI_CTL总线通信是否正常使用S_AXI_CTL总线读取0x0, 0x4, 0x8地址读取数据如下供应商ID设备ID值0x712410EE命令状态寄存器值为0x00100000ClassCode ID版本ID值为0x060400002、配置RC端FPGA的PCIE配置空间①配置命令CMD寄存器(0x04)开启BUSM_EN 、MEM_EN、IO_EN、PARITY、SERR_EN.②配置设备枚举范围寄存器0x18将寄存器配置为0x00070100代表RC 主总线 Bus0 直接下游总线起点 Bus1 系统最多支持 7 级总线Bus1~Bus73、读取EP端NVME SSD的PCIE配置空间当 AXI 映射 PCIe 核配置为Root Port(RC)时通过ECAM 增强配置访问机制生成配置事务该功能仅 RC 模式可用。对一段特定内存窗口ECAM 窗口的 AXI 读写会自动转换成 PCIe 标准配置读 / 写 TLP。访问Primary Bus默认 Bus0生成 Type 1 桥配置头事务访问 FPGA 内置 RC 本地配置空间访问Secondary Bus次总线如 Bus1生成 Type 0 EP 配置事务用于 NVMe 等终端设备访问区间 Secondary Bus Bus ≤ Subordinate Bus多级桥下游总线生成 Type1 桥配置事务软件枚举阶段必须将主 / 次 / 从属总线号写入 RC 内置 Type1 配置头偏移 0x18 寄存器。ECAM的基地址为ECAM_OFFSETBus20 ∣ Dev 15 ∣ Func12。只有一块NVME SSD时默认Bus1Dev0Func0。基地址ECAM_OFFSET0x100000。NVME SSD配置空间使用type0类型读取0x1000000x1000040x100008地址查看ID等信息供应商ID设备ID值0x10011BC0命令状态寄存器值为0x00100000ClassCode ID版本ID值为0x010802014、配置EP端NVME SSD的PCIE配置空间①配置命令CMD寄存器(0x100004)开启BUSM_EN 、MEM_EN。②配置BAR空间地址寄存器0x100010、0x1000140x100010写入低32位地址0x80000004对应IP核中配置地址0x100014写入高32位地址0x000000005、配置IP核寄存器配置根端口状态 / 控制寄存器寄存器偏移地址0x148开启Bridge Enable 桥使能。Bridge Enable该位置 1 时AXI BAR 空间的读写流量可以转发到 PCIe 总线。软件完成 PCIe 枚举流程后必须向该位写 1 开启桥转发读取0x148寄存器值后BIT0置1后再写入。二、使用S_AXI总线进行配置S_AXI总线主要用于配置NVME SSD内部寄存器。NVME SSD内部寄存器位于BAR空间中完成地址映射后就可以进行访问了。1、读取寄存器获取CAP,VS,CC寄存器数据对应地址分别为0x80000000CAP低32位0x80000004CAP高32位0x800000080x80000014。acpl is FF0100FFacph is 00000020VS is 00010300CC is 000000002、配置寄存器初始化①等待CSTS寄存器0x8000001Cready位为0②配置CC寄存器0x80000014为0x00460000 配置Admin提交队列单条大小为64byte, Admin完成队列单条大小为16byte。③配置AQA寄存器0x80000024为0x00100010配置Admin提交、完成队列深度为16。④配置ASQ寄存器0x80000028、0x8000002C分别为0x101000000x00000000配置Admin提交队列基地址高32位为0低32位为0x10100000。⑤配置ACQ寄存器0x80000030、0x80000034分别为0x101010000x00000000配置Admin完成队列基地址高32位为0低32位为0x10101000。⑥配置CC寄存器设置EN地址0x80000014写0x00460001⑦等待CSTS寄存器0x8000001Cready位为13、提交和完成队列流程Admin和IO通用流程如下提交队列①指令写入内部DDR提交队列地址中这一步不会向NVME SSD发送数据只将指令存入指定内部空间等待NVME读取②发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。完成队列①判断是否接收到完成命令根据P位相位翻转判断是否接受到新的完成指令。状态Status不为0表示出错。②发起完成门铃向完成门铃寄存器Admin为0x80001004写完成队列头指针。4、读取Identify中Controller信息Identify信息共4094字节。主要读取NVME SSD硬盘的ID、MDTS信息等①定义Identify存放地址如#define IDENTIFY_CTRL_BASE 0x10200000②提交队列信息sqe.cdw0 0x06;sqe.nsid 0;sqe.dptr[0] 0x10200000; //数据缓冲区地址sqe.dptr[1] 0;sqe.cdw10 1;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。③等待完成队列向完成门铃寄存器Admin为0x80001004写完成队列头指针。获取MDTS计算出单次最大传输数据大小。控制器最小页 CAP.MPSMIN 4KB (4096B)5、设置IO队列数量设置IO队列数量使用设置特征命令DW11如上实际写入值为队列数量-1创建2个队列是NCQR和NSQR都为1①提交队列信息sqe.cdw0 0x09;sqe.cdw10 0x07sqe.cdw11 0x00010001;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。③等待完成队列向完成门铃寄存器Admin为0x80001004写完成队列头指针。6、创建IO队列①定义IO队列基地址如#define IO_WR_SQ_BASE 0x10102000#define IO_WR_CQ_BASE 0x10103000#define IO_RD_SQ_BASE 0x10104000#define IO_RD_CQ_BASE 0x10105000②创建写完成队列sqe.cdw0 0x03000005;sqe.nsid 0;sqe.rsvd1 0;sqe.mptr 0;sqe.dptr[0] 0x10103000; // PRP1CQ物理基地址sqe.dptr[1] 0;sqe.cdw10 0x00070001;sqe.cdw11 0x00000001;sqe.cdw12 0;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。等待完成队列,判断是否创建成功。向完成门铃寄存器Admin为0x80001004写完成队列头指针。③创建读完成队列sqe.cdw0 0x03010005;sqe.nsid 0;sqe.rsvd1 0;sqe.mptr 0;sqe.dptr[0] 0x10105000; // PRP1CQ物理基地址sqe.dptr[1] 0;sqe.cdw10 0x00070002;sqe.cdw11 0x00000001;sqe.cdw12 0;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。等待完成队列,判断是否创建成功。向完成门铃寄存器Admin为0x80001004写完成队列头指针。④创建写提交队列sqe.cdw0 0x03020001;sqe.nsid 0;sqe.rsvd1 0;sqe.mptr 0;sqe.dptr[0] 0x10102000; // PRP1CQ物理基地址sqe.dptr[1] 0;sqe.cdw10 0x00070001;sqe.cdw11 0x00010001;sqe.cdw12 0;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。等待完成队列,判断是否创建成功。向完成门铃寄存器Admin为0x80001004写完成队列头指针。⑤创建读提交队列sqe.cdw0 0x03030001;sqe.nsid 0;sqe.rsvd1 0;sqe.mptr 0;sqe.dptr[0] 0x10104000; // PRP1CQ物理基地址sqe.dptr[1] 0;sqe.cdw10 0x00070002;sqe.cdw11 0x00020001;sqe.cdw12 0;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;将指令写入Admin提交队列中发起提交门铃向提交门铃寄存器Admin为0x80001000写提交队列尾指针。等待完成队列,判断是否创建成功。向完成门铃寄存器Admin为0x80001004写完成队列头指针。7、写数据到NVME SSD①定义写数据基地址及链表地址#define WRITE_DATA_BUF 0x20000000#define PRP_LIST_BUF 0x10400000UL链表结构单条数据长度64B.typedef struct {u64 prp_entry[256];} PrpList;②提交队列信息单个LBA大小为512B. Nlb为写入LBA的个数SLBA为第一逻辑块地址// DW0: CID Write操作码sqe.cdw0 (((u32)cid) 16) | 0x01;sqe.nsid nsid;sqe.rsvd1 0;sqe.mptr 0;// DW10/DW1164位起始LBAsqe.cdw10 (u32)lba;sqe.cdw11 (u32)(lba 32);// DW12NLB nlb- 1 (NVMe标准)sqe.cdw12 (nlb - 1) 0xFFFF;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;// dptr表示访问的内存空间地址向nvme中写数据只用提交队列告诉NVME数据存放在哪个地址nvme自行进行dma取数据sqe.dptr[0] cur_addr; //这里为0x20000000//仅1页4KBPRP2置0sqe-dptr[1] 0;//多页情况//剩余页数填充PRP链表sqe-dptr[1] PRP_LIST_BUF; // PRP2指向PRP列表首地址这里为0x10400000//在链表中填入需要写入的页地址while(remain 0)//剩余需要写入的数据大于0{prp_list-prp_entry[entry_idx] cur_addr;//实际地址填入链表0x20000000地址基础上进行4K累加后的地址cur_addr 4096; //地址按4K累加if(remain 4096)remain - 4096;elseremain 0;entry_idx;}// PRP链表最后一项填0标记结束prp_list-prp_entry[entry_idx] 0;将指令写入IO WR提交队列中发起提交门铃向提交门铃寄存器IO WR为0x80001008写提交队列尾指针。③等待完成队列返回的status为0表示写入成功。向完成门铃寄存器IO WR为0x8000100C写完成队列头指针。7、从NVME SSD读取数据①定义写数据基地址及链表地址#define READ_DATA_BUF 0x28000000#define PRP_LIST_BUF 0x10400000UL链表结构单条数据长度64B.typedef struct {u64 prp_entry[256];} PrpList;②提交队列信息// DW0: CID Read 操作码sqe.cdw0 (((u32)cid) 16) | 0x02;sqe.nsid nsid;sqe.rsvd1 0;sqe.mptr 0;// DW10/DW1164位起始LBAsqe.cdw10 (u32)lba;sqe.cdw11 (u32)(lba 32);// DW12NLB nlb- 1sqe.cdw12 (nlb - 1) 0xFFFF;sqe.cdw13 0;sqe.cdw14 0;sqe.cdw15 0;// dptr表示访问的内存空间地址向nvme中写数据只用提交队列告诉NVME数据存放在哪个地址nvme自行进行dma取数据sqe.dptr[0] cur_addr; //这里为0x28000000// 仅1页4KBPRP2置0sqe-dptr[1] 0;//多页情况// 剩余页数填充PRP链表sqe-dptr[1] PRP_LIST_BUF; // PRP2指向PRP列表首地址这里为0x10400000//在链表中填入需要写入的页地址while(remain 0)//剩余需要写入的数据大于0{prp_list-prp_entry[entry_idx] cur_addr;//实际地址填入链表0x28000000地址基础上进行4K累加后的地址cur_addr 4096; //地址按4K累加if(remain 4096)remain - 4096;elseremain 0;entry_idx;}// PRP链表最后一项填0标记结束prp_list-prp_entry[entry_idx] 0;将指令写入IO RD提交队列中发起提交门铃向提交门铃寄存器IO RD为0x80001010写提交队列尾指针。③等待完成队列返回的status为0表示写入成功。向完成门铃寄存器IO RD为0x80001014写完成队列头指针。三、M_AXI总线配置M_AXI总线由EP端NVME SSD发起主要用于NVME SSD进行DMA读写。将M_AXI总线与ZYNQ或DDR连接读、写操作时NVME SSD会自动通过M_AXI总线访问内存。

相关新闻

别被忽悠了!一份建设学院网站的通知书到底该怎么写才不踩坑

别被忽悠了!一份建设学院网站的通知书到底该怎么写才不踩坑

刚接到那个所谓的“建设学院网站”项目,我差点把咖啡喷屏幕上。这年头,连学校官网这种正经事儿都能被包装成玄学,真是让人哭笑不得。很多人以为写个通知就是发个红头文件,嘿,那叫行政公文,不叫建设方案。你要是真按那个套路走,最后交出来的东西肯定是一堆没人看的垃圾代…

发布时间:2026/7/10 7:54:07
WordPress性能瓶颈与现代化架构迁移实战指南

WordPress性能瓶颈与现代化架构迁移实战指南

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 如果你还在用WordPress建站,可能已经感受到了时代的变迁。WordPress曾经是个人博客和小型企业网站的首选,但如…

发布时间:2026/7/10 7:54:35
成都企业网站建设及公司ppt:别整那些虚头巴脑的,客户只看这三点

成都企业网站建设及公司ppt:别整那些虚头巴脑的,客户只看这三点

昨天半夜两点,我还在改那个PPT。真的,手都在抖。不是累的,是气的。甲方爸爸又说要“大气”,要“高端”,要“国际范儿”。我说哥,咱们是个做餐饮供应链的小公司,你让我搞出个苹果发布会的感觉,我上哪给你变去?这事儿吧,其实跟做网站是一个道理。很多老板找我聊,开口就…

发布时间:2026/7/10 7:52:53
搞工程别只看报价,四川德立胜建设工程有限公司网站里的门道你懂多少?

搞工程别只看报价,四川德立胜建设工程有限公司网站里的门道你懂多少?

找施工队怕被坑?怕工期拖延?怕质量烂尾?看完这篇,你至少能避开80%的隐形大坑,不再当冤大头。说句掏心窝子的话,很多老板在找建筑公司的时候,第一反应是问“多少钱一平”。这其实是最危险的信号。我见过太多案例,因为贪便宜选了低价队,最后补漏的钱比当初省下的还多。真…

发布时间:2026/7/10 8:50:07
别被忽悠了!网站建设的要求有哪些?这才是真相

别被忽悠了!网站建设的要求有哪些?这才是真相

做网站这事儿,真不是敲几行代码就完事了。我见过太多老板,花了几万块,结果网站打开慢得像蜗牛。用户还没看完第一屏,就关掉了。这钱扔水里,连个响儿都听不见。很多人问,网站建设的要求有哪些?其实核心就三点:好看、好用、好找。别整那些虚头巴脑的概念。先说速度,这是…

发布时间:2026/7/10 8:50:03
别被忽悠了,房县网站建设到底该咋整才不踩坑?

别被忽悠了,房县网站建设到底该咋整才不踩坑?

看着后台那寥寥无几的访客数,心里是不是像堵了块石头?明明产品不错,服务也到位,可网上就是没人找得到你。很多老板觉得,搞个网站不就是找个模板套一下,花个几千块完事?大错特错。这种想法,简直就是把自家的门面开在荒郊野岭,还指望路人主动敲门。记得去年有个做土特产…

发布时间:2026/7/10 8:49:27
东莞建设工程交易中心网站怎么查中标?避坑指南与真实内幕

东莞建设工程交易中心网站怎么查中标?避坑指南与真实内幕

想查东莞的中标信息,却找不到门路? 别急,这篇直接教你怎么在东莞建设工程交易中心网站高效找数据。 我不讲虚的,只讲怎么帮你省钱、避坑。做工程这行,水太深了。 以前我们靠关系,现在靠数据。 很多人问我,怎么在东莞建设工程交易中心网站看到真实的竞争对手底细? 其实不…

发布时间:2026/7/10 8:49:16
别慌!搞定internet网站建设试卷其实没那么难,这3招亲测有效

别慌!搞定internet网站建设试卷其实没那么难,这3招亲测有效

看着那张密密麻麻的internet网站建设试卷,你是不是手心冒汗?心跳加速?别急着把笔折断,我懂那种感觉。上周我也差点崩溃,面对那些代码逻辑和服务器配置题,脑子直接死机。但后来我静下心来,发现这玩意儿没那么可怕。今天就把我压箱底的经验掏出来,不整虚的,直接上干货。…

发布时间:2026/7/10 8:49:10
别被忽悠了!揭秘西安知名网站建设公司背后的真实逻辑

别被忽悠了!揭秘西安知名网站建设公司背后的真实逻辑

做企业网站,真的那么难吗?我见过太多老板,拿着几百万预算,最后做出来的网站丑得像十年前的产物。也见过小老板,预算只有几千块,却做出了让人眼前一亮的官网。差别在哪?不在钱,在脑子。今天我就把话撂在这:别盲目迷信名气。所谓的“西安知名网站建设公司”,很多只是广…

发布时间:2026/7/10 8:48:47
老板们别被忽悠了,企业网站建设费用摊销到底怎么算才不亏?

老板们别被忽悠了,企业网站建设费用摊销到底怎么算才不亏?

说实话,每次听到老板们拍着桌子问“做个网站要多少钱”,我心里就直犯嘀咕。你们关心的根本不是网站好不好用,而是这钱花得值不值,能不能立马变出利润来。我见过太多公司,花个三五万做个花里胡哨的首页,结果后台乱成一锅粥,SEO标签全没填,上线半年连个蜘蛛都不爬。这种钱…

发布时间:2026/7/10 0:00:19
网站搜索建设怎么做?新手避坑指南与实战心得

网站搜索建设怎么做?新手避坑指南与实战心得

很多老板做网站,花大价钱搞设计,最后发现用户根本找不到内容,搜索功能形同虚设。这篇干货不讲虚的,直接告诉你怎么搭建一个真正好用的站内搜索,解决用户找不到东西、跳出率高的问题。上周我去了一家做高端家具的电商网站。页面确实漂亮,极简风,高级感拉满。但是,我想找…

发布时间:2026/7/10 0:00:33
北京市建设工程质量监督网站查询实操指南与避坑实录

北京市建设工程质量监督网站查询实操指南与避坑实录

做工程最怕什么?怕验收不过,怕资料补不齐,怕最后拿着钱还背一身债。这篇不整虚的,直接告诉你怎么通过北京市建设工程质量监督网站搞定验收流程,以及那些没人愿意告诉你的隐形坑。先说个真事儿。上个月有个做装修的朋友,急着拿竣工验收备案表,结果在北京市建设工程质量监…

发布时间:2026/7/10 0:00:37
做个人信息管理网站建设,这3个坑我踩了七年,你千万别再跳

做个人信息管理网站建设,这3个坑我踩了七年,你千万别再跳

做了七年建站,见过太多老板花大钱买模板,最后发现根本没法用。特别是现在大家都讲究数据隐私,想搞个个人信息管理网站建设,结果越搞越乱。这篇文不整虚的,直接说怎么把这套系统落地,让你自己的数据真正听话。先说个真事儿。去年有个做自由职业的朋友找我,他说想建个网站…

发布时间:2026/7/9 15:43:56
杨凌规划建设局网站怎么查最新规划?老杨说点大实话

杨凌规划建设局网站怎么查最新规划?老杨说点大实话

杨凌规划建设局网站你是不是也遇到过这种情况?想看看自家旁边要修路,还是建公园。翻遍了手机,搜出来的全是几年前的旧闻。或者好不容易找到个入口,页面加载慢得像蜗牛。心里那个急啊,真的,懂的人都懂。我是老杨,在杨凌混了十几年,跟这行打交道不少。今天不跟你扯那些虚…

发布时间:2026/7/9 15:43:42
杭州网站建设 seo 避坑指南:别被那些只会套模板的忽悠了

杭州网站建设 seo 避坑指南:别被那些只会套模板的忽悠了

昨天半夜两点,我还在改一个客户的后台,咖啡都凉透了。这哥们儿是做机械配件的,在余杭那边,找的前一家公司花了八千块做了个站,结果上线一个月,百度连个影子都没有。他急得给我打电话,说是不是被黑了。我让他把链接发过来,打开一看,好家伙,那代码乱得跟刚被猫抓过的毛…

发布时间:2026/7/9 16:54:10
建站7年才悟出的网站建设思路,别再花冤枉钱了

建站7年才悟出的网站建设思路,别再花冤枉钱了

做建站这行整整7年了。 见过太多老板花几万块, 最后做出来的网站像个垃圾场。 今天不整那些虚头巴脑的术语。 就聊聊我踩过的坑, 和真正能落地的网站建设思路。很多老板一上来就问: “多少钱能做个高大上的?” 我通常直接劝退。 因为方向错了, 你给再多钱也是打水漂。 真正…

发布时间:2026/7/9 15:45:02
合肥的网站建设避坑指南:别被低价忽悠,这3个细节决定生死

合肥的网站建设避坑指南:别被低价忽悠,这3个细节决定生死

做企业官网最怕什么?不是技术难,是交钱后没人管,或者上线一个月连个访客都没有。这篇东西不扯虚的,直接告诉你怎么在合肥找个靠谱的团队,或者自己怎么避坑。先说个大实话,我在合肥混这行五年多,见过太多老板因为贪便宜吃大亏。你去百度搜“合肥的网站建设”,出来一堆报…

发布时间:2026/7/9 15:44:20
别被忽悠了!德州网站建设那些坑,我拿真金白银换来的教训

别被忽悠了!德州网站建设那些坑,我拿真金白银换来的教训

做这行久了,心里就憋着一股火。每次看到客户拿着网上抄来的模板,问我能不能做成“苹果官网”那种效果。我就想笑。真的,太想笑了。今天咱不整那些虚头巴脑的专业术语。就聊聊德州网站建设里,那些让人头秃的真实事儿。我有个客户,老张。他是做德州本地建材的,实在人。当初…

发布时间:2026/7/9 15:45:20