在 FPGA 多通道 DMA 采集设计中,通过 collect_end 信号实现采集策略与数据搬运逻辑解耦的核心在于:将"何时停止采集"的决策权完全交给前级触发模块(策略层),而 DMA 引擎(执行层)仅响应统一的结束脉冲执行标准化的收尾流程,不感知具体的停止原因。
1. 核心解耦机制:统一接口抽象
collect_end 信号作为一个单周期脉冲,屏蔽了三种不同采集模式(瞬时、触发、实时)在停止条件上的巨大差异。DMA 状态机无需判断是"缓冲区满了"、"触发条件满足了"还是"上位机手动停止了",只需检测到该信号即进入统一的清理状态。
| 采集模式 | 策略层产生 collect_end 的时机 |
典型应用场景 | DMA 引擎的感知 |
|---|---|---|---|
| 瞬时采集 | 预定义缓冲区写满 (position == max_pos) |
单次快照、设备调试 | 仅收到一个结束脉冲 |
| 触发采集 | 触发事件发生后,采够后置数据量自动结束 | 示波器、故障捕获 | 仅收到一个结束脉冲 |
| 实时采集 | 上位机主动写入寄存器请求 (collect_endreq=1) |
连续监测、振动分析 | 仅收到一个结束脉冲 |
设计原理:触发模块决定"何时停",DMA 模块负责"怎么收尾"。两者通过单一信号握手,互不侵入内部逻辑 。
2. DMA 状态机收尾逻辑实现
当 DMA 引擎在 DMAWAIT 状态检测到 collect_end 信号时,执行以下标准化流程,确保数据完整性并安全退出:
2.1 残留数据清洗(防丢数据)
即使收到结束信号,DMA 也不会立即停止,而是优先检查跨时钟域 FIFO 中是否还有残留数据。若有,则发起最后一次非固定长度的 Burst 传输,将 FIFO 清空。
2.2 状态标记与退出
通过设置标志位 r_dma_numremain = 0 标记这是最后一次传输,传输完成后直接跳转至 IDLE 状态,不再进入循环等待或地址回卷逻辑,同时置位 r_dma_oksta 通知上位机读取。
Verilog 代码示例:
verilog
// DMA 状态机核心片段:处理 collect_end 信号
// 状态定义
localparam DMASTA_IDLE = 3'b000;
localparam DMASTA_DMAWAIT = 3'b001;
localparam DMASTA_DMAST = 3'b010;
localparam DMASTA_DMADO = 3'b100;
always @(posedge m_axi_clk or negedge rst_n) begin
if (!rst_n) begin
r_dmastate <= DMASTA_IDLE;
control_go <= 0;
r_dma_oksta <= 0;
end else begin
case (r_dmastate)
DMASTA_DMAWAIT: begin
// 核心解耦点:不关心 collect_end 来源,只响应结束动作
if (r_collect_end && (~r_dma_oksta)) begin
if (fifo_rdwn > 0) begin
// 场景 A: FIFO 有残留数据 -> 发起最后一次突发传输
r_buf_curDatNum_ch <= r_buf_curDatNum_ch + fifo_rdwn;
r_control_write_length <= fifo_rdwn; // 长度动态调整
r_dma_numremain <= 0; // 标记为最后一次传输
r_dmastate <= DMASTA_DMAST;
control_go <= 1; // 启动 AXI 传输
end else begin
// 场景 B: FIFO 已空 -> 直接结束,无需额外传输
r_dma_oksta <= 1; // 通知上位机完成
r_dmastate <= DMASTA_IDLE;
end
end
// 正常数据传输逻辑 (省略)...
end
DMASTA_DMADO: begin
if (control_done) begin
if (r_dma_numremain) begin
// 非最后一次传输:回到等待状态,可能继续循环
r_dmastate <= DMASTA_DMAWAIT;
// 地址回卷逻辑 (仅在非结束状态下生效)
if (buf_length_ch[ADDRESSWIDTH-1:4] == r_buf_curDatNum_ch)
r_buf_curDatNum_ch <= 0;
end else begin
// 最后一次传输完成:彻底结束
r_dmastate <= DMASTA_IDLE;
r_dma_oksta <= 1;
r_buf_curDatNum_ch <= 0;
end
control_go <= 0;
end
end
// IDLE 和 DMAST 状态逻辑 (省略)...
endcase
end
end
3. 双缓冲与模式无缝切换
解耦设计配合自动回卷 和半满标志,使得同一套硬件逻辑无需修改即可支持从单次快照到连续流式采集的所有场景:
- 实时采集模式 :
collect_end信号长期无效。当写指针到达缓冲区末尾时,硬件自动归零(回卷),并翻转DMA_half_flg。上位机利用半满标志实现 Ping-Pong 读写(读前半时写后半),实现无限循环采集 。 - 瞬时/触发模式 :一旦满足特定条件,策略层发出
collect_end。DMA 立即停止回卷逻辑,执行上述收尾流程,将数据定格在 DDR 中供上位机一次性读取。
效果对比:
| 特性 | 耦合设计 (传统) | 解耦设计 (collect_end 机制) |
|---|---|---|
| 状态机复杂度 | 高,需包含多种停止条件的判断分支 | 低,仅需处理"进行中"和"收尾"两种状态 |
| 模式切换成本 | 需重新编译或加载不同比特流/微码 | 仅需改变 collect_end 的产生逻辑,DMA 核不变 |
| 数据安全性 | 容易因状态跳转遗漏导致 FIFO 数据丢失 | 强制先清空 FIFO 再结束,保证数据零丢失 |
| 可扩展性 | 新增触发模式需修改 DMA 逻辑 | 新增模式只需在前级生成 collect_end 脉冲 |
这种设计实现了采集策略(业务逻辑)与数据搬运(底层机制)的彻底分离,是纯 FPGA 架构实现高灵活性数据采集系统的关键 。