本原創文章由深圳市小眼睛科技有限公司創作,版權歸本公司所有,如需轉載,需授權并注明出處(www.meyesemi.com)
1. 實驗簡介
實驗目的:
? ? ? 實現 3X3 圖像矩陣對應 9 個像素點圖像數據的讀取。
實驗環境:
? ? ? Window11
? ? ? PDS2022.SP6.4
? ? ? Modelsim10.6c
? ? ? MatlabR2023b(可以用別的版本)
硬件環境:
? ? ? MES2L676-100HP
2. 實驗原理
? ? ??在數字圖像處理中,部分算法需根據每個像素點及其周圍一定范圍內的像素點數據進行計算,圖像矩陣的 生成至關重要。本系列圖像處理實驗主要采用 3X3 圖像矩陣實現對應圖像處理算法。
? ? ??例如一幅完整的 5X5 圖像如下圖所示,每個方格表示一個像素點,方格內的數字表示對應像素點的像素數據。
?
? ? ??3X3 圖像矩陣的行對應圖像一行中三個連續的像素點,3X3 圖像矩陣的列對應圖像一列中三個連續的像素點,矩陣的元素對應圖像的像素數據。在 5X5 的圖像中,按圖像的掃描方式從左到右,從上到下地獲取對應 3X3 圖像矩陣的數據
?
? ? ??在圖像處理算法中,若通過每個 3X3 圖像矩陣計算中心像素點的像素數據,為保證圖像分辨率不變,在圖 像左側兩列和上方兩行的位置對像素數據補“0”操作,如下圖所示:
?
? ? ? 基于以上分析,在圖像數據按行輸入的情況下,為獲取 3X3 圖像矩陣需同時輸出三行圖像中的數據,因此 采用 FPGA 的緩存資源(fifo/ram)將接收的每一行數據進行緩存,并且在輸出 3X3 圖像矩陣數據時輸出當前 第 n 行對應位置的數據、第 n-1 行對應位置的數據以及第 n-2 行對應位置的數據。另外,為緩存第 n-1 行圖像 數據和第 n-2 行圖像數據,需調用 2 個 fifo 緩存模塊,并且實現當前數據緩存到第 n-1 行圖像數據緩存 fifo, 從第 n-1 行圖像數據緩存 fifo 讀出后再緩存到第 n-2 行圖像數據緩存 fifo,確保 3X3 矩陣輸出時讀取兩個 fifo可同時獲得第 n-1 行和第 n-2 行的數據。FPGA 實現 3X3 圖像矩陣具體方案框圖如下:
?
按行輸入的圖像數據 video_data 在數據有效期間緩存到 fifo1,同時 fifo1 讀出一行數據進入 fifo2 緩存, 且 fifo2 同時讀出一行數據,若 fifo1 或 fifo2 為空則輸出 0。數據輸出過程如下圖所示:
?
此外,實現同時輸出連續三行圖像數據后,需注意所輸出的三個數據對應在一行中的位置保持一致。
3. 接口列表
以下為 matrix_3x3.v 模塊的接口列表。
?
4. 工程說明
4.1. 代碼模塊說明
3X3 圖像矩陣生成模塊代碼如下所示:
// 3x3 矩陣生成
module matrix_3x3
#(parameter IMG_WIDTH = 11'd1920,parameter IMG_HEIGHT = 11'd1080
)
(input wire video_clk,input wire rst_n,input wire video_vs,input wire video_de,input wire [7:0] video_data, // 3x3 矩陣輸出output wire matrix_de,output reg [7:0] matrix11,output reg [7:0] matrix12,output reg [7:0] matrix13,output reg [7:0] matrix21,output reg [7:0] matrix22,output reg [7:0] matrix23,output reg [7:0] matrix31,output reg [7:0] matrix32,output reg [7:0] matrix33
);// wire definewire [7:0] line3_data; // 第三行數據wire [7:0] line2_data; // 第二行數據wire [7:0] line1_data; // 第一行數據wire wr_fifo_en; // 寫 FIFO 使能wire rd_fifo_en; // 讀 FIFO 使能// reg definereg [10:0] x_cnt;reg [10:0] y_cnt;// 列計數always @(posedge video_clk or negedge rst_n) beginif (!rst_n)x_cnt <= 11'd0;else if (x_cnt == IMG_WIDTH - 1) // 計數一行x_cnt <= 11'd0;else if (video_de) // 數據有效x_cnt <= x_cnt + 1'b1;elsex_cnt <= x_cnt;end// 行計數always @(posedge video_clk or negedge rst_n) beginif (!rst_n)y_cnt <= 11'd0;else if (y_cnt == IMG_HEIGHT - 1 && x_cnt == IMG_WIDTH - 1) // 計數一幀y_cnt <= 11'd0;else if (x_cnt == IMG_WIDTH - 1) // 數據有效y_cnt <= y_cnt + 1'b1;elsey_cnt <= y_cnt;end
以上代碼根據模塊接口列表,定義模塊端口及對輸入數據進行行/列計數
// 3x3 矩陣 第一行和最后一行無法構成
assign wr_fifo_en = video_de && (y_cnt < IMG_HEIGHT-1);
assign rd_fifo_en = video_de && (y_cnt > 0);reg wr_fifo_en_1d;
reg [7:0] video_data_1d;always @(posedge video_clk or negedge rst_n) beginif (!rst_n) beginwr_fifo_en_1d <= 1'd0;video_data_1d <= 8'd0;endelse beginwr_fifo_en_1d <= wr_fifo_en;video_data_1d <= video_data;end
end// 通過兩個 FIFO 與當前的輸入一起構成 3x3 矩陣
assign line3_data = video_data_1d;// fifo1
fifo_line_buffer u1_fifo_line_buffer (.wr_clk (video_clk), // input.wr_rst (~rst_n), // input.wr_en (wr_fifo_en), // input.wr_data (video_data), // input [7:0].wr_full (), // output.almost_full (), // output.rd_clk (video_clk), // input.rd_rst (~rst_n), // input.rd_en (rd_fifo_en), // input.rd_data (line2_data), // output [7:0].rd_empty (u1_empty), // output.almost_empty() // output
);// fifo2
fifo_line_buffer u2_fifo_line_buffer (.wr_clk (video_clk), // input.wr_rst (~rst_n), // input.wr_en (wr_fifo_en_1d),// input.wr_data (line2_data), // input [7:0].wr_full (), // output.almost_full (), // output.rd_clk (video_clk), // input.rd_rst (~rst_n), // input.rd_en (rd_fifo_en), // input.rd_data (line1_data), // output [7:0].rd_empty (), // output.almost_empty() // output
);
以上代碼實現兩級 fifo 對圖像數據按行緩存。為確保三行數據輸出保持同步,需注意 fifo 讀出數據相較于 fifo 讀使能信號延時 1 個時鐘周期,因此 line3_data 數據需將當前輸入數據延遲 1 個時鐘周期,與 fifo 輸出的 line2_data 和 line1_data 保持同步,并且 fifo1 輸出數據寫入 fifo2 時也需要將 fifo1 的讀使能信號延時 1 個 時鐘周期再作為 fifo2 的寫使能信號。
// 數據延遲 de 延遲
reg video_de_d0;
reg video_de_d1;always @(posedge video_clk or negedge rst_n) beginif (!rst_n) beginvideo_de_d0 <= 1'd0;video_de_d1 <= 1'd0;endelse beginvideo_de_d0 <= video_de;video_de_d1 <= video_de_d0;end
end// 矩陣數據生成
always @(posedge video_clk or negedge rst_n) beginif (!rst_n) begin{matrix11, matrix12, matrix13} <= 24'd0;{matrix21, matrix22, matrix23} <= 24'd0;{matrix31, matrix32, matrix33} <= 24'd0;endelse if (video_de_d0) begin{matrix11, matrix12, matrix13} <= {matrix12, matrix13, line1_data};{matrix21, matrix22, matrix23} <= {matrix22, matrix23, line2_data};{matrix31, matrix32, matrix33} <= {matrix32, matrix33, line3_data};endelse begin{matrix11, matrix12, matrix13} <= 24'd0;{matrix21, matrix22, matrix23} <= 24'd0;{matrix31, matrix32, matrix33} <= 24'd0;end
end// 矩陣數據有效輸出
assign matrix_de = video_de_d1;
assign matrix_vs = video_vs;endmodule
以上代碼實現 3X3 圖像矩陣的生成。三行數據同時輸出,每一行的數據按“打拍”方式移位實現矩陣的位 置的移動,需注意輸出數據在生成矩陣時產生 1 個時鐘周期的延時,因此最終數據的矩陣有效信號 matrix_de 也需延時 1 個時鐘周期。
4.2. 代碼仿真
? ? ??在 modelsim 平臺,matrix_3x3 模塊的仿真激勵模塊 matrix_tb.v 生成 5x5 的圖像數據源,仿真分析結果如下:
5x5 的圖像數據源符合以下圖像示意圖:
3X3 圖像矩陣的生成符合預期。