4. CFAR工程实现与优化

在毫米波雷达信号处理链中,CFAR(恒虚警率检测)是连接距离-多普勒二维谱与目标点云的关键一步。算法本身并不复杂:对每个待检测单元(CUT),用其周围参考单元估计噪声功率,再乘以门限因子得到判决门限。但要把CFAR放到S32R这类嵌入式雷达SoC上跑出实时性,问题就从"算法对不对"变成了"数据怎么摆、指令怎么用、窗口怎么并行、延迟怎么压"。本节围绕NXP S32R平台上的BBE32与LAX两类加速资源,讨论CFAR的工程实现与优化路径。

一、CFAR在S32R上的计算特征

以最常见的CA-CFAR为例,设参考窗单侧长度为N,保护单元单侧长度为G,则每个CUT需要累加2N个参考单元的功率,再除以2N得到噪声均值估计,乘以门限因子α后与CUT功率比较。若距离-多普勒谱尺寸为256×64,则共有16384个CUT,每个CUT涉及约2N次乘加与一次除法。当N取8时,单帧CFAR的乘加量约为26万次,看似不大,但若用通用CPU逐点循环,配合频繁的边界判断与除法,单帧耗时很容易突破毫秒级,挤占后续聚类与跟踪的时间预算。

S32R的BBE32(Baseband Engine)是一类面向向量运算的DSP核,支持SIMD风格的并行乘加、比较与饱和运算;LAX(Lookup Accelerator)则更偏向查表、地址生成与数据搬运的硬件辅助。CFAR的优化本质,是把"逐点标量循环"改造成"向量化批处理+流水线搬运"。

二、滑动窗口并行化的核心思路

CA-CFAR的参考窗在距离维和多普勒维上滑动,相邻CUT的参考窗高度重叠。若对每个CUT独立累加,会重复计算大量相同单元。工程上常用两种并行化策略:

  • 前缀和(积分图)法:先对每一行(或每一列)做前缀和,则任意一段连续参考单元的累加可用两次前缀和相减得到。这样每个CUT的参考累加从2N次乘加降为2次减法,代价是额外一次前缀和扫描。对于256×64的谱,前缀和扫描约1.6万次加法,远小于逐点累加的26万次。
  • 向量滑动窗法:利用BBE32的向量寄存器,一次加载连续多个CUT的参考数据,通过向量移位与累加实现窗口滑动。相邻CUT之间只增减窗口边缘的单元,中间部分复用上一次的累加结果。

两种方法可以结合:先用前缀和把二维累加降维,再用BBE32向量指令批量处理多个CUT的除法与比较。实际工程中,前缀和法在内存访问上更规整,更适合LAX做地址生成与数据预取。

三、内存布局对性能的决定性影响

CFAR的访存模式是典型的"邻域访问":每个CUT要读取其左右(距离维)和上下(多普勒维)的参考单元。如果谱数据按行优先连续存放,距离维邻域访问是连续的,但多普勒维邻域访问会跨行,步长为一行宽度。这种跨步访问会显著降低缓存命中率,并让BBE32的向量加载无法对齐。

推荐的布局是分块+转置:将256×64的谱按距离维切成若干块(例如每块32个距离单元),块内先做距离维CFAR,再将块转置后做多普勒维CFAR。转置后,原本跨行的多普勒邻域变成连续访问。另一种做法是直接采用"距离-多普勒双缓冲"布局,把谱同时按行和按列各存一份,用空间换时间。在S32R的片上SRAM中,256×64的复数谱若用16位定点表示,单份约32KB,双份64KB,通常可以接受。

定点化建议:CFAR的功率计算涉及平方,动态范围较大。建议在平方前将I/Q从16位压缩到12位,平方后用32位累加,门限比较时再统一右移。这样既避免溢出,又保留足够信噪比。

四、BBE32与LAX的指令级配合

BBE32适合承担计算密集部分:向量乘加用于功率累加,向量比较用于门限判决,向量除法或倒数近似用于噪声均值归一化。LAX则适合承担地址生成与数据搬运:在CFAR循环开始前,用LAX预取下一块参考数据到片上缓冲,使BBE32的计算与数据搬运重叠。

一个典型的流水线是:LAX搬运第k块数据 → BBE32计算第k-1块的CFAR → 结果写入输出缓冲。这样计算单元不会因等待数据而空转。需要注意的是,LAX的预取深度要与BBE32的单块处理时间匹配,预取太浅会暴露访存延迟,太深则会挤占片上SRAM。

五、实时性约束与预算分配

假设雷达帧周期为50ms,信号处理链总预算为20ms,其中CFAR分配4ms。在256×64谱、N=8、G=2的配置下,若采用前缀和+BBE32向量化,单帧CFAR的指令周期数可控制在约200万周期以内。以S32R的BBE32运行在400MHz估算,约5ms,略超预算。此时需要进一步优化:将N从8降到6,或把多普勒维CFAR改为在距离维CFAR之后用更小的窗口处理,或对低多普勒区域降采样。这些取舍需要在检测概率与实时性之间做平衡。

S32R CFAR 工程实现:数据流与加速器配合 距离-多普勒谱 256 × 64 复数 16位定点 I/Q 分块 + 转置 距离维切块 32 转置后多普勒连续 LAX 加速器 地址生成 / 预取 双缓冲搬运 BBE32 向量核 前缀和 / 向量乘加 门限比较 / 判决 流水线时序(单帧内重叠执行) t=0 t=4ms LAX 搬运块 k LAX 搬运块 k+1 LAX 搬运块 k+2 LAX 搬运块 k+3 BBE32 空闲 BBE32 计算块 k BBE32 计算块 k+1 BBE32 计算块 k+2 输出:CFAR 检测点(距离、多普勒、功率) 实时性约束与调优杠杆 参考窗 N=8 → 6 | 保护单元 G=2 | 门限因子 α 由虚警率 Pfa 决定 | 分块大小 32 | 双缓冲深度 2 预算:帧周期 50ms,信号处理 20ms,CFAR 目标 ≤ 4ms | 超预算时优先降 N 或对低多普勒区降采样

六、一个可复用的实现检查清单

在把CFAR从MATLAB模型搬到S32R工程代码时,建议按以下顺序逐项确认,避免反复返工:

检查项关键问题判断依据
数据布局距离维与多普勒维是否都连续可向量化?BBE32向量加载是否对齐,跨步访问是否消除
定点位宽平方与累加是否溢出?用最大输入功率回放,检查累加器高位是否翻转
边界处理谱边缘CUT的参考窗是否越界?边缘区域单独用截断窗或镜像填充,避免读脏数据
门限因子α是否与定点缩放匹配?用已知Pfa的仿真数据验证虚警率偏差
流水线深度LAX预取是否覆盖BBE32计算时间?用周期计数器测量空转周期占比
实时性单帧CFAR是否在预算内?连续100帧统计最坏执行时间,而非平均值

最后需要强调,CFAR的优化不是孤立的。检测点数量会直接影响后续聚类与跟踪的计算量,门限因子偏松会带来大量虚警,偏紧则会漏检真实目标。工程上通常先用仿真确定满足检测概率与虚警率要求的参数组合,再在S32R上按上述路径做向量化与内存优化,最后用实车或暗室数据回归验证。只有把算法参数、数据布局、加速器指令和实时预算放在一起权衡,CFAR才能真正在S32R上稳定跑进帧周期。