FPGA篇(三)基于FPGA的几种排序算法
目錄
1??????冒泡法和比較排序法
1.1????????算法原理
1.2????????仿真結果
1.3????????算法優缺點
2??????并行全比較排序法
2.1????????算法原理及Verilog實現
2.2????????仿真結果
2.3????算法優缺點
3??????串行全比較排序法
3.1????????算法原理及Verilog實現
3.2???????仿真結果
3.3???????算法優缺點
2??????總結
?
最近筆者在項目中正好遇到需要排序的情況,以前剛接觸C語言的時候排序的方法主要有冒泡排序、選擇排序等方法;于是就用Verilog實現了冒泡法,但是發現此方法和選擇排序法需要的時間周期太長,比如16個數據差不多需要136個周期才能完成排序,于是筆者在網上找到了并行全比較排序法和改進的串行全比較排序法;以下將一一介紹。
?
1??????冒泡法和比較排序法
?
1.1????????算法原理
?
這兩種方法比較容易理解,下面給出兩種排序方法的百科連接,大家可以自行百度。
冒泡排序:
https://baike.baidu.com/item/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F
?
?
選擇排序:
https://baike.baidu.com/item/%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F%E6%B3%95/2304587?fr=aladdin
?
1.2????????仿真結果
?
????????下面給出冒泡法的Verilog仿真結果,藍色箭頭是輸入的原始數據,紅色箭頭所指的是排完序的數據,黃色箭頭指的是排序所用的時間,仿真用的是100MHz的始終,所以冒泡總共需要136個周期。
?
1.3????????算法優缺點
?
????選擇排序法和冒泡法屬于傳統的兩兩比較的算法,但是消耗的周期比較長,在一些對實時性要求較高的情況下無法滿足要求。
?
2??????并行全比較排序法
2.1????????算法原理及Verilog實現
????????傳統的排序方式是以兩兩之間順序比較為基礎,而并行全比較實時排序算法是基于序列中任意兩個數并行比較實現。由于從原來的串行比較變成了并行比較,所以需要消耗比以前多的比較器,詮釋了FPGA中“用面積換速度”的思想。以序列長度為m的數據為例:
A:????第一個時鐘周期:將其中一個數據和其他數據在一個周期中一一比較,比較器分三種情況:
????1.????????這個數據大于其他數據,則它的得分為0;
????2.????????這個數據等于其他數據,若它在這個序列中比和它相等的其他數據靠前,則它的得分為0,反之為1;
????3.????????這個數據小于其他數據,則它的得分為1;
//-------------------------- 計算得分 ----------------------------------generategenvar i;for(i=1;i<=COL_WIDTH;i=i+1)begin:unfold_ialways@(posedge clk or posedge rst)beginif(rst)begin comp_valid_i[i] <= 0;score_i[i] <= 0; endelse if(comp_valid_f)beginif(comp_data[col] > comp_data[i])score_i[i] <= 0;else if(comp_data[col] == comp_data[i])beginif(col <= i) //如果有兩個相同的數據,其中若輸入順序在前面則排序就靠前score_i[i] <= 0;elsescore_i[i] <= 1;endelse score_i[i] <= 1;comp_valid_i[i] <= comp_valid_f;endelsebeginscore_i[i] <= 0;comp_valid_i[i] <= 0;endendendendgenerate?
?
B:第二個時鐘周期:將每個數據和其他數據比較后的數據累加;
?
?
always@(posedge clk or posedge rst)beginif(rst)beginscore <= 0; // score_t[1]<=0; // score_t[2]<=0;location <= 0;add_cnt <= 0;data_o <= 0;valid_o <= 0;endelse if(comp_valid_j[1] == 1)beginadd_cnt <= 0; // add_cnt <= 1; // score_t[1] <= ( score_j[1]+score_j[2] ) + ( score_j[3]+score_j[4] ); // score_t[2] <= ( score_j[5]+score_j[6] ) + ( score_j[7]+score_j[8] );score <= ( ( score_j[1]+score_j[2] ) + ( score_j[3]+score_j[4] ) )+( ( score_j[5]+score_j[6] ) + ( score_j[7]+score_j[8] ) )+( ( score_j[9]+score_j[10] ) + ( score_j[11]+score_j[12] ) )+( ( score_j[13]+score_j[14] ) + ( score_j[15]+score_j[16] ) )+ 1;location <= {row[7:0],col[7:0]};//行,列data_o <= comp_data[col];//數據valid_o <= 1;end end?
C: 第三個時鐘周期:將每個數據根據自己的得分賦值給新的數組(若得分為1的就賦值給數組中的第一個數,2就賦值給新的數組中第二個數);
?
//--------------------------------------------------------------------------------always@(posedge clk or posedge rst)beginif(rst)beginsort_done <= 0; //數據的坐標 endelse if(valid_o[1])beginchn[score[1]] <= data_o[1]; //重新排列的數據 chn[score[2]] <= data_o[2]; //重新排列的數據chn[score[3]] <= data_o[3]; //重新排列的數據chn[score[4]] <= data_o[4]; //重新排列的數據chn[score[5]] <= data_o[5]; //重新排列的數據chn[score[6]] <= data_o[6]; //重新排列的數據chn[score[7]] <= data_o[7]; //重新排列的數據chn[score[8]] <= data_o[8]; //重新排列的數據chn[score[9]] <= data_o[9]; //重新排列的數據chn[score[10]] <= data_o[10]; //重新排列的數據chn[score[11]] <= data_o[11]; //重新排列的數據chn[score[12]] <= data_o[12]; //重新排列的數據chn[score[13]] <= data_o[13]; //重新排列的數據chn[score[14]] <= data_o[14]; //重新排列的數據chn[score[15]] <= data_o[15]; //重新排列的數據chn[score[16]] <= data_o[16]; //重新排列的數據sort_done <= 1;endelsebeginsort_done <= 0;endend?
D:? 第四個時鐘周期:將新數組輸出;
?
經過以上四個步驟,即可將算法完成。
?
2.2????????仿真結果
?
????????如上圖所示,紅色箭頭代表著輸入數據,其中紅色的圈標記出輸入相同的兩個數據;黃色箭頭為每個數據與別的數據比較后的得分,得分越小則代表這個數據越大,其中黃色部分是第一個數據和第二個數據的得分,這兩個數據的大小是一樣的,但是第一個數據輸入數組中比第二個數據靠前,所以它的得分低一分,這也驗證了我們設計邏輯上在是正確的;藍色箭頭則代表的是排完序的輸出序列,經觀察發現結果正確。
?
2.3????算法優缺點
l? 優點:并行比較排序方式在實時性上有明顯的優勢,只需要四個時鐘周期就可以排序完成;
l? 缺點:
????????1.????????由于是并行比較消耗了較多的資源,而且在第二個時鐘周期(得分累加)需要大量的加法器級聯,考慮到路徑延遲、建立保持時間和時鐘抖動,一個時鐘周期許多個加法器級聯會有問題;
????????2.????????在代碼可移植性方面也有欠缺,比如若序列大小改變,在第二個和第三個時鐘周期的時候就需要人為修改多處代碼;
?
3??????串行全比較排序法
3.1????????算法原理及Verilog實現
????????串行全比較排序法在并行全比較排序法做了一些改進,將原來并行全比較排序法的前三個周期由并行轉變為串行,但是可以在比較的同時將得分累加,所以串行全比較排序法排序需要的周期是2*m(m個序列)個周期。
//--------------------------------------------------------------------------------always@(posedge clk or posedge rst)beginif(rst)begincomp_cnt <= COL_WIDTH + 1;score <= 1;valid_o <= 0;endelse if(comp_cnt <= COL_WIDTH)begincomp_cnt <= comp_cnt + 1;if(comp_data[col] > comp_data[comp_cnt])score <= score;else if(comp_data[col] == comp_data[comp_cnt])beginif(col <= comp_cnt)score <= score;elsescore <= score + 1;endelse score <= score + 1;if(comp_cnt == COL_WIDTH) valid_o <= 1;else valid_o <= 0;endelse if(valid_r)begincomp_cnt <= 1;score <= 1;valid_o <= 0;endelsebegincomp_cnt <= comp_cnt;score <= score;valid_o <= 0;endend //-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------always@(posedge clk or posedge rst)beginif(rst)beginsort_count <= COL_WIDTH + 1;sort_done <= 0;endelse if(sort_count <= COL_WIDTH)beginsort_count <= sort_count + 1;comp_data_index[score[sort_count]] <= comp_data[sort_count]; //這邊改成DPR_RAMif(sort_count == COL_WIDTH)sort_done <= 1;else sort_done <= 0;endelse if(valid_o[1])beginsort_count <= 1;sort_done <= 0;endelsebeginsort_count <= sort_count;sort_done <= 0;endend //--------------------------------------------------------------------------------3.2???????仿真結果
?
?
?
?
?
????????如上圖所示,紅色箭頭代表著輸入數據;黃色箭頭為每個數據與別的數據比較后的得分;藍色箭頭則代表的是排完序的輸出序列,經觀察發現結果正確。
????????從圖中可以讀出排序需要的時間是330ns,由于仿真采用的時鐘是100MHz,所以串行全比較算法需要33個時鐘周期(大約2*n個周期)。
3.3???????算法優缺點
串行全比較算法和并行全比較算法比較:
l? 優點:
????????1.????????資源消耗的比較少;
????????2.????????代碼可移植性好,序列變化只需要改變幾個參數,不需要大規模修改代碼;
l? 缺點:
????????串行全比較算法所消耗的時間比并行全比較算法長。
2??????總結
l? 代碼可移植性:傳統串行排序算法>串行全比較排序法>并行全比較排序法
l??資源使用:傳統串行排序算法<串行全比較排序法<并行全比較排序法
l? 排序時間:并行全比較排序法<串行全比較排序法<傳統串行排序算法
?
總結
以上是生活随笔為你收集整理的FPGA篇(三)基于FPGA的几种排序算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FPGA篇(一) 基于verilog
- 下一篇: Matlab篇(一)Matlab操作技巧