基于 Zynq UltraScale+ MPSoC 的 PL DDR4 直写 NVMe 与 exFAT 文件系统方案
面向宽带 ADC、雷达、通信、工业检测和高速仪器的数据采集存储平台
项目代号:PL-Direct NVMe Acquisition & Storage Platform(PDNS 单盘版)
摘要
高速采集系统真正困难的地方,往往不是“把数据采进 FPGA”,而是如何持续、可靠地把海量数据写入 SSD,并且让采集文件能够被 Linux 和 Windows 直接管理。
本项目基于 Zynq UltraScale+ MPSoC,构建了一条“采集数据进入 PL DDR4,再由 PL 侧 NVMe Host Core 直接写入 SSD”的高速数据通路。PS 侧运行 PetaLinux,负责 exFAT 文件系统、文件预分配、物理区间映射、任务调度和状态监控,但不再搬运大流量采集数据。
这种软硬件分工避免了传统方案中 PL DDR、PS DDR、Linux 页缓存之间的多次复制,在保留标准文件系统易用性的同时,降低了 CPU 和 PS 内存带宽压力。目前工程已经完成单盘直写、PRP List、QD32 并发、多文件连续采集、文件池复用、全文件数据序列校验以及环形缓冲区满保护等功能。
关键词:Zynq MPSoC、FPGA、NVMe、PL DDR4、exFAT、高速采集、零拷贝、PetaLinux、ADC
一、传统高速采集方案的瓶颈
常见的 FPGA + Linux 采集系统通常采用下面的数据路径:
ADC → FPGA → PL/PS DDR → Linux 驱动 → 页缓存 → 文件系统 → SSD这种架构容易实现,但在数据率达到 GB/s 级别后,会逐渐暴露出几个问题:
- 采集数据需要在 PL DDR、PS DDR和内核缓冲区之间多次搬移;
- CPU 参与 DMA 管理、数据复制和文件写入,系统负载较高;
- Linux 调度、回写和页缓存抖动可能造成瞬时堵塞;
- 文件系统写入速度和实时采集速度互相耦合;
- 当 SSD 出现垃圾回收或介质写入抖动时,采集链路容易丢点。
本项目的核心思路,是把“大数据通路”和“文件管理通路”分开:
- PL 负责高速实时数据和 NVMe 命令数据通路;
- PS Linux 负责文件系统、元数据、任务控制和异常处理;
- 采集数据不经过 PS DDR 和 Linux 页缓存。
二、产品总体架构
系统的数据通路如下:
对应的物理数据路径为:
采集源 → AXI4-Stream FIFO → PL DDR4 → NVMe SSDPS 侧 Linux 只参与控制面:
创建文件 → 分配exFAT簇 → 获取物理LBA → 下发直写任务 → 更新文件状态与元数据 → 监控采集结果因此,这里的“PL 侧直写”并不是绕过文件系统裸写整块 SSD,而是在 Linux 预先维护好文件和物理区间后,由 PL DDR4 直接向这些已保留的 LBA 写入数据。这样既保留了 exFAT 文件的兼容性,又避免了采集载荷进入 PS 数据通路。
三、当前工程配置
当前版本的主要配置如下。
| 项目 | 当前配置 |
|---|---|
| FPGA 平台 | Zynq UltraScale+ MPSoC |
| 开发工具 | Vivado 2022.2 |
| Linux 构建环境 | PetaLinux 2022.2 |
| 测试数据源 | adc_gen |
| 虚拟 ADC 通道数 | 4 通道 |
| 单通道位宽 | 16 bit |
| 当前采样配置 | 300 MSPS |
| 理论源数据率 | 2.4 GB/s,约 2288.8 MiB/s |
| PL DDR4 环形缓冲区 | 8 GiB |
| 缓冲块数量 | 8192 |
| 单缓冲块大小 | 1 MiB |
| NVMe 逻辑块大小 | 512 byte |
| 单条 NVMe 命令数据量 | 最大 128 KiB |
| 硬件命令队列深度 | QD32 |
| 目标文件系统 | exFAT |
| 当前存储形态 | 单 NVMe SSD |
300 MSPS 是当前工程中测试数据源的配置,并不代表接口只能工作在这一采样率。真实 ADC 接入时,可以根据通道数、位宽、采样时钟和 AXI4-Stream 数据宽度重新计算和配置,但持续平均输入速率不能超过存储链路的稳定写入能力。
四、核心功能与技术特点
1. PL DDR4 到 NVMe 的直接数据路径
采集数据首先由 DataMover 写入 PL 侧 DDR4 环形缓冲区。NVMe 写命令随后直接引用 PL DDR4 中的物理数据地址,SSD 从该地址读取数据。
整个采集载荷不需要复制到 PS DDR,也不进入 Linux 页缓存。PS 只负责准备目标 LBA、提交命令并处理完成事件,适合持续大吞吐采集场景。
2. 8 GiB 环形缓冲与生产者/消费者模型
PL DDR4 被划分为 8192 个 1 MiB 缓冲块,通过单调递增的producer和consumer计数器管理:
producer表示 PL 已经完成写入的数据块;consumer表示已经成功落盘并释放的数据块;ready = producer - consumer表示等待落盘的缓冲数量;backpressure用于观察存储侧不能及时消费数据的情况。
这套模型能够吸收 SSD 的短时延迟抖动,并为驱动提供清晰的缓冲区所有权边界。
3. 环形缓冲区满自动停机保护
高速采集系统不能在缓冲区满后继续覆盖尚未落盘的数据。当前版本已加入跨层保护:
- PL 检测环形缓冲区满后停止继续生产数据;
- 锁存
buffer_full和写入错误状态; - 控制模块撤销持续启动状态;
- Linux 驱动停止采集任务;
- 用户态工具报告
producer、consumer、ready和错误原因; - 未完成文件保留为
.partial,避免被误认为有效采集文件。
发生环满说明采集源的长期平均数据率已经超过 SSD 的可持续写入能力,或存储设备出现了异常长尾延迟。系统会明确停机,而不是静默覆盖旧数据。
4. NVMe 多命令并发
项目配套的iprop_nvme_block驱动已实现:
- Linux blk-mq 块设备接口;
- PRP1、PRP2 和 PRP List;
- 多个 DMA 缓冲和并发请求;
- CID 与完成队列匹配;
- QD32 硬件队列;
- 中断完成,避免同步轮询长期占用 CPU;
- 普通块设备访问和 PL DDR4 直写接口。
对于 1 MiB PL 缓冲块,驱动会拆分为多条 NVMe 命令并保持命令队列处于工作状态,从而减少单命令同步路径带来的空闲间隙。
5. exFAT 文件池与物理区间映射
exFAT 具有 Windows、Linux 间交换方便的优势,但部分 PetaLinux 2022.2 内核实现不支持常规fallocate()。项目因此实现了专用的文件池管理流程:
- 标准顺序零填充预分配;
- 快速预分配模式
--fast-prepare; - FIEMAP 不可用时的 FIBMAP/簇级映射;
- 64 位物理块号映射;
- 支持一个文件由多个连续物理区间组成;
- 保存
.partial.map物理映射缓存; - 后续采集快速加载并校验缓存;
- 已准备文件池可通过
capture --overwrite重复使用; - 可通过
precondition对保留区间进行首次写入预热。
文件池把耗时的空间分配和映射工作移到正式采集之前,使采集阶段只执行必要的 NVMe 数据写入和文件切换操作。
6. 多文件无间断采集
系统支持将长时间采集任务切分成多个固定容量文件。当前文件完成后:
- 确认全部数据已经写入;
- 将文件从
.partial转为.bin; - 切换到下一个已准备好的文件;
- 保持 PL 缓冲和 NVMe 命令流水线继续运行。
这种方式兼顾了超大容量连续记录和后处理便利性,也避免单个超大文件损坏后影响整段数据。
7. 可验证的数据完整性
当前adc_gen支持多通道模拟和 64 位单调帧序列。4 个 16 位通道共同组成一个 64 位帧号:
CH0 = sequence[15:0] CH1 = sequence[31:16] CH2 = sequence[47:32] CH3 = sequence[63:48]每次显式复位后可从新的伪随机初始值开始,校验程序自动读取首帧作为基准,并逐帧检查:
- 是否丢帧;
- 是否重复;
- 是否倒退或乱序;
- 文件内部是否连续;
- 多文件边界是否连续。
相比简单的递增 16 位计数,这种模式可以覆盖更长时间的连续采集,并准确定位错误发生的字节偏移和帧位置。接入真实 ADC 后,也建议在数据帧中保留硬件帧号和时间戳。
五、软件与设备接口
Linux 启动后,主要设备节点为:
/dev/pl_capture0 PL采集控制设备 /dev/ipropnvme0 PL侧NVMe块设备配套工具包括:
| 工具 | 作用 |
|---|---|
pl_capture_ctl | 配置、启动、停止、复位和读取采集状态 |
pl_direct_writer | 单文件 PL DDR4 直写 |
pl_direct_pool.sh | 文件池准备、预热、测速、连续采集和校验 |
pl_capture_verify | ADC 序列及完整性校验 |
pl_direct_test.sh | 单文件端到端测试 |
一个典型的使用流程如下:
# 1. 快速准备文件池sudopl_direct_pool.sh prepare --fast-prepare\-b/dev/ipropnvme0-m/mnt/nvme0\-n4096-c400-C4-pad_data# 2. 可选:首次触达目标LBA,使SSD进入稳定写入状态sudopl_direct_pool.sh precondition\-b/dev/ipropnvme0-m/mnt/nvme0\-n4096-c400-C4-pad_data# 3. 执行连续采集sudopl_direct_pool.sh capture\-b/dev/ipropnvme0-m/mnt/nvme0\-n4096-c400-C4-pad_data# 4. 全文件数据完整性校验sudopl_direct_pool.sh verify\-b/dev/ipropnvme0-m/mnt/nvme0\-n4096-c400-C4-pad_data-f# 5. 后续任务可直接覆盖并复用同一文件池sudopl_direct_pool.sh capture--overwrite\-b/dev/ipropnvme0-m/mnt/nvme0\-n4096-c400-C4-pad_data其中-n 4096表示每个文件包含 4096 个 1 MiB 缓冲块,即单文件容量为 4 GiB。具体参数应根据 SSD 容量、采集时长和文件管理策略调整。
六、实测表现
在当前工程和测试平台上,多文件长时间直写测试已经完成:
- 多个 4 GiB 文件连续切换;
overflow=0;error=0;- 完成文件连续生成;
- 测试界面观察到约 1907 MiB/s 的持续直写速度;
- 其他工程测试记录中,在不同采样率、SSD状态和预热条件下观察到约 1.9~2.2 GiB/s 的采集写入水平。
这些数值是特定 FPGA 时序、SSD 型号、盘内温度、剩余空间、SLC 缓存和文件池状态下的工程测试结果,不应直接视为所有 SSD 的保证指标。产品交付时应使用目标 SSD 完成稳态满盘、温升、掉电恢复和全文件序列校验。
需要特别区分三类带宽:
fio对已有文件或块设备的峰值并发写入带宽;- 文件池首次分配、簇映射和预热速度;
- 真实采集链路从 PL DDR4 到 SSD 的持续直写带宽。
三者经过的软件路径和硬件数据源不同,不能只用一次短时间fio峰值推断持续采集能力。
七、与传统 Linux 写文件方案对比
| 对比项 | 传统 PL→PS DDR→文件写入 | 本项目 PL DDR4→NVMe 直写 |
|---|---|---|
| 采集数据是否进入 PS DDR | 是 | 否 |
| 是否经过 Linux 页缓存 | 通常是 | 采集载荷不经过 |
| CPU 数据搬运压力 | 较高 | 较低 |
| 文件系统兼容性 | 好 | 保留 exFAT 文件兼容 |
| SSD 抖动吸收能力 | 依赖软件缓冲 | 8 GiB PL 环形缓冲 |
| 长时间文件切换 | 需要应用层处理 | 文件池自动切换 |
| 数据完整性验证 | 通常需自行开发 | 内置 64 位帧序列校验 |
| 环满行为 | 可能丢数据或阻塞 | 自动停止并锁存错误 |
八、适用场景
该平台适合持续数据率高、CPU 不宜参与数据搬运、同时又需要标准文件输出的场景,例如:
- 多通道高速 ADC 原始数据记录;
- 雷达回波、电子侦察和电子对抗;
- 软件无线电及宽带 IQ 数据采集;
- 高速相机、线阵成像和光电探测;
- 超声、振动、瞬态和工业无损检测;
- 高能物理及科研仪器;
- 网络数据记录和协议分析设备;
- 便携式或边缘侧高速数据记录仪。
九、工程可靠性设计
高速写入只是基础能力,真正可用的采集产品还必须能明确识别异常。本项目已经覆盖以下保护和诊断机制:
- PL DDR4 地址和描述符边界检查;
- producer/consumer/ready 实时监控;
- 环满停止,避免覆盖未落盘数据;
- NVMe 命令状态和 CID 完成匹配;
- 中断超时和异常退出处理;
.partial与.bin文件状态区分;- 多物理区间文件映射;
- 物理映射缓存边界校验;
- 多通道 64 位序列的全文件校验;
- 文件切换时的尾部缓冲释放;
- 用户态状态和错误码输出。
当前生成的 bitstream 已通过 Vivado 2022.2 布线后静态时序检查,报告显示建立时间和保持时间均满足约束。上板应用仍建议结合 ILA、寄存器状态、长时间温升和目标 SSD 做系统级验证。
十、当前版本边界
为了准确理解产品能力,当前单盘版本有以下边界:
- 当前工程实现一个 NVMe Host Core 和一个 SSD,尚未实现多盘 RAID0;
- exFAT 主要用于 Linux 与 Windows 间方便交换,快速预分配依赖项目配套驱动和工具;
- 8 GiB 环形缓冲可以吸收短时抖动,但不能弥补 SSD 长期平均速度低于采集源的问题;
- 当前数据源为
adc_gen,真实 ADC 需要接入标准 AXI4-Stream 采集接口; - 当前工程验证采用流式 DMA 一致性维护,设备树不应在硬件不支持一致性时随意加入
dma-coherent; - 活动中的
.partial文件在异常掉电后可能需要恢复或丢弃,严苛场景应增加掉电保持和文件系统恢复策略; - SSD 的持续写入能力与型号、温度、容量占用、固件和 NAND 类型密切相关。
多盘扩展在架构上可行,但需要为每块 SSD 配置独立 NVMe 控制通路、队列和中断,并在文件映射层增加条带化调度,属于下一阶段的 RAID0/多盘并行版本。
十一、项目价值
本项目并不是简单地给 FPGA 增加一个 NVMe 接口,而是把采集、缓存、块设备、文件系统和数据校验组成了一套完整链路:
可验证数据源 ↓ PL高速采集与DDR4环形缓存 ↓ NVMe并发命令与中断完成 ↓ exFAT文件池和物理映射 ↓ 多文件连续记录与完整性校验它兼顾了 FPGA 实时数据通路和 Linux 文件管理的优势,为 GB/s 级高速数据记录设备提供了一种可工程化、可验证、可扩展的实现方式。
