大俠好,歡迎來到FPGA技術江湖,江湖偌大,相見即是緣分。大俠可以關注FPGA技術江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。
今天給大俠帶來基于FPGA的實時圖像邊緣檢測系統設計,由于篇幅較長,分三篇。今天帶來第三篇,下篇,話不多說,上貨。
這里也超鏈接了上篇和中篇,方便各位大俠參考學習。
基于FPGA的實時圖像邊緣檢測系統設計(上)
基于FPGA的實時圖像邊緣檢測系統設計(中)
導讀
隨著科學技術的高速發展,FPGA在系統結構上為數字圖像處理帶來了新的契機。圖像中的信息并行存在,因此可以并行對其施以相同的操作,使得圖像處理的速度大大提高,這正好適合映射到FPGA架構中用硬件算法得以實現。
本篇闡述了基于FPGA設計一個能夠實時采集、實時處理并實時顯示的數字圖像處理系統的設計思想和流程,分析了攝像頭接口的時序;闡述了圖像信息的捕獲原理;詳細介紹了圖像邊緣檢測部分各模塊的功能;重點介紹了具有去噪功能的中值濾波模塊的設計;簡單描述了邊緣檢測算子的選用;系統的介紹了SDRAM的工作原理以及控制方式;介紹了VGA時序;最后針對整個系統做了驗證和總結,包括仿真波形的驗證以及板級驗證。
該系統基于實體FPGA開發板實現了圖像數據的實時采集、實時邊緣檢測和實時顯示,運行穩定,實時性能較高,從而也表明FPGA確實具有海量數據高速傳輸的能力。
本篇為本人當年的畢業設計部分整理,各位大俠可依據自己的需要進行閱讀,參考學習。
第三篇內容摘要:本篇會介紹系統驗證、結論以及各個模塊主要代碼,包括圖像實時采集模塊的主要代碼,圖像實時捕獲模塊的主要代碼,中值濾波模塊的主要代碼,邊緣檢測模塊的主要代碼,圖像緩存模塊的主要代碼,圖像實時顯示模塊的主要代碼等相關內容。
五、系統驗證
在本系統設計過程中,我以自頂向下的層次化設計思想為主進行系統的頂層架構設計,明確各模塊的功能以及各模塊之間的握手關系,之后分模塊編寫代碼并加以驗證,調試代碼使得各模塊功能得以實現,最后基于頂層模塊進行仿真驗證,如圖5-1和5-2為系統頂層模塊的仿真波形,其中圖5-1為全局波形,圖5-2為局部放大的波形。
圖5-1 系統頂層模塊的全局仿真波形
圖5-2 系統頂層模塊的局部仿真波形
隨后連接FPGA開發實驗板并更新其驅動程序,按照開發板的配置文件分配引腳,全編譯通過后下板進行板級測試。本系統驗證時所采用的開發板是實體FPGA開發板。
實體FPGA開發板采用的是Altera Cyclone IV代系列的EP4CE10E22C8N芯片。該開發板是一款FPGA圖像開發板,其核心芯片EP4CE10E22C8N擁有6272個邏輯單元和150個IO引腳,開發板上配置有VGA、USB、CMOS接口、SDRAM、按鍵、LED等很多種外部設備,可以作為本系統設計驗證的硬件工具。
實體FPGA開發板的主要參數如下表6-1所示。
表5-1 FPGA開發板的主要參數
下板結果表明我所設計的數字圖像邊緣檢測系統的功能已經實現,能夠實時采集圖像、實時處理并實時顯示,這里截取的是圖片,現實場景顯示可以根據攝像頭的移動實時顯示。
六、結論
本系統設計中,我基于FPGA驅動的主要設備如下:型號為Ov7725的攝像頭;具有通用性的VGA接口。同時,我研究了相關的邊緣檢測算法,為了數據處理結果更加準確,我還根據系統需要進行了圖像數據的預處理操作:先將彩色圖像轉換成為灰度文件;接著采用中值濾波技術對采集到的圖像數據進行了有效去噪。通過本系統的設計,我深刻理解了基于FPGA驅動外部設備的基本原理,掌握了基于FPGA、運用Verilog語言驅動外部設備和實現算法的能力,感受到了FPGA的先進,也進一步確定了自己的發展方向。在進行系統驗證時,基于FPGA開發板實現了圖像數據的實時采集、實時邊緣檢測和實時顯示,系統性能良好,實時性能較高,結果證明FPGA能夠輕松實現海量數據的高速傳輸。
附:部分主要代碼
圖像實時采集模塊的主要代碼:
1 module sccb_config_ctrl( 2 clk, //24Mhz輸入時鐘 3 rst_n, //系統復位 4 scl, //iic的時鐘線 5 sda, //iic的數據線 6 config_done //配置完成標志 7 ); 8 //系統輸入 9 input clk; //外部輸入時鐘24Mhz 10 input rst_n; //系統復位 11 //系統輸出 12 output reg scl; //iic的時鐘線 13 output reg config_done; //配置完成標志 14 15 16 inout sda; //iic的數據線 17 18 reg sda_buffer; //寫入數據的中間寄存器 19 reg flag; //控制系統是否占有總線控制權 20 reg [7:0] lut_cnt; //指針寄存器計數器 21 reg [15:0] lut_data; //寄存器地址和配置數據 22 reg [3:0] s; 23 24 assign sda = (flag) ? sda_buffer : 1'bz;//當flag為高電平時,系統擁有總線控制權 25 //并發送sda_buffer中的數據。當flag為低電平時, 26 //釋放總線。 27 28 //----------延時1ms計數器----------------- 29 reg [31:0] delay_cnt; 30 reg delay_done; 31 32 always @ (posedge clk or negedge rst_n) 33 begin 34 if(!rst_n) 35 begin 36 delay_done <= 0; 37 delay_cnt <= 0; 38 end 39 else if(delay_cnt == 20000) //23809 40 delay_done <= 1; 41 else 42 begin 43 delay_cnt <= delay_cnt + 1; 44 delay_done <= 0; 45 end 46 end 47 48 //----------------分頻產生400Khz時鐘clk_sys---------- 49 reg [7:0] count;//計數器 50 reg clk_sys;//系統時鐘 51 reg [5:0] state;//狀態寄存器 52 53 always @ (posedge clk or negedge rst_n) 54 begin 55 if (!rst_n) 56 begin 57 clk_sys <= 1'b1; 58 count <= 8'd0; 59 end 60 else 61 if (count < 100)//分頻成為近200K的時鐘 62 count <= count + 1; 63 else 64 begin 65 count <= 8'd0; 66 clk_sys <= ~clk_sys; 67 end 68 end 69 70 //------------------輸出scl------------- 71 always @ (negedge clk_sys or negedge rst_n) 72 begin 73 if (!rst_n) 74 begin 75 scl <= 1'b1;//復位時,scl為高 76 end 77 else 78 begin 79 if(config_done == 1 || delay_done == 0)//當總線忙的時候,scl為近400K的時鐘 80 scl <= 1; 81 else 82 scl <= ~scl;//空閑時,scl為高 83 end 84 end 85 86 reg [3:0] cnt;//發送或者接收數據的個數 87 reg [15:0] memory;//發送或者接受數據的中間寄存器 88 89 always @ (posedge clk_sys or negedge rst_n) 90 begin 91 if (!rst_n) 92 begin 93 config_done <= 0; 94 flag <= 1'b1; //復位時,系統獲得總線的控制權 95 sda_buffer <= 1'b1; //向iic的數據線上發送高電平 96 state <= 0; 97 cnt <= 0; 98 memory <= 16'd0; 99 lut_cnt <= 2; 100 s <= 0; 101 end 102 else 103 case(state) 104 0 :if(scl) 105 begin 106 if(delay_done)//延時標志信號拉高 107 begin 108 sda_buffer <= 1'b0; //發送啟動信號 109 state <= 1; 110 memory <= 16'h0042;//準備ID地址 111 end 112 else 113 state <= 0; 114 end 115 else 116 state <= 0; 117 118 1 :if((scl == 0) && (cnt < 8))//發送ID地址 119 begin 120 sda_buffer <= memory[7]; 121 cnt <= cnt + 1; 122 memory = {memory[14:0],memory[15]}; 123 state <= 1; 124 end 125 else 126 begin 127 if ((scl == 0) && (cnt == 8)) 128 begin 129 cnt <= 0; 130 flag <= 0;//釋放總線控制權 131 state <= 2; 132 end 133 else 134 begin 135 state <= 1; 136 end 137 end 138 139 2 : 140 if(scl)//在SCL高電平期間接收數據 141 begin 142 if(!sda)//檢測應答信號 143 begin 144 state <= 3; 145 memory <= lut_data;//指針寄存器地址 146 end 147 else 148 begin 149 state <= 0; 150 end 151 end 152 else 153 state <= 2; 154 155 3 : if((scl == 0) && (cnt < 8)) //發送指針寄存器地址 156 begin 157 flag <= 1;//獲得總線控制權 158 sda_buffer <= memory[15]; 159 cnt <= cnt + 1; 160 memory = {memory[14:0],memory[15]}; 161 state <= 3; 162 end 163 else 164 begin 165 if ((scl == 0) && (cnt == 8)) 166 begin 167 cnt <= 0; 168 flag <= 0;//釋放總線控制權 169 state <= 4; 170 end 171 else 172 begin 173 state <= 3; 174 end 175 end 176 177 4 : 178 if(scl) 179 begin 180 if(!sda)//檢測應答信號 181 begin 182 state <= 5; 183 end 184 else 185 begin 186 state <= 0; 187 end 188 end 189 190 5 : if((scl == 0) && (cnt < 8))//發送八位控制字 191 begin 192 flag <= 1; //獲得總線控制權 193 sda_buffer <= memory[15]; 194 cnt <= cnt + 1; 195 memory <= {memory[14:0],memory[15]}; 196 state <= 5; 197 end 198 else 199 begin 200 if ((scl == 0) && (cnt == 8)) 201 begin 202 cnt <= 0; 203 flag <= 0; //釋放總線控制權 204 state <= 6; 205 lut_cnt <= lut_cnt + 1; //指針寄存器+1 206 end 207 else 208 begin 209 state <= 5; 210 end 211 end 212 213 6 : 214 if(scl) //在SCL高電平期間,接收ACK 215 begin 216 if(!sda)//檢測應答信號 217 begin 218 state <= 7; 219 end 220 else 221 begin 222 state <= 0; 223 end 224 end 225 226 7 : if (scl == 0) 227 begin 228 flag <= 1; 229 sda_buffer <= 0;//拉低數據線(為發送停止信號做準備) 230 state <= 8; 231 end 232 else 233 state <= 7; 234 235 8 : if (scl == 1) //發送停止信號 236 begin 237 sda_buffer <= 1; 238 begin 239 if (s == 8) 240 begin 241 if(lut_cnt < 70) 242 begin 243 state <= 0; 244 s <= 0; 245 end 246 else 247 config_done <= 1; //配置完成 248 end 249 else 250 s <= s + 1; 251 end 252 end 253 else 254 state <= 8; 255 256 default : state <= 0; 257 endcase 258 end 259 260 always @ (*) 261 begin 262 case (lut_cnt) 263 // OV7725 : VGA RGB565 Config 264 //Read Data Index 265 // 0 : LUT_DATA = {8'h0A, 8'h77}; //Product ID Number MSB (Read only) 266 // 1 : LUT_DATA = {8'h0B, 8'h21}; //Product ID Number LSB (Read only) 267 0 : lut_data = {8'h1C, 8'h7F}; //Manufacturer ID Byte - High (Read only) 268 1 : lut_data = {8'h1D, 8'hA2}; //Manufacturer ID Byte - Low (Read only) 269 //Write Data Index 270 2 : lut_data = {8'h12, 8'h80}; // BIT[7]-Reset all the Reg 271 3 : lut_data = {8'h3d, 8'h03}; //DC offset for analog process 272 4 : lut_data = {8'h15, 8'h02}; //COM10: href/vsync/pclk/data reverse(Vsync H valid) 273 5 : lut_data = {8'h17, 8'h22}; //VGA: 8'h22; QVGA: 8'h3f; 274 6 : lut_data = {8'h18, 8'ha4}; //VGA: 8'ha4; QVGA: 8'h50; 275 7 : lut_data = {8'h19, 8'h07}; //VGA: 8'h07; QVGA: 8'h03; 276 8 : lut_data = {8'h1a, 8'hf0}; //VGA: 8'hf0; QVGA: 8'h78; 277 9 : lut_data = {8'h32, 8'h00}; //HREF / 8'h80 278 10 : lut_data = {8'h29, 8'hA0}; //VGA: 8'hA0; QVGA: 8'hF0 279 11 : lut_data = {8'h2C, 8'hF0}; //VGA: 8'hF0; QVGA: 8'h78 280 //如果不使用內部PLL,這個命令是無效的 281 12 : lut_data = {8'h0d, 8'h41}; //Bypass PLL 00:0 01:4x 10:6x 11:8x 282 13 : lut_data = {8'h11, 8'h01}; //CLKRC,Finternal clock = Finput clk*PLL multiplier/[(CLKRC[5:0]+1)*2] = 25MHz*4/[(x+1)*2] 283 //00: 50fps, 01:25fps, 03:12.5fps (50Hz Fliter) 284 14 : lut_data = {8'h12, 8'h06}; //BIT[6]: 0:VGA; 1;QVGA 285 //BIT[3:2]: 01:RGB565 286 //VGA: 00:YUV; 01:Processed Bayer RGB; 10:RGB; 11:Bayer RAW; BIT[7]-Reset all the Reg 287 15 : lut_data = {8'h0C, 8'h10}; //COM3: Bit[7:6]:Vertical/Horizontal mirror image ON/OFF, Bit[0]:Color bar; Default:8'h10 288 //DSP control 289 16 : lut_data = {8'h42, 8'h7f}; //BLC Blue Channel Target Value, Default: 8'h80 290 17 : lut_data = {8'h4d, 8'h09}; //BLC Red Channel Target Value, Default: 8'h80 291 18 : lut_data = {8'h63, 8'hf0}; //AWB Control 292 19 : lut_data = {8'h64, 8'hff}; //DSP_Ctrl1: 293 20 : lut_data = {8'h65, 8'h00}; //DSP_Ctrl2: 294 21 : lut_data = {8'h66, 8'h00}; //{COM3[4](0x0C), DSP_Ctrl3[7]}YUYV; 01:YVYU; [10:UYVY] 11:VYUY 295 22 : lut_data = {8'h67, 8'h00}; //DSP_Ctrl4:00/01: YUV or RGB; 10: RAW8; 11: RAW10 296 //AGC AEC AWB 297 23 : lut_data = {8'h13, 8'hff}; 298 24 : lut_data = {8'h0f, 8'hc5}; 299 25 : lut_data = {8'h14, 8'h11}; 300 26 : lut_data = {8'h22, 8'h98}; //Banding Filt er Minimum AEC Value; Default: 8'h09 301 27 : lut_data = {8'h23, 8'h03}; //Banding Filter Maximum Step 302 28 : lut_data = {8'h24, 8'h40}; //AGC/AEC - Stable Operating Region (Upper Limit) 303 29 : lut_data = {8'h25, 8'h30}; //AGC/AEC - Stable Operating Region (Lower Limit) 304 30 : lut_data = {8'h26, 8'ha1}; //AGC/AEC Fast Mode Operating Region 305 31 : lut_data = {8'h2b, 8'h9e}; //TaiWan: 8'h00:60Hz Filter; Mainland: 8'h9e:50Hz Filter 306 32 : lut_data = {8'h6b, 8'haa}; //AWB Control 3 307 33 : lut_data = {8'h13, 8'hff}; //8'hff: AGC AEC AWB Enable; 8'hf0: AGC AEC AWB Disable; 308 //matrix sharpness brightness contrast UV 309 34 : lut_data = {8'h90, 8'h0a}; 310 35 : lut_data = {8'h91, 8'h01}; 311 36 : lut_data = {8'h92, 8'h01}; 312 37 : lut_data = {8'h93, 8'h01}; 313 38 : lut_data = {8'h94, 8'h5f}; 314 39 : lut_data = {8'h95, 8'h53}; 315 40 : lut_data = {8'h96, 8'h11}; 316 41 : lut_data = {8'h97, 8'h1a}; 317 42 : lut_data = {8'h98, 8'h3d}; 318 43 : lut_data = {8'h99, 8'h5a}; 319 44 : lut_data = {8'h9a, 8'h1e}; 320 45 : lut_data = {8'h9b, 8'h3f}; //Brightness 321 46 : lut_data = {8'h9c, 8'h25}; 322 47 : lut_data = {8'h9e, 8'h81}; 323 48 : lut_data = {8'ha6, 8'h06}; 324 49 : lut_data = {8'ha7, 8'h65}; 325 50 : lut_data = {8'ha8, 8'h65}; 326 51 : lut_data = {8'ha9, 8'h80}; 327 52 : lut_data = {8'haa, 8'h80}; 328 //Gamma correction 329 53 : lut_data = {8'h7e, 8'h0c}; 330 54 : lut_data = {8'h7f, 8'h16}; // 331 55 : lut_data = {8'h80, 8'h2a}; 332 56 : lut_data = {8'h81, 8'h4e}; 333 57 : lut_data = {8'h82, 8'h61}; 334 58 : lut_data = {8'h83, 8'h6f}; 335 59 : lut_data = {8'h84, 8'h7b}; 336 60 : lut_data = {8'h85, 8'h86}; 337 61 : lut_data = {8'h86, 8'h8e}; 338 62 : lut_data = {8'h87, 8'h97}; 339 63 : lut_data = {8'h88, 8'ha4}; 340 64 : lut_data = {8'h89, 8'haf}; 341 65 : lut_data = {8'h8a, 8'hc5}; 342 66 : lut_data = {8'h8b, 8'hd7}; 343 67 : lut_data = {8'h8c, 8'he8}; 344 68 : lut_data = {8'h8d, 8'h20}; 345 //Others 346 69 : lut_data = {8'h0e, 8'h65};//night mode auto frame rate control 347 default : lut_data = {8'h1C, 8'h7F}; 348 endcase 349 end 350 351 endmodule
圖像實時捕獲模塊的主要代碼:
1 modulecoms_capture_rgb565(clk_cmos,rst_n,pclk,vsync,href,din,xclk, 2 frame_data, frame_clk, frame_href, frame_vsync, cmos_fps_rate); 3 4 input clk_cmos; //24Mhz驅動時鐘輸入 5 input rst_n; 6 input pclk; //輸入的像素時鐘 7 input vsync; //輸入場同步信號 8 input href; //輸入的行同步信號 9 input [7:0] din; //輸入的像素數據 10 11 output xclk; //輸出的CMOS Sensor的驅動時鐘 24Mhz 12 output frame_clk; //輸出拼接后的像素數據的時鐘 13 output [15:0] frame_data; //輸出拼接后的像素數據 14 output frame_href; //輸出同步的行同步信號 15 output frame_vsync; //輸出同步的場同步信號 16 output reg cmos_fps_rate; //輸出幀率 17 18 assign xclk = clk_cmos; 19 20 //-------------檢測場、行同步信號------------ 21 reg href_r, vsync_r; 22 always @(posedge pclk or negedge rst_n) 23 begin 24 if (!rst_n) 25 begin 26 href_r <= 1; 27 vsync_r <= 1; 28 end 29 else 30 begin 31 href_r <= href; 32 vsync_r <= vsync; 33 end 34 end 35 //行同步信號由低電平變為高電平時,說明數據有效 36 assign pose_href = (~href_r) & href; 37 //場同步信號由高電平變為低電平時,說明一幀數據接收完畢 38 assign nege_vsync = vsync_r & (~vsync); 39 40 //----------延時10幀產生一個標志編號---------- 41 reg frame_cnt_end; //延時10幀數據結束標志 42 reg [3:0] frame_cnt; //幀計數器 43 always @(posedge pclk or negedge rst_n) 44 begin 45 if(!rst_n) 46 begin 47 frame_cnt <= 0; 48 frame_cnt_end <= 0; 49 end 50 else if (frame_cnt == 10) 51 frame_cnt_end <= 1; 52 else if(nege_vsync) 53 frame_cnt <= frame_cnt + 1; 54 else 55 frame_cnt <= frame_cnt; 56 end 57 58 reg [15:0] din_buffer2; 59 reg [7:0] din_buffer1; 60 reg byte_flag; 61 reg [10:0] cnt; 62 always @(posedge pclk or negedge rst_n) 63 begin 64 if(!rst_n) 65 begin 66 byte_flag <= 0; 67 din_buffer1 <= 0; 68 din_buffer2 <= 0; 69 cnt <= 0; 70 end 71 else if(href) 72 begin 73 cnt <= cnt + 1; 74 din_buffer1 <= din; 75 if(cnt >= 1278) 76 byte_flag <= 0; 77 else 78 byte_flag <= ~byte_flag; 79 80 if(byte_flag == 1) 81 din_buffer2 <= {din_buffer1,din}; 82 else 83 din_buffer2 <= din_buffer2; 84 end 85 else 86 begin 87 byte_flag <= 0; 88 din_buffer1 <= 0; 89 din_buffer2 <= din_buffer2; 90 cnt <= 0; 91 end 92 end 93 94 reg byte_flag_r; 95 always@(posedge pclk or negedge rst_n) 96 begin 97 if(!rst_n) 98 byte_flag_r <= 0; 99 else 100 byte_flag_r <= byte_flag; 101 end 102 103 assign frame_data = frame_cnt_end & href ? din_buffer2 : 0; 104 assign frame_clk = frame_cnt_end ? byte_flag_r : 0; 105 assign frame_vsync = frame_cnt_end ? vsync_r : 1'b0; 106 assign frame_href = frame_cnt_end ? href_r : 1'b0; 107 108 reg [27:0] delay_cnt; 109 always@(posedge pclk or negedge rst_n) 110 begin 111 if(!rst_n) 112 delay_cnt <= 0; 113 else if(delay_cnt < 48000000 - 1'b1) 114 delay_cnt <= delay_cnt + 1'b1; 115 else 116 delay_cnt <= 0; 117 end 118 wire delay_2s = (delay_cnt == 48000000 - 1'b1) ? 1'b1 : 1'b0; 119 120 reg [8:0] cmos_fps_cnt; 121 always @(posedge pclk or negedge rst_n) 122 begin 123 if(!rst_n) 124 begin 125 cmos_fps_cnt <= 0; 126 cmos_fps_rate <= 0; 127 end 128 else if(delay_2s == 1'b0) 129 begin 130 cmos_fps_cnt <= nege_vsync ? cmos_fps_cnt + 1'b1 : cmos_fps_cnt; 131 cmos_fps_rate <= cmos_fps_rate; 132 end 133 else 134 begin 135 cmos_fps_cnt <= 0; 136 cmos_fps_rate <= cmos_fps_cnt[8:1]; 137 end 138 end 139 140 endmodule
中值濾波模塊的主要代碼:
1 module zhongzhilvbo (clk, rst_n, data_in, fifo_empty, data_out, wrreq, rdreq); 2 3 input clk; 4 input rst_n; 5 input [23:0] data_in; 6 input fifo_empty; 7 8 output [7:0] data_out; 9 output reg wrreq; 10 output reg rdreq; 11 12 reg [7:0] data [8:0]; 13 wire [7:0] data_n[8:0]; 14 reg shift; 15 16 assign data_out = data_n[4]; 17 18 always @ (posedge clk or negedge rst_n) 19 begin 20 if (!rst_n) 21 begin 22 data [8] <= 0; 23 data [7] <= 0; 24 data [6] <= 0; 25 data [5] <= 0; 26 data [4] <= 0; 27 data [3] <= 0; 28 data [2] <= 0; 29 data [1] <= 0; 30 data [0] <= 0; 31 end 32 else 33 begin 34 if (shift) 35 begin 36 data[8] <= data[5]; 37 data[7] <= data[4]; 38 data[6] <= data[3]; 39 data[5] <= data[2]; 40 data[4] <= data[1]; 41 data[3] <= data[0]; 42 data[2] <= data_in[23:16]; 43 data[1] <= data_in[15:8]; 44 data[0] <= data_in[7:0]; 45 end 46 end 47 end 48 49 reg compara_rst_n; 50 genvar i; 51 reg [7:0] temp; 52 reg temp_rst_n; 53 reg [3:0] count; 54 55 always @ (posedge clk or negedge temp_rst_n) 56 begin 57 if (!temp_rst_n) 58 begin 59 temp <= data [8]; 60 count <= 0; 61 end 62 else 63 begin 64 temp <= data[count]; 65 count <= count + 1; 66 end 67 68 end 69 generate 70 for (i = 0; i < 9; i = i + 1) 71 begin : compara 72 if (i == 0) 73 begin 74 comparaer u1(.clk(clk), .rst_n(compara_rst_n), .ex_data(temp), .up_data(8'hff), .self_data(data_n[i])); 75 end 76 else 77 begin 78 comparaer comparaer(.clk(clk), .rst_n(compara_rst_n), .ex_data(temp), .up_data(data_n[i-1]), .self_data(data_n[i])); 79 end 80 end 81 endgenerate 82 83 reg [2:0] state; 84 reg [3:0] cnt; 85 86 always @ (posedge clk or negedge rst_n) 87 begin 88 if (!rst_n) 89 begin 90 rdreq <= 0; 91 compara_rst_n <= 0; 92 wrreq <= 0; 93 state <= 0; 94 shift <= 0; 95 cnt <= 0; 96 temp_rst_n <= 0; 97 end 98 else 99 begin 100 case (state) 101 0 : begin 102 if (fifo_empty) 103 begin 104 state <= 0; 105 wrreq <= 0; 106 compara_rst_n <= 0; 107 end 108 else 109 begin 110 state <= 1; 111 rdreq <= 1; 112 wrreq <= 0; 113 compara_rst_n <= 0; 114 end 115 end 116 117 1 : begin 118 rdreq <= 0; 119 shift <= 1; 120 state <= 2; 121 end 122 123 2 : begin 124 shift <= 0; 125 temp_rst_n <= 1; 126 state <= 3; 127 end 128 129 3 : begin 130 if (cnt < 8) 131 begin 132 cnt <= cnt + 1; 133 compara_rst_n <= 1; 134 state <= 3; 135 end 136 else 137 begin 138 cnt <= 0; 139 temp_rst_n <= 0; 140 state <= 4; 141 end 142 end 143 144 4 : begin 145 wrreq <= 1; 146 state <= 0; 147 end 148 149 endcase 150 end 151 end 152 endmodule
邊緣檢測模塊的主要代碼:
1 module sob (clk, rst_n, data, result, fifo_wr, shift_en); 2 3 input clk; 4 input rst_n; 5 input [23:0] data; 6 input shift_en; 7 8 output reg [7:0] result; 9 output reg fifo_wr; 10 11 12 reg [7:0] O[-1:1][-1:1]; 13 reg signed [10:0] Dx, Dy; 14 15 function [10:0] abs ( input signed [10:0] x); 16 abs = x >=0 ? x : -x ; // 取x的絕對值 17 endfunction 18 19 always @ (posedge clk or negedge rst_n) 20 begin 21 if (!rst_n) 22 begin 23 result <= 8'd0; 24 Dx <= 0; 25 Dy <= 0; 26 end 27 else 28 begin 29 if ( shift_en ) 30 begin 31 result <= (abs(Dx) + abs(Dy))>>3 ;// 右移三位實現除以8的運算 32 Dx <= -$signed({3'b000, O[-1][-1]}) //-1* O[-1][-1] 33 +$signed({3'b000, O[-1][+1]}) //+1* O[-1][+1] 34 -($signed({3'b000, O[ 0][-1]}) //-2* O[ 0][-1] 35 <<1) 36 +($signed({3'b000, O[ 0][+1]}) //+2* O[ 0][+1] 37 <<1) 38 -$signed({3'b000, O[+1][-1]}) //-1* O[+1][-1] 39 +$signed({3'b000, O[+1][+1]}); //+1* O[+1][+1] 40 Dy <= $signed({3'b000, O[-1][-1]}) //+1* O[-1][-1] 41 +($signed({3'b000, O[-1][ 0]}) //+2* O[-1][0] 42 <<1) 43 +$signed({3'b000, O[-1][+1]}) //+1* O[-1][+1] 44 -$signed({3'b000, O[+1][-1]})//-1* O[+1][-1] 45 -($signed({3'b000, O[+1][ 0]}) //-2* O[+1][ 0] 46 <<1) 47 -$signed({3'b000, O[+1][+1]}); //-1* O[+1][+1] 48 O[-1][-1] <= O[-1][0]; 49 O[-1][ 0] <= O[-1][+1]; 50 O[-1][+1] <= data[23:16]; 51 O[ 0][-1] <= O[0][0]; 52 O[ 0][ 0] <= O[0][+1]; 53 O[ 0][+1] <= data[15:8]; 54 O[+1][-1] <= O[+1][0]; 55 O[+1][ 0] <= O[+1][+1]; 56 O[+1][+1] <= data[7:0]; 57 end 58 end 59 end 60 61 62 63 reg [2:0] state; 64 65 always @ (posedge clk or negedge rst_n) 66 begin 67 if (!rst_n) 68 begin 69 fifo_wr <= 1'b0; 70 state <= 0; 71 end 72 else 73 begin 74 case (state) 75 0 : begin 76 if (shift_en) 77 begin 78 state <= 2; 79 fifo_wr <= 0; 80 end 81 else 82 begin 83 state <= 0; 84 fifo_wr <= 0; 85 end 86 end 87 88 1 : begin 89 if (shift_en) 90 begin 91 fifo_wr <= 1'b1; 92 end 93 else 94 fifo_wr <= 0; 95 end 96 97 2 : state <= 3; 98 99 3 : state <= 4; 100 101 4 : state <= 1; 102 103 default : state <= 0; 104 105 endcase 106 end 107 end 108 109 endmodule
圖像緩存模塊的主要代碼:
1 `include "sdram_head.v" 2 3 module sdr_fsm(soft_rst_n, sys_clk, init_done, ref_done, rd_done, wr_done, ref_time, mux_sel, 4 init_rst_n, ref_rst_n, rd_rst_n, wr_rst_n, time_rst_n, int_addr, 5 local_rdreq, local_wrreq, local_ready,wr_ddr,rd_ddr,rd_finish, wr_finish,local_finish); 6 7 input soft_rst_n; 8 input sys_clk; 9 input init_done; 10 input ref_done; 11 input rd_done; 12 input wr_done; 13 input [9:0] ref_time; 14 input [24:0] wr_ddr; 15 input [24:0] rd_ddr; 16 17 // input [24:0] local_addr; 18 // output reg [31:0] local_rdata; 19 // input [31:0] local_wdata; 20 input local_rdreq, local_wrreq; 21 output reg local_ready,local_finish; 22 output reg rd_finish; 23 output reg wr_finish; 24 25 output reg [1:0] mux_sel; 26 output reg init_rst_n; 27 output reg ref_rst_n; 28 output reg rd_rst_n; 29 output reg wr_rst_n; 30 output reg time_rst_n; 31 // output reg [31:0] wr_data; 32 output reg [24:0] int_addr; 33 34 localparam s0 = 3'b000; 35 localparam s1 = 3'b001; 36 localparam s2 = 3'b010; 37 localparam s3 = 3'b011; 38 localparam s4 = 3'b100; 39 40 reg [2:0] state; 41 42 reg rd,rd_en; 43 44 always @ (posedge sys_clk) 45 begin 46 if (!soft_rst_n) 47 begin 48 rd <= 0; 49 end 50 else 51 begin 52 if (local_rdreq && rd_en) 53 rd <= local_rdreq; 54 else 55 if (!rd_en) 56 rd <= 0; 57 else 58 rd <= rd; 59 end 60 end 61 62 reg wr,wr_en; 63 64 always @ (posedge sys_clk) 65 begin 66 if (!soft_rst_n) 67 begin 68 wr <= 0; 69 end 70 else 71 begin 72 if (local_wrreq && wr_en) 73 wr <= local_wrreq; 74 else 75 if (!wr_en) 76 wr <= 0; 77 else 78 wr <= wr; 79 end 80 end 81 82 83 always @ (posedge sys_clk) 84 begin 85 if (!soft_rst_n) 86 begin 87 mux_sel <= `INIT; 88 init_rst_n <= 0; 89 ref_rst_n <= 0; 90 wr_rst_n <= 0; 91 rd_rst_n <= 0; 92 time_rst_n <= 0; 93 state <= s0; 94 // local_rdata <= 32'd0; 95 local_ready <= 0; 96 rd_finish <= 0; 97 wr_finish <= 0; 98 // wr_data <= 32'd0; 99 int_addr <= 25'd0; 100 wr_en <= 1; 101 rd_en <= 1; 102 local_finish <= 0; 103 end 104 else 105 case (state) 106 s0 : if (!init_done) 107 init_rst_n <= 1; 108 else 109 begin 110 init_rst_n <= 0; 111 mux_sel <= `REF; 112 time_rst_n <= 1; 113 state <= s1; 114 local_ready <= 1; 115 wr_en <= 1; 116 rd_en <= 1; 117 end 118 119 s1 : if ((ref_time < `ctREFR) && (!wr) && (!rd)) 120 state <= s1; 121 else if (rd) 122 begin 123 int_addr <= rd_ddr; 124 rd_rst_n <= 1; 125 mux_sel <= `READ; 126 local_ready <= 0; 127 rd_finish <= 0; 128 state <= s3; 129 rd_en <= 0; 130 end 131 else if (wr) 132 begin 133 int_addr <= wr_ddr; 134// wr_data <= local_wdata; 135 wr_rst_n <= 1; 136 mux_sel <= `WRITE; 137 local_ready <= 0; 138 wr_finish <= 0; 139 state <= s4; 140 wr_en <= 0; 141 end 142 else if (ref_time >= `ctREFR) 143 begin 144 ref_rst_n <= 1; 145 time_rst_n <= 0; 146 mux_sel <= `REF; 147 state <= s2; 148 local_ready <= 0; 149 local_finish <= 0; 150 end 151 152 s2 : if (!ref_done) 153 state <= s2; 154 else 155 begin 156 state <= s1; 157 time_rst_n <= 1; 158 ref_rst_n <= 0; 159 local_finish <= 1; 160 local_ready <= 1; 161 end 162 163 s3 : if (!rd_done) 164 state <= s3; 165 else 166 begin 167 local_ready <= 1; 168 rd_finish <= 1; 169 rd_rst_n <= 0; 170// local_rdata <= rd_data; 171 state <= s1; 172 rd_en <= 1; 173 end 174 175 s4 : if (!wr_done) 176 state <= s4; 177 else 178 begin 179 local_ready <= 1; 180 wr_finish <= 1; 181 wr_rst_n <= 0; 182 state <= s1; 183 wr_en <= 1; 184 end 185 186 default : state <= s0; 187 endcase 188 end 189 endmodule
圖像實時顯示模塊的主要代碼:
1 module lcd_driver 2 ( 3 //global clock 4 input clk, //system clock 5 input rst_n, //sync reset 6 7 //lcd interface 8 output lcd_dclk, //lcd pixel clock 9 output lcd_blank, //lcd blank 10 output lcd_sync, //lcd sync 11 output lcd_hs, //lcd horizontal sync 12 output lcd_vs, //lcd vertical sync 13 output lcd_en, //lcd display enable 14 output [15:0] lcd_rgb, //lcd display data 15 16 //user interface 17 output lcd_request, //lcd data request 18 output [10:0] lcd_xpos, //lcd horizontal coordinate 19 output [10:0] lcd_ypos, //lcd vertical coordinate 20 input [15:0] lcd_data //lcd data 21); 22`include "lcd_para.v" 23 24/******************************************* 25 SYNC--BACK--DISP--FRONT 26*******************************************/ 27//------------------------------------------ 28//h_sync counter & generator 29 reg [10:0] hcnt; 30 always @ (posedge clk or negedge rst_n) 31 begin 32 if (!rst_n) 33 hcnt <= 11'd0; 34 else 35 begin 36 if(hcnt < `H_TOTAL - 1'b1) //line over 37 hcnt <= hcnt + 1'b1; 38 else 39 hcnt <= 11'd0; 40 end 41 end 42 assign lcd_hs = (hcnt <= `H_SYNC - 1'b1) ? 1'b0 : 1'b1; 43 44//------------------------------------------ 45//v_sync counter & generator 46 reg [10:0] vcnt; 47 always@(posedge clk or negedge rst_n) 48 begin 49 if (!rst_n) 50 vcnt <= 11'b0; 51 else if(hcnt == `H_TOTAL - 1'b1) //line over 52 begin 53 if(vcnt < `V_TOTAL - 1'b1) //frame over 54 vcnt <= vcnt + 1'b1; 55 else 56 vcnt <= 11'd0; 57 end 58 end 59 assign lcd_vs = (vcnt <= `V_SYNC - 1'b1) ? 1'b0 : 1'b1; 60 61//------------------------------------------ 62//LCELL LCELL(.in(clk),.out(lcd_dclk)); 63 assign lcd_dclk = ~clk; 64 assign lcd_blank = lcd_hs & lcd_vs; 65 assign lcd_sync = 1'b0; 66 67//----------------------------------------- 68 assign lcd_en = (hcnt >= `H_SYNC + `H_BACK && hcnt < `H_SYNC + `H_BACK + `H_DISP) && 69 (vcnt >= `V_SYNC + `V_BACK && vcnt < `V_SYNC + `V_BACK + `V_DISP) 70 ? 1'b1 : 1'b0; 71 assign lcd_rgb = lcd_en ? (lcd_data > 5) ? 16'd0 : 16'hffff : 16'd0; 72////assign lcd_rgb = lcd_en ? {lcd_data[10:6],lcd_data[10:5],lcd_data[10:6]} : 16'd0; 73//assign lcd_rgb = lcd_en ? {lcd_data[7:3],lcd_data[7:2],lcd_data[7:3]} : 16'd0; 74//assign lcd_rgb = lcd_en ? lcd_data : 16'd0; 75 76//------------------------------------------ 77//ahead x clock 78 localparam H_AHEAD = 2'd1; 79 assign lcd_request = (hcnt >= `H_SYNC + `H_BACK - H_AHEAD && hcnt < `H_SYNC + `H_BACK + `H_DISP - H_AHEAD) && 80 (vcnt >= `V_SYNC + `V_BACK && vcnt < `V_SYNC + `V_BACK + `V_DISP) 81 ? 1'b1 : 1'b0; 82//----------------------------------------- 83//lcd xpos & ypos 84 assign lcd_xpos = lcd_request ? (hcnt - (`H_SYNC + `H_BACK - 1'b1)) : 11'd0; 85 assign lcd_ypos = lcd_request ? (vcnt - (`V_SYNC + `V_BACK - 1'b1)) : 11'd0; 86 endmodule
本篇到此結束,基于FPGA的實時圖像邊緣檢測系統設計介紹完畢,各位大俠,關注不迷路哦,有緣再見。
審核編輯:湯梓紅
-
FPGA
+關注
關注
1626文章
21666瀏覽量
601836 -
檢測系統
+關注
關注
3文章
947瀏覽量
43014 -
實時圖像
+關注
關注
0文章
7瀏覽量
8047
原文標題:基于FPGA的實時圖像邊緣檢測系統設計(附代碼)
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論