基于FPGA+DSP数据采集平台DMA应用学习
基于FPGA+DSP数据采集平台DMA应用学习
- 项目背景
- 一、DMA原理分析
- 二、应用DMA必要性分析
- 三、DMA传输的优势
- 四、技能树分析
项目背景
前面我们基本确定了FPGA与DSP之间的通信方案,硬件接口选用EMIF接口,这个接口相对于SPI来说传输速率上限高,能够满足当前虚构的通信需求,为什么说是虚构的需求,因为现在只能大致确定通信速率应该是高于100MHz,数据量到底有多少也不太知道,但是这种东西肯定是越快越好呗,大不了就是两次传输之间间隔的时间控制一下。因为考虑到和DSP通信,所以也要针对性的考虑一下数据传输的方式。
一、DMA原理分析
DMA(Direct Memory Access,直接内存访问)的核心目标是:让外设与内存之间直接交换数据,无需 CPU 全程参与。其工作流程可简化为 3 步:
初始化配置
CPU 先给 DMA 控制器设置参数:传输方向(外设→内存 / 内存→外设)、源地址、目标地址、传输长度等。
独立传输
DMA 控制器向总线(如 PCIe、AXI)发起 “总线请求”,获得总线控制权后,直接根据配置的地址和长度,逐字节 / 块搬运数据。此时 CPU 可以执行其他任务,无需干预。
传输完成通知
数据传输结束后,DMA 控制器通过 “中断” 或 “寄存器标志” 通知 CPU,CPU 再进行后续处理(如校验数据、启动下一轮任务)。
简言之:DMA 是 “CPU 放权,专用控制器接管数据传输” 的机制,核心是减少 CPU 在数据搬运中的开销。
其实你不需要对DMA的原理有多么深的了解,你只需要知道DMA的工作模式,需要知道什么参数,DSP端是可以进行寄存器的配置来达到DMA的使用目的,同样FPGA端只需要配合,比如说用FIFO、DDR3这些准备好数据即可,甚至调用DMA的ip核进行通信。
二、应用DMA必要性分析
之前虽然知道DMA这个东西,比如在嵌入式32中的串口、SPI、 ADC中都有DMA模式,但是也只是仅限于知道这个名词,对这个模式有什么作用、优势以及原理都不清楚。所以我了解这个项目最开始的问题就是FPGA为什么需要DMA,因为FPGA本身就是并行处理的,不同的任务之间不耽误,并行操作。
下面是FPGA不进行DMA的一些缺陷:
资源占用与效率矛盾
FPGA 的逻辑单元(LUT、寄存器等)是有限的。如果用处理逻辑直接控制数据传输(比如通过状态机逐字节读写内存),会占用大量并行资源,导致实际可用于计算的资源减少。而 DMA 本质是专用的 “数据搬运引擎”,可以独立完成传输,让 FPGA 的并行逻辑专注于计算,避免 “一身二用”。
高带宽场景的刚需
FPGA 常用于高速数据场景(如雷达信号采集、高速通信接口、AI 加速器等),这些场景需要持续传输 GB 级甚至 TB 级数据(比如从 ADC 采集数据到 DDR 内存,或从 PCIe 接口读写主机内存)。
此时如果没有 DMA,FPGA 需要通过 “中断 - 响应” 方式逐批处理传输,会产生大量延迟(中断上下文切换、地址计算等),无法满足高带宽需求。而 DMA 支持连续地址传输、批量数据块搬运,能充分利用总线带宽。
与外部系统的协作规范
FPGA 很少作为独立系统存在,通常需要与 CPU、内存、外设组成混合系统(如 FPGA 通过 PCIe 连接 x86 主机,或通过 AXI 总线连接 ARM 核)。这些系统中,DMA 是标准化的数据交换机制—— 比如 PCIe 协议中,DMA 是设备与主机内存通信的默认方式,FPGA 作为 PCIe 从设备,必须支持 DMA 才能融入系统。
理解关键
FPGA本身不需要自己的DMA,FPGA是作为DSP的从设备,被动响应传输请求,是DSP端启动DMA控制器来批量读取FPGA的数据,所以就要求FPGA在得到响应后数据是一定准备好的,这时候可能就需要DMA ip核进行配合。
为什么使用DMA,最终绝大部分受益还是在DSP端,因为DSP端释放了CPU的压力,进而可以去配合其他算法进行处理。
三、DMA传输的优势
DSP CPU 直接逐个读取(无 DMA)
步骤:
① DSP CPU 执行指令:计算 FPGA 的 EMIF 地址(如 0x80000000)。
② 发送读请求(拉低 nRE,驱动地址),等待 FPGA 返回第一个数据。
③ 读取数据到 DSP 寄存器,再写入内存。
④ 重复步骤①-③,直到读完 256 个数据(每次都要重新计算地址、发送请求、等待响应)。
开销:
每个数据传输需要约 10-20 个 DSP 指令周期(地址计算、寄存器操作、等待 EMIF 响应)。
256 个数据总耗时 = 256 ×(指令周期 + EMIF 传输周期),其中大量时间浪费在 CPU 的指令执行和重复的控制信号交互上。
DSP DMA 批量读取(启用 DMA)
步骤:
① DSP CPU 只需初始化一次 DMA:设置源地址(FPGA 的 EMIF 数据区,0x80000000)、目的地址(DSP 内存,0x00800000)、传输长度(1KB=256×4 字节)、触发方式(如 FPGA 的 “数据就绪” 信号)。
② DMA 控制器自动发起传输:
一次性发送 “突发读请求”(EMIF 支持连续读取,只需一次地址设置,后续自动递增)。
连续读取 256 个数据,直接写入 DSP 内存,全程无需 CPU 干预。
③ 传输完成后,DMA 通过中断通知 CPU:“1KB 数据已就绪”。
开销:
CPU 仅在初始化和中断处理时消耗约 100 个指令周期,传输过程中 CPU 可完全脱离,去执行其他任务(如数据处理、控制逻辑)。
批量传输利用了 EMIF 的 “突发模式”,控制信号(地址、片选、读使能)只需切换一次,单位数据的传输时间大幅降低(总耗时≈EMIF 传输周期 ×256,几乎无额外开销)。
四、技能树分析
FPGA端要大概做哪些内容,针对性学习那些模块的使用:
FIFO / 双端口 RAM 使用:由于 ADC 是连续采集(如 100MSPS 采样率),而 DMA 是块传输(如每 1KB 传输一次),需用 FIFO 缓存数据:
当 FIFO 中的数据量达到预设阈值(如 80% 满),触发 “数据就绪” 信号,通知 DSP 可启动 DMA 传输。
若 FIFO 空 / 满,需产生状态标志(供 DSP 查询或触发中断),避免溢出 / 空读。
跨时钟域处理:若 ADC 采集时钟(如 100MHz)与 EMIF 通信时钟(如 50MHz)不同步,需用异步 FIFO 隔离,避免亚稳态。
EMIF 接口逻辑实现(核心中的核心)
协议时序适配:根据 DSP 的 EMIF 规范(如 TI C6000 系列的 EMIF 标准),实现符合要求的接口逻辑:
信号定义:地址线(A [23:0])、数据线(D [31:0])、控制信号(片选 nCE、读写使能 nWE/nRE、字节使能 BE [3:0] 等)。
时序约束:严格匹配 EMIF 的建立时间(setup time)、保持时间(hold time)、读写周期(access time),需通过 FPGA 的时序约束工具(如 Xilinx 的 XDC、Altera 的 SDC)保证。
从设备行为模拟:FPGA 在 EMIF 中作为 “从设备”(被 DSP 的 DMA 控制器访问),需实现:
当 DSP 的 DMA 发起读请求(nRE 有效)时,FPGA 从 FIFO 中读出数据并驱动到数据线上。
支持突发传输(Burst Transfer):EMIF 通常支持连续读(如一次读 16 个 32 位数据),FPGA 需在一次片选有效期间,自动递增内部地址(或连续从 FIFO 读出),配合 DSP 的突发传输以提升效率。
与 DSP 的握手控制
状态寄存器设计:在 FPGA 内部实现一组寄存器(通过 EMIF 可被 DSP 读写),包含:
数据就绪标志(bit0:1 表示 FIFO 数据量达标)。
FIFO 状态(bit1-2:空 / 半满 / 满)。
错误标志(bit3:FIFO 溢出 / 校验错误)。
中断信号:当数据就绪或出错时,通过 FPGA 的 GPIO 输出中断信号(如 INT)到 DSP,触发 DSP 的中断服务程序(替代 DSP 轮询状态寄存器,降低开销)。
总结一下就是这些:
硬件描述语言:Verilog(更常用)或 VHDL,能编写状态机(控制采集、缓存、传输流程)。
EMIF 协议:熟悉目标 DSP 的 EMIF 手册(如 TI 的《TMS320C66x EMIF User’s Guide》),理解时序参数和信号交互逻辑。
FPGA IP 核使用:掌握 FIFO、双端口 RAM 等 IP 核的配置(如 Xilinx 的 FIFO Generator、Altera 的 MegaWizard)。
时序约束与分析:能用工具(Vivado/Quartus)进行时序分析,确保 EMIF 接口的建立 / 保持时间满足要求(避免数据传输错误)。
跨时钟域处理:掌握异步 FIFO、握手信号同步(如两级寄存器)等方法,解决多时钟域问题。