FPGA设计篇之并行全排序
FPGA设计篇之并行全排序
- 写在前面
- 并行全排序算法原理
- 并行全排序算法RTL实现
- Test_Bench
- 仿真结果
- 写在最后
写在前面
在FPGA设计的过程中,有时候需要对一些数据进行排序,那么常见的排序算法有冒泡排序、并行全排序、双调排序等,它们之间的区别在这里就不进行过多的介绍,本文主要介绍并行全排序算法的原理以及RTL代码实现。
并行全排序算法原理
并行全排序算法,之所以叫并行全排序算法,是指其各个数据之间的比较的并行执行的。
并行全排序对于多少个数值的排序,都只需要2个时钟周期,但是随之需要排序数据个数的增加,其资源消耗呈指数上升。并行全排序算法排序的过程包括两个步骤:
(1)将数据中的每个数据与所有数据进行对比,如果对比结果为若为大于(a > \gt >b),则对比结果为1,否则,为0;
(2)将步骤一中每个数据与其他数据对比的结果相加,得到值即为对应的大小顺序;
比如:对四个值1、7、5、2进行排序,那么其结果如下图所示。
可见,这里是符合我们预期要求的。但是还有个疑问,如果这组数值中存在两个相等的数值,那么结果会怎么样?比如:对四个值1、7、5、2进行排序,那么其结果如下。
这时候,由于用于排序的四个值中有两个都为7,相等,也就导致了这两个值对应的2排序值都为2,这在我们设计的过程中往往是不允许的,因为在多数情况下,我们需要将这个排序值作为其他模块中作为位索引的参数,那么我们对这两个相等的值做出区分,给他们不同的排序值(给第1个7的排序值赋为2,第2个7的排序值赋为3或者是给第1个7的排序值赋为3,第2个7的排序值赋为2)。
那么,我们通过这样一个办法将其区分:假设第用于对比的值为第i个(i = 0 ~ 3),用于被对比的值为第j个(j = 0 ~ 3),当i > \gt >j时,对比采用大于等于( ⩾ \geqslant ⩾)符号进行对比,如果a ⩾ \geqslant ⩾b,则对比结果为1,否则,为0;而当i ⩽ \leqslant ⩽j时,对比采用大于( > \gt >)符号进行对比,如果a > \gt >b,则对比结果为1,否则,为0。按照这个方法对四个值:1、7、5、7再进行对比,得到排序值如下:
那么,这样的作用其实就是:如果用于排序的N个数值中,出现多个相等的值,则将原本序号更大的数值赋予更大的排序值。
并行全排序算法RTL实现
首先可以设计一个状态机,用于控制排序的进程,主要包括三个状态:初始化、排序、反转。
always @(posedge clk or negedge rst_n)if(!rst_n)FSM_state_sort <= Initial;else case(FSM_state_sort)Initial:beginif(sort_sig)FSM_state_sort <= Sort;elseFSM_state_sort <= Initial;endSort:beginif(cnt_sort == 1'd1)FSM_state_sort <= Convert;elseFSM_state_sort <= Sort;endConvert:beginFSM_state_sort <= Initial;enddefault: FSM_state_sort <= Initial;endcase
在这里,首先状态机处于初始化状态,如果排序信号sort_sig为高电平,则进入排序状态,而在排序状态下,我们需要进行两个操作:数据两两相比较和对某个数据与其他数据的比较结果进行求和,那么这里需要两个时钟周期,于是在这里设置一个计数器cnt_sort,如果计数器计数到1,则进入反转状态下,将原本每个数据的下标根据排序结果进行调换。
那么,对数值进行两两并行比较的RTL代码如下:
always @(posedge clk or negedge rst_n)if(!rst_n) begin //复位信号for(i=0;i<DN;i=i+1) begin temp[i] = 0;endendelse if(sort_sig) begin //排序开始信号for(i=0;i<DN;i=i+1) beginfor(j=0;j<DN;j=j+1) beginif(i>j) beginif(data_unsort[i*DW+:DW]>=data_unsort[j*DW+:DW]) temp[i][j] <= 1;else temp[i][j] <= 0;endelse beginif(data_unsort[i*DW+:DW]>data_unsort[j*DW+:DW])temp[i][j] <= 1;elsetemp[i][j] <= 0;endendendend
对比较结果求和代码如下:
always @(posedge clk or negedge rst_n)if(!rst_n) begin //复位信号sequence_sorted_temp <= 0;endelse if((FSM_state_sort == Sort) && (cnt_sort == 1'd0)) begin //序列初始化for(i=0;i<DN;i=i+1) beginsequence_sorted_temp[i*DW_sequence+:DW_sequence] <= i;endendelse if(cnt_sort == 1'd1) begin //更新序列for(i=0;i<DN;i=i+1) beginsequence_sorted_temp[i*DW_sequence+:DW_sequence] <= temp[i][0]+temp[i][1]+temp[i][2]+temp[i][3]+temp[i][4]+temp[i][5]+temp[i][6]+temp[i][7]; endendelsesequence_sorted_temp <= sequence_sorted_temp;
根据排序结果对原本每个数据对应的下标进行调换代码如下:
always @(posedge clk or negedge rst_n)if(!rst_n)sequence_sorted <= 0;else if(FSM_state_sort == Convert)for(i=0;i<DN;i=i+1) beginsequence_sorted[sequence_sorted_temp[i*DW_sequence+:DW_sequence]*DW_sequence+:DW_sequence] <= i; end elsesequence_sorted <= sequence_sorted;
Test_Bench
仿真代码如下。
`timescale 1ns/1ns
module tb_parallel_sort();//--------------------------------------------
//参数定义
//-------------------------------------------- parameter DW = 8; //数据位宽parameter DN = 8; //数据个数parameter DW_sequence = $clog2(DN); //序号位宽//--------------------------------------------
//端口定义
//-------------------------------------------- reg clk,rst_n;reg sort_sig;reg [DW*DN-1:0] data_unsort;wire [DW_sequence*DN-1:0] sequence_sorted;wire sort_finish;wire [DW_sequence-1:0] sequence_sorted_0;wire [DW_sequence-1:0] sequence_sorted_1;wire [DW_sequence-1:0] sequence_sorted_2;wire [DW_sequence-1:0] sequence_sorted_3;wire [DW_sequence-1:0] sequence_sorted_4;wire [DW_sequence-1:0] sequence_sorted_5;wire [DW_sequence-1:0] sequence_sorted_6;wire [DW_sequence-1:0] sequence_sorted_7;assign sequence_sorted_0 = sequence_sorted[0*DW_sequence+:DW_sequence];assign sequence_sorted_1 = sequence_sorted[1*DW_sequence+:DW_sequence];assign sequence_sorted_2 = sequence_sorted[2*DW_sequence+:DW_sequence];assign sequence_sorted_3 = sequence_sorted[3*DW_sequence+:DW_sequence];assign sequence_sorted_4 = sequence_sorted[4*DW_sequence+:DW_sequence];assign sequence_sorted_5 = sequence_sorted[5*DW_sequence+:DW_sequence];assign sequence_sorted_6 = sequence_sorted[6*DW_sequence+:DW_sequence];assign sequence_sorted_7 = sequence_sorted[7*DW_sequence+:DW_sequence];//--------------------------------------------
//初始信号值
//--------------------------------------------initial beginclk = 0;rst_n = 0;sort_sig = 1'b0;#5#10 rst_n = 1;#10 sort_sig = 1'b1;data_unsort[DW*0+:DW] = 'd29; //6data_unsort[DW*1+:DW] = 'd19; //2data_unsort[DW*2+:DW] = 'd9 ; //0data_unsort[DW*3+:DW] = 'd22; //3data_unsort[DW*4+:DW] = 'd27; //4data_unsort[DW*5+:DW] = 'd28; //5data_unsort[DW*6+:DW] = 'd92; //7data_unsort[DW*7+:DW] = 'd9 ; //1#10 sort_sig = 1'b0;#1600$stop;endalways #5 clk <= ~clk;//--------------------------------------------
//模块例化
//--------------------------------------------
parallel_sort
#( .DN (DN ),.DW (DW )
)
parallel_sort_inst
(.clk(clk),.rst_n(rst_n),.sort_sig(sort_sig),.data_unsort(data_unsort),.sequence_sorted(sequence_sorted),.sort_finish(sort_finish)
);endmodule
仿真结果
在这里我们以8个数为例,这8个数分别为: a 0 a_0 a0=29, a 1 a_1 a1=19, a 2 a_2 a2=9, a 3 a_3 a3=22, a 4 a_4 a4=27, a 5 a_5 a5=28, a 6 a_6 a6=92, a 7 a_7 a7=9。那么,对这组数据进行升序排列后的结果应该是 a 2 a_2 a2( a 7 a_7 a7)< a 1 a_1 a1< a 3 a_3 a3< a 4 a_4 a4< a 5 a_5 a5< a 0 a_0 a0< a 6 a_6 a6,运行Test_Bench,得到以下结果,可见与我们理论上排序的结果一致,且只需要3个时钟周期,仿真通过。
写在最后
并行全排序是一种使用面积换速度的排序算法,无论对于多大的数据集,其排序时间仅需3个时钟周期,但是对于数据集中数据个数的上升,其电路面积呈指数上升,所以对于含有少量数据的数据集的排序,并行全排序是一种可选的方案。
好了,上面就是关于FPGA中实现并行全排序的一些学习笔记,如果有疑义的地方欢迎评论区友好探讨学习!!!!!(RTL代码)
FPGA设计篇之并行全排序相关推荐
- FPGA设计篇之双调排序
FPGA设计篇之双调排序(Bitonic Sort) 一.写在前面 二.双调排序算法原理 2.1 双调序列 2.2 Batcher定理 2.3 双调排序算法 2.4 构造双调序列 三.双调排序算法RT ...
- FPGA设计篇之流水线思想
FPGA设计篇之流水线思想 一.写在前面 二.正文开始 2.1举个栗子 2.2.1情况一(组合逻辑) 2.1.2情况二(流水线设计) 2.1.4 小总结 2.2举第二个栗子 写在最后 一.写在前面 ...
- 读论文之《基于 FPGA 的并行全比较排序算法》
为什么介绍这种排序算法:最近在独立编写霍夫曼编码的verilog HDL设计程序,其中用到了排序模块,对一组数据进行排序,苦寻几天,最终找到了这个全新的适合硬件实现的排序算法,分享与此,以空间换时间的 ...
- 基于 FPGA 的并行全比较排序算法,topK
以空间换时间的并行排序算法. https://blog.csdn.net/Reborn_Lee/article/details/80469391 并行全比较排序算法介绍 排序是一种重要的数据运算,传统 ...
- 华为FPGA设计高级技巧xilnx篇-阅读笔记2
华为FPGA设计高级技巧xilnx篇-阅读笔记2 设计技巧 合理选择加法电路 串行进位与超前进位 使用圆括号处理多个加法器 IF语句和Case语句:速度与面积的关系. 减少关键路径的逻辑级数 通过等效 ...
- C#算法设计排序篇之04-选择排序(附带动画演示程序)
选择排序(Selection Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/681 访问. 选择排序是一种简 ...
- FPGA设计实战演练(高级技巧篇)
初学者,不太建议读这本书,你会感觉FPGA设计好复杂,等在你做过2个项目之后,在慢慢体会这些书里的设计理念,可能慢慢就懂了.
- FPGA设计-时序约束(上篇,理论篇)
最近想要同步CSDN和微信公众号的内容,各位看客们可以两边都关注一下,方便获取最新的信息.请扫描下面的的二维码添加关注,谢谢支持. 最近都在做ARM的方面学习工作,感觉有必要记录下来之前FPGA的工作 ...
- FPGA设计思想与技巧(转载)
题记:这个笔记不是特权同学自己整理的,特权同学只是对这个笔记做了一下完善,也忘了是从那DOWNLOAD来的,首先对整理者表示感谢.这些知识点确实都很实用,这些设计思想或者也可以说是经验吧,是很值得每一 ...
最新文章
- Latex常用数学符号
- JVM加载class文件的原理简述
- 实验结果报告与实验总结_教科版科学四年级上册实验报告
- 推荐10个Github热门Python库,非常实用!
- 前台特效(9)无限极分类折叠菜单
- 文件夹操作之判断是否存在(Directory)
- Spotify模式并非“敏捷涅磐”
- 博客园添加鼠标粒子吸附特效
- linux中如何设置用户自己的工作环境,Linux系统下设置用户登录环境
- Docker容器虚拟化与传统虚拟机比较
- Error in mounted hook: “TypeError: Cannot read properties of undefined (reading ‘i
- LRC软件测试简历,C语言 LRC歌词文件解析
- 如何在vim中打印出^M
- 从物联网到元宇宙 PPT
- windows10搭建DVWA靶场(新手向)
- 游戏史上80重要创新(原资料来自17173)
- 基于AD603的AGC电路
- 学测绘和计算机,测绘工程就业方向与前景 女生学测绘好找工作吗
- 《Read, Listen, and See: Leveraging Multimodal Information Helps Chinese Spell Checking》阅读记录
- Zookeepr分布式协调服务之基础铺垫(大数据工程师工作笔记)
热门文章
- Hadoop中的shuffle、partition和combiner
- 工具|MySQL、Redis、MongoDB网络抓包工具
- DevExpress 第三方控件汉化
- (六)多线程说学逗唱:线程的暂停与其优先级
- 首届微软研究峰会视频上线,快来查收你的独家观看指南!
- int linux 原子操作_Linux原子操作
- VBA如何遍历文件夹下面的所有文件
- 蚂蚁风险大脑亮相ATEC城市峰会:为数字经济时代做好“安全守护”
- 显示器切换服务器用什么键,电脑显示器切换器购买要注意什么 哪款电脑切换器好用...
- educoder数据结构 树 第1关:由双遍历序列构造二叉树