大俠好,歡迎來到FPGA技術(shù)江湖,江湖偌大,相見即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。
今天給大俠帶來基于FPGA的實時圖像邊緣檢測系統(tǒng)設(shè)計,由于篇幅較長,分三篇。今天帶來第三篇,下篇,話不多說,上貨。
這里也超鏈接了上篇和中篇,方便各位大俠參考學習。
基于FPGA的實時圖像邊緣檢測系統(tǒng)設(shè)計(上)
基于FPGA的實時圖像邊緣檢測系統(tǒng)設(shè)計(中)
隨著科學技術(shù)的高速發(fā)展,F(xiàn)PGA在系統(tǒng)結(jié)構(gòu)上為數(shù)字圖像處理帶來了新的契機。圖像中的信息并行存在,因此可以并行對其施以相同的操作,使得圖像處理的速度大大提高,這正好適合映射到FPGA架構(gòu)中用硬件算法得以實現(xiàn)。
本篇闡述了基于FPGA設(shè)計一個能夠?qū)崟r采集、實時處理并實時顯示的數(shù)字圖像處理系統(tǒng)的設(shè)計思想和流程,分析了攝像頭接口的時序;闡述了圖像信息的捕獲原理;詳細介紹了圖像邊緣檢測部分各模塊的功能;重點介紹了具有去噪功能的中值濾波模塊的設(shè)計;簡單描述了邊緣檢測算子的選用;系統(tǒng)的介紹了SDRAM的工作原理以及控制方式;介紹了VGA時序;最后針對整個系統(tǒng)做了驗證和總結(jié),包括仿真波形的驗證以及板級驗證。
該系統(tǒng)基于實體FPGA開發(fā)板實現(xiàn)了圖像數(shù)據(jù)的實時采集、實時邊緣檢測和實時顯示,運行穩(wěn)定,實時性能較高,從而也表明FPGA確實具有海量數(shù)據(jù)高速傳輸?shù)哪芰Α?/p>
本篇為本人當年的畢業(yè)設(shè)計部分整理,各位大俠可依據(jù)自己的需要進行閱讀,參考學習。
第三篇內(nèi)容摘要:本篇會介紹系統(tǒng)驗證、結(jié)論以及各個模塊主要代碼,包括圖像實時采集模塊的主要代碼,圖像實時捕獲模塊的主要代碼,中值濾波模塊的主要代碼,邊緣檢測模塊的主要代碼,圖像緩存模塊的主要代碼,圖像實時顯示模塊的主要代碼等相關(guān)內(nèi)容。
五、系統(tǒng)驗證
在本系統(tǒng)設(shè)計過程中,我以自頂向下的層次化設(shè)計思想為主進行系統(tǒng)的頂層架構(gòu)設(shè)計,明確各模塊的功能以及各模塊之間的握手關(guān)系,之后分模塊編寫代碼并加以驗證,調(diào)試代碼使得各模塊功能得以實現(xiàn),最后基于頂層模塊進行仿真驗證,如圖5-1和5-2為系統(tǒng)頂層模塊的仿真波形,其中圖5-1為全局波形,圖5-2為局部放大的波形。
圖5-1 系統(tǒng)頂層模塊的全局仿真波形
?圖5-2 系統(tǒng)頂層模塊的局部仿真波形
隨后連接FPGA開發(fā)實驗板并更新其驅(qū)動程序,按照開發(fā)板的配置文件分配引腳,全編譯通過后下板進行板級測試。本系統(tǒng)驗證時所采用的開發(fā)板是實體FPGA開發(fā)板。
實體FPGA開發(fā)板采用的是Altera Cyclone IV代系列的EP4CE10E22C8N芯片。該開發(fā)板是一款FPGA圖像開發(fā)板,其核心芯片EP4CE10E22C8N擁有6272個邏輯單元和150個IO引腳,開發(fā)板上配置有VGA、USB、CMOS接口、SDRAM、按鍵、LED等很多種外部設(shè)備,可以作為本系統(tǒng)設(shè)計驗證的硬件工具。
實體FPGA開發(fā)板的主要參數(shù)如下表6-1所示。
表5-1 FPGA開發(fā)板的主要參數(shù)
下板結(jié)果表明我所設(shè)計的數(shù)字圖像邊緣檢測系統(tǒng)的功能已經(jīng)實現(xiàn),能夠?qū)崟r采集圖像、實時處理并實時顯示,這里截取的是圖片,現(xiàn)實場景顯示可以根據(jù)攝像頭的移動實時顯示。
六、結(jié)論
本系統(tǒng)設(shè)計中,我基于FPGA驅(qū)動的主要設(shè)備如下:型號為Ov7725的攝像頭;具有通用性的VGA接口。同時,我研究了相關(guān)的邊緣檢測算法,為了數(shù)據(jù)處理結(jié)果更加準確,我還根據(jù)系統(tǒng)需要進行了圖像數(shù)據(jù)的預(yù)處理操作:先將彩色圖像轉(zhuǎn)換成為灰度文件;接著采用中值濾波技術(shù)對采集到的圖像數(shù)據(jù)進行了有效去噪。通過本系統(tǒng)的設(shè)計,我深刻理解了基于FPGA驅(qū)動外部設(shè)備的基本原理,掌握了基于FPGA、運用Verilog語言驅(qū)動外部設(shè)備和實現(xiàn)算法的能力,感受到了FPGA的先進,也進一步確定了自己的發(fā)展方向。在進行系統(tǒng)驗證時,基于FPGA開發(fā)板實現(xiàn)了圖像數(shù)據(jù)的實時采集、實時邊緣檢測和實時顯示,系統(tǒng)性能良好,實時性能較高,結(jié)果證明FPGA能夠輕松實現(xiàn)海量數(shù)據(jù)的高速傳輸。
附:部分主要代碼
圖像實時采集模塊的主要代碼:
1 module sccb_config_ctrl(
2 clk, //24Mhz輸入時鐘
3 rst_n, //系統(tǒng)復(fù)位
4 scl, //iic的時鐘線
5 sda, //iic的數(shù)據(jù)線
6 config_done //配置完成標志
7 );
8 //系統(tǒng)輸入
9 input clk; //外部輸入時鐘24Mhz
10 input rst_n; //系統(tǒng)復(fù)位
11 //系統(tǒng)輸出
12 output reg scl; //iic的時鐘線
13 output reg config_done; //配置完成標志
14
15
16 inout sda; //iic的數(shù)據(jù)線
17
18 reg sda_buffer; //寫入數(shù)據(jù)的中間寄存器
19 reg flag; //控制系統(tǒng)是否占有總線控制權(quán)
20 reg [7:0] lut_cnt; //指針寄存器計數(shù)器
21 reg [15:0] lut_data; //寄存器地址和配置數(shù)據(jù)
22 reg [3:0] s;
23
24 assign sda = (flag) ? sda_buffer : 1'bz;//當flag為高電平時,系統(tǒng)擁有總線控制權(quán)
25 //并發(fā)送sda_buffer中的數(shù)據(jù)。當flag為低電平時,
26 //釋放總線。
27
28 //----------延時1ms計數(shù)器-----------------
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 //----------------分頻產(chǎn)生400Khz時鐘clk_sys----------
49 reg [7:0] count;//計數(shù)器
50 reg clk_sys;//系統(tǒng)時鐘
51 reg [5:0] state;//狀態(tài)寄存器
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;//復(fù)位時,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;//發(fā)送或者接收數(shù)據(jù)的個數(shù)
87 reg [15:0] memory;//發(fā)送或者接受數(shù)據(jù)的中間寄存器
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; //復(fù)位時,系統(tǒng)獲得總線的控制權(quán)
95 sda_buffer <= 1'b1; //向iic的數(shù)據(jù)線上發(fā)送高電平
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; //發(fā)送啟動信號
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))//發(fā)送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;//釋放總線控制權(quán)
131 state <= 2;
132 end
133 else
134 begin
135 state <= 1;
136 end
137 end
138
139 2 :
140 if(scl)//在SCL高電平期間接收數(shù)據(jù)
141 begin
142 if(!sda)//檢測應(yīng)答信號
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)) //發(fā)送指針寄存器地址
156 begin
157 flag <= 1;//獲得總線控制權(quán)
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;//釋放總線控制權(quán)
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)//檢測應(yīng)答信號
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))//發(fā)送八位控制字
191 begin
192 flag <= 1; //獲得總線控制權(quán)
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; //釋放總線控制權(quán)
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)//檢測應(yīng)答信號
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;//拉低數(shù)據(jù)線(為發(fā)送停止信號做準備)
230 state <= 8;
231 end
232 else
233 state <= 7;
234
235 8 : if (scl == 1) //發(fā)送停止信號
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 //如果不使用內(nèi)部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]}:00: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? module?coms_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驅(qū)動時鐘輸入
5 input rst_n;
6 input pclk; //輸入的像素時鐘
7 input vsync; //輸入場同步信號
8 input href; //輸入的行同步信號
9 input [7:0] din; //輸入的像素數(shù)據(jù)
10
11 output xclk; //輸出的CMOS Sensor的驅(qū)動時鐘 24Mhz
12 output frame_clk; //輸出拼接后的像素數(shù)據(jù)的時鐘
13 output [15:0] frame_data; //輸出拼接后的像素數(shù)據(jù)
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 //行同步信號由低電平變?yōu)楦唠娖綍r,說明數(shù)據(jù)有效
36 assign pose_href = (~href_r) & href;
37 //場同步信號由高電平變?yōu)榈碗娖綍r,說明一幀數(shù)據(jù)接收完畢
38 assign nege_vsync = vsync_r & (~vsync);
39
40 //----------延時10幀產(chǎn)生一個標志編號----------
41 reg frame_cnt_end; //延時10幀數(shù)據(jù)結(jié)束標志
42 reg [3:0] frame_cnt; //幀計數(shù)器
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 ;// 右移三位實現(xiàn)除以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
本篇到此結(jié)束,基于FPGA的實時圖像邊緣檢測系統(tǒng)設(shè)計介紹完畢,各位大俠,關(guān)注不迷路哦,有緣再見。