• 正文
  • 相关推荐
申请入驻 产业图谱

【FPGA实战】:一个32路无符号数据并行排序模块的设计与实战

09/15 08:56
117
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、模块是做什么的?

图像处理雷达信号处理等场景中,经常需要对一批数据做排序求中值/最大最小值。传统冒泡、快排算法需要多周期迭代,实时性差。 sort_32_u8 模块,是一种基于计数排序思想的硬件实现,也常被称为“秩排序”,采用**全并行“秩排序”(Rank Sort)**架构,仅用 3 级流水线、3 个时钟周期就能完成 32 路 8bit 无符号数据的排序输出。

该架构的资源随 N² 增长:32 路数据需要 1024 个比较器和 32 个 5bit 加法树,N 扩大时资源消耗急剧上升,适合 N≤64 的中小规模排序;此外所有比较在同一拍完成,时序收敛压力较大,建议 DATA_WIDTH 较大时插入寄存器切割关键路径。

二、核心原理

秩排序的思想:每个数不需要和其他数交换位置,只需要数清有多少个数比自己小,这个数量就是它排序后的目标位置。

以数据 A 和数据 B 比较为例,A 的排名计数规则是:

    • A > B:A 得 1 分(B 排在 A 前面);A < B:A 得 0 分;A == B:

下标靠前的得 1 分,下标靠后的得 0 分

    ,这样保证相等元素也能占据不同位置,避免冲突。

对应代码中 pipe1 的逻辑:

if(din[j] < din[i])      pipe1_flag[j][i] <= 0;
else if(din[j] == din[i]) begin
    if(j >= i) pipe1_flag[j][i] <= 0;
    else       pipe1_flag[j][i] <= 1;
end
else pipe1_flag[j][i] <= 1;

三、三级流水线架构

1、比较阶段

Pipe1(并行比较):32×32 = 1024 个比较器同时工作,两两比较生成标志矩阵 pipe1_flag[j][i],同时锁存数据 pipe1_din

    模块内部通过两重循环构建了一个 32×32 的比较器阵列。对于每一个输入数据 din[j],它与其他所有数据 din[i] 进行比较。pipe1_flag[j][i] 存储比较结果:如果 din[j] > din[i],则置1;如果相等,根据索引 j 和 i 的关系决定(这里实现的是逆序稳定排序,即如果数值相等,索引靠后的元素会被排在前面);如果 din[j] < din[i],则置0。本质上,这个 flag 的累加值代表了 din[j] 在所有数据中“大于”其他元素的个数。

2、求和阶段

Pipe2(排名汇总):对每个数据按行累加 32 个标志位,得到排名值 pipe2_flag_sum[j](范围 0~31),并通过 pipe1_valid_sum 全与逻辑确保数据整体有效;

    pipe2_flag_sum[j] 对第 j 行的所有比较结果 pipe1_flag[j][0...31] 进行求和。这个和就是 din[j] 在最终有序数组中的目标索引(Rank)。例如,和为0表示它是最小的,和为31表示它是最大的。经过这一级后,知道了每个数据应该被放到哪个位置

3、重排输出阶段

Pipe3(按名次分发):把每个数据写入以自己的排名为索引的位置

    根据计算出的索引 pipe2_flag_sum[k],将 pipe2_din[k] 放入 pipe3_din 数组的对应位置。输出 dout 直接连接 pipe3_din。
pipe3_din[pipe2_flag_sum[j]] <= pipe2_din[j];

4、关键特性

排名 0 的数落到 pipe3_din[0],排名 31 的落到 pipe3_din[31],输出天然有序(升序)。

    排序顺序:升序(小 -> 大)。dout_0 是最小值,dout_31 是最大值。流水线结构:模块为典型的 3 级流水线结构(Pipe1: 比较与锁存, Pipe2: 求和与锁存, Pipe3: 重排与锁存)。延迟:从 vld_in 有效到 vld_out 有效,固定延迟为 3 个时钟周期。数据处理:全并行处理,32个数据同时进入,排序后同时输出。

四、典型应用场景

中值滤波:图像 3×3、5×5 滤波的加速实现,取排序后中间值即可去除椒盐噪声;

运动目标检测:背景建模中取某区域的中值/分位数作为背景值;

Top-K 挑选:雷达恒虚警(CFAR)检测中筛选最强回波;

流水线化数据处理:由于是纯组合+寄存器结构,数据可以背靠背连续输入,吞吐率达每周期一批数据(本例 valid 控制下为 3 周期延迟的高吞吐流水线)。

五、仿真验证

Testbench 的设计思路:

随机激励:生成 10 组 0~255 随机数据,同时驱动 DUT 输入端口和 tb_i_data_inarray 数组;

黄金参考模型:编写 bubble_sort 任务对同一组数据做软件排序,生成期望结果 ref_sorted

自动比对:将 32 个输出端口拼成 tb_o_data_outarray 数组,等待 o_data_out_valid 拉高后逐项比对,统计 error_count

边界用例:额外增加全 0 输入测试,验证相等元素处理逻辑不冲突、无竞争。

if (tb_o_data_outarray[i] !== ref_sorted[i]) begin
    $display("Mismatch at index %0d ...", i);
    error_count = error_count + 1;
end

六、如何获取?

关注公众号:我是小灰灰的FPGA,关注我,带你从入门到精通数字逻辑设计。

后台回复(建议复制粘贴):sort_32_u8

相关推荐