在對圖像進行處理時經常用到矩陣操作,本篇博客介紹一下用兩個FIFO生成 3x3 矩陣的方法,並對其進行驗證。
要求:模擬一張分辨率為 10x5 的圖片,圖片的數據為 1~50,對其生成 3x3 矩陣,以便后面的圖像處理。
testbench:數據的使能和數據對齊,每隔 10 個數據就空閑小段時間,每隔 50 個數據又空閑一段時間,模仿圖像幀的樣子,如下所示:
一、計數器行列規划
數據是 1-50,分為 10 列 5 行,而數據本身是沒有行列概念的,因此要用兩個計數器對數據行列規划。
第一個計數器為 col_cnt,計10下。第二個計數器為 row_cnt,計5下。這樣數據就人為的划分成了10x5,如下圖所示:
二、調用兩個FIFO形成3行數據
1、生成一個同步 FIFO IP核,深度只要是超過 2 行的數據個數就行,例如這里一行數據個數是10個,FIFO的深度就選為32。模式選為 normal(standard)模式,其他信號都不勾選。
2、設計3x3模塊,調用兩次 FIFO IP 核,兩個FIFO寫數據相同,都是本模塊進來的數據 din,兩個FIFO的各種信號按后綴 1 和 2 來區分。兩個FIFO的讀寫信號示意圖如下所示:
這樣設置的話,從第 3 行 din 來開始,q_1、q_2 和新進來的數據din就能形成 3 行平行數據,代碼書寫如下:
assign wr_en_1 = (cnt_row < 4) ? din_vld : 1'b0; //不寫最后1行 assign rd_en_1 = (cnt_row > 0) ? din_vld : 1'b0; //從第1行開始讀 assign wr_en_2 = (cnt_row < 3) ? din_vld : 1'b0; //不寫最后2行 assign rd_en_2 = (cnt_row > 1) ? din_vld : 1'b0; //從第2行開始讀
3、這樣操作后生成的仿真波形如下所示:
由波形看到 din_r(din打了一拍)和 q_1、q_2 信號在第三行數據時變成了平行的三行數據。 din 信號需要打一拍是因為此次使用的FIFO模式為normal(standard)模式,給出其讀使能后過 1clk 后才出數據 q,因此 din 打了一拍后就能和 q_1、q_2 對齊了。如果 FIFO 使用的是 show-ahead(first word fall through)模式則不需要對 din 信號進行打拍就能對齊。
從波形中還可以得出一些信息:
(1)來前兩行數據時,din_r 和 q_1、q_2 形成的三行數據不完整,從第3行數據時才完整。
(2)din_r、q_1、q_2的順序和我們的數據排列相比是倒的,符合人的正常思維的順序是:q_2、q_1、din_r。
(3)形成3行數據后,由於FIFO選用的是 normal(standard)模式,din數據打了一拍,所以整個過程消耗了 1clk。
三、打 3 拍形成 3x3 矩陣
獲得了上述的波形后,我們采用打拍即可完成矩陣的生成,上面說了數據是倒的,因此選擇矩陣數據時把編號給正過來。
//矩陣數據選取,1clk //--------------------------------------------------- assign row_1 = q_2; assign row_2 = q_1; always @(posedge clk or negedge rst_n) begin if(!rst_n) row_3 <= 'd0; else row_3 <= din; end
這里 row_3 就是原本的 din_r,命名將順序正過來,后面打拍也就更能理解了。
//打拍形成矩陣,矩陣順序歸正,1clk //--------------------------------------------------- always @(posedge clk or negedge rst_n) begin if(!rst_n) begin {matrix_11, matrix_12, matrix_13} <= {8'd0, 8'd0, 8'd0}; {matrix_21, matrix_22, matrix_23} <= {8'd0, 8'd0, 8'd0}; {matrix_31, matrix_32, matrix_33} <= {8'd0, 8'd0, 8'd0}; end else begin {matrix_11, matrix_12, matrix_13} <= {matrix_12, matrix_13, row_1}; {matrix_21, matrix_22, matrix_23} <= {matrix_22, matrix_23, row_2}; {matrix_31, matrix_32, matrix_33} <= {matrix_32, matrix_33, row_3}; end end
最后形成的矩陣波形如下所示:
由波形見得,最后生成的矩陣是成功的,該矩陣的觀看順序是從上到下,一列一列的看,例如第一個矩陣是:{000,000,001},第二個矩陣是:{000,000,012}。此外由於矩陣是打拍形成的,也耗費了 1clk 。至此,我們的 3x3 矩陣就生成了,總共耗費 2clk,即兩個時鍾周期。
四、問題引出
如果只是做到這樣,其實已經能做圖像處理了,但是細細品味這些波形會發現很多小問題。我們會產生一些疑問:
(1)換行時的數據很怪,如第 4 行數據的第一個矩陣是{10,10,11,20,20,21,30,30,31},這是什么鬼?
(2)換幀時的數據更怪,雖然第一幀圖片前面的矩陣很多都是0,但第二幀圖片前面的矩陣很多都是上一幀圖片遺留的數據,怎么辦?
(3)這個矩陣進行圖像處理的實際效果怎么樣?
(4)show-ahead(first word fall through)模式的話又會是什么情況?
(5)對於上面的問題,有改進的辦法嗎?
這篇博客已經有些長度了,對這些問題我們下篇博客繼續分析!
參考資料:
[1]V3學院FPGA教程