基於FPGA的非線性濾波器(三)
阿新 • • 發佈:2022-04-28
基於FPGA的非線性濾波器(三)
之並行全比較排序模組設計
由於排序運算在影象的行列方向上是同性的,因此,同時考慮首先進行一維影象方向上的排序,再對列方向上的行排序結果進行排序,即可得到一個視窗內的排序結果。
一維方向的排序運算模組,記為sort_1d。同樣地,對於最終的二維排序運算模組,記為sort_2d。
1.sort_1d模組設計
計算步驟如下:
(1)首先得到待排序的n個數據:這可以通過將資料流打n-1拍實現。
(2)進行全比較:當前資料與其他所有一次進行比較,並記錄比較結果,比較的過程需先考慮輸入次序問題。
(3)將(2)中的記錄結果進行相加:根據不同的比較寬度,相加工作可以通過多個時鐘完成。
(4)查詢(3)中相加結果按指定次序輸出:如果要實現中值濾波,中間索引號輸出,對於其他次序的濾波可以採用其他編號的資料輸出。
以1x3的排序單元為例,至少需要6個比較器、3個加法器和6個暫存器,其設計框圖如下圖所示。
其中OUT_ID為輸入訊號,進行判決輸出。例如對於種植濾波,選擇中間結果進行輸出。例如,設定我們的處理核為KSZ,則有
OUT_ID = KSZ>>1 中值濾波器
OUT_ID = 0 最大值濾波器
OUT_ID = KSZ-1 最小值濾波器
module sort_1d( rst_n, clk, din, din_valid, dout, dout_valid ); parameter DW = 14; parameter KSZ = 3; parameter OUT_ID = (KSZ>>1); //中值濾波器 parameter DW_MAX_NUM = 8; //輸入資料個數的最大位寬 input rst_n; input clk; input [DW-1:0] din; input din_valid; output [DW-1:0] dout; output dout_valid; reg [KSZ+3:0] din_valid_r; //輸入有效暫存器 reg [DW-1:0] din_r [0:KSZ+2]; //輸入資料暫存器 wire cmp_result [0:KSZ-1][0:KSZ-1]; //比較中間結果訊號 reg [7:0] cmp_sum[0:KSZ-1]; //三個比較和暫存器 reg [7:0] cmp_sum_r[0:KSZ-1]; reg [7:0] cmp_sum_r2[0:KSZ-1]; reg [DW-1:0] dout_temp; //輸出暫存器 //首先快取輸入資料和輸入有效資料,同時得到待排序的資料 //快取輸入資料 always @(posedge clk or negedge rst_n) begin if(~rst_n) begin din_r[0] <= {DW{1'b0}}; end else begin if(din_valid) din_r[0] <= din; end end generate begin : xhdl0 genvar i; for(i=1;i<=KSZ+2;i=i+1) begin always @(posedge clk or negedge rst_n) if(~rst_n) din_r[i] <= {DW{1'b0}}; else din_r[i] <= din_r[i-1]; end end endgenerate //快取輸入有效訊號 always @(posedge clk or negedge rst_n) if(~rst_n) din_valid_r <= {KSZ+4{1'b0}}; else din_valid_r <= (din_valid_r[KSZ+2:0],din_valid); //關鍵比較程式碼如下 //將第一個資料與其他資料做比較 結果存放在cmp_result[0]中 generate begin :xhdl1 genvar i; for(i=1;i<=KSZ-2;i=i+1) begin : cmp_1st assign cmp_result[0][i] = (din_r[0] >= din_r[i]) ? 1'b1: 1'b0; end end endgenerate //與自身的比較結果置0 assign cmp_result[0][0] = 1'b0; //其他資料比較電路 generate begin : xhl4 genvar i; for(i = 2; i <= KSZ; i = i+1) begin : cmp_others begin : xhdl2 genvar j; for(j = 1; j <= i-1; j = j+1) begin : cmp_previous assign cmp_result[i-1][j-1] = (din_r[i-1] > din_r[j-1]): 1'b1:1'b0; end end assign cmp_result[i-1][i-1] = 1'b0; begin : xhdl3 genvar j; for(j = i+1;j<=KSZ; j = j+1) begin assign cmp_result[i-1][j-1] <= (din_r[i-1] >= din_r[j-1]) ?1'b1:1'b0; end end end end end endgenerate //將比較結果相加 if(KSZ == 3) begin : sum_ksz_3 always @(posedge clk or negedge rst_n) if(~rst_n) begin cmp_sum[i] <=8'b0; cmp_sum_r[i] <= 8'b0; cmp_sum_r2[i] <= 8'b0; end else begin if(din_valid_r[KSZ-1]) begin cmp_sum_r[i] <= (cmp_result[i][0]) + (cmp_result[i][2]); cmp_sum_r2[i] <= cmp_result[i][1]; end if(din_valid_r[KSZ]) begin cmp_sum[i] <= cmp_sum_r[i] + cmp_sum_r2[i]; end end end //查詢目標值 generate if(KSZ == 3) begin : dout_ksz_3 always @(posedge clk or negedge rst_n) if(~rst_n) dout_temp <= {DW{1'b0}}; else begin if(din_valid_r[KSZ+1]) begin if(cmp_sum[0] == OUT_ID) dout_temp <= din_r[2]; else if(cmp_sum[1] == OUT_ID) dout_temp <= din_r[3]; else if(cmp_sum[2] == OUT_ID) dout_temp <= din_r[4]; end end end endgenerate //資料有效輸出 assign dout_valid = din_valid_r[KSZ+2]; assign dout = dout_temp; endmodule