今天给大侠带来基于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; //外部输入时钟24Mhz10 input rst_n; //系统复位11 //系统输出12 output reg scl; //iic的时钟线13 output reg config_done; //配置完成标志141516 inout sda; //iic的数据线1718 reg sda_buffer; //写入数据的中间寄存器19 reg flag; //控制系统是否占有总线控制权20 reg [7:0] lut_cnt; //指针寄存器计数器21 reg [15:0] lut_data; //寄存器地址和配置数据22 reg [3:0] s;2324 assign sda = (flag) ? sda_buffer : 1'bz;//当flag为高电平时,系统拥有总线控制权25 //并发送sda_buffer中的数据。当flag为低电平时,26 //释放总线。2728 //----------延时1ms计数器-----------------29 reg [31:0] delay_cnt;30 reg delay_done;3132 always @ (posedge clk or negedge rst_n)33 begin34 if(!rst_n)35 begin36 delay_done <= 0;37 delay_cnt <= 0;38 end39 else if(delay_cnt == 20000) //2380940 delay_done <= 1;41 else42 begin43 delay_cnt <= delay_cnt + 1;44 delay_done <= 0;45 end46 end4748 //----------------分频产生400Khz时钟clk_sys----------49 reg [7:0] count;//计数器50 reg clk_sys;//系统时钟51 reg [5:0] state;//状态寄存器5253 always @ (posedge clk or negedge rst_n)54 begin55 if (!rst_n)56 begin57 clk_sys <= 1'b1;58 count <= 8'd0;59 end60 else61 if (count < 100)//分频成为近200K的时钟62 count <= count + 1;63 else64 begin65 count <= 8'd0;66 clk_sys <= ~clk_sys;67 end68 end6970 //------------------输出scl-------------71 always @ (negedge clk_sys or negedge rst_n)72 begin73 if (!rst_n)74 begin75 scl <= 1'b1;//复位时,scl为高76 end77 else78 begin79 if(config_done == 1 || delay_done == 0)//当总线忙的时候,scl为近400K的时钟80 scl <= 1;81 else82 scl <= ~scl;//空闲时,scl为高83 end84 end8586 reg [3:0] cnt;//发送或者接收数据的个数87 reg [15:0] memory;//发送或者接受数据的中间寄存器8889 always @ (posedge clk_sys or negedge rst_n)90 begin91 if (!rst_n)92 begin93 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 end102 else103 case(state)104 0 :if(scl)105 begin106 if(delay_done)//延时标志信号拉高107 begin108 sda_buffer <= 1'b0; //发送启动信号109 state <= 1;110 memory <= 16'h0042;//准备ID地址111 end112 else113 state <= 0;114 end115 else116 state <= 0;117118 1 :if((scl == 0) && (cnt < 8))//发送ID地址119 begin120 sda_buffer <= memory[7];121 cnt <= cnt + 1;122 memory = {memory[14:0],memory[15]};123 state <= 1;124 end125 else126 begin127 if ((scl == 0) && (cnt == 8))128 begin129 cnt <= 0;130 flag <= 0;//释放总线控制权131 state <= 2;132 end133 else134 begin135 state <= 1;136 end137 end138139 2 :140 if(scl)//在SCL高电平期间接收数据141 begin142 if(!sda)//检测应答信号143 begin144 state <= 3;145 memory <= lut_data;//指针寄存器地址146 end147 else148 begin149 state <= 0;150 end151 end152 else153 state <= 2;154155 3 : if((scl == 0) && (cnt < 8)) //发送指针寄存器地址156 begin157 flag <= 1;//获得总线控制权158 sda_buffer <= memory[15];159 cnt <= cnt + 1;160 memory = {memory[14:0],memory[15]};161 state <= 3;162 end163 else164 begin165 if ((scl == 0) && (cnt == 8))166 begin167 cnt <= 0;168 flag <= 0;//释放总线控制权169 state <= 4;170 end171 else172 begin173 state <= 3;174 end175 end176177 4 :178 if(scl)179 begin180 if(!sda)//检测应答信号181 begin182 state <= 5;183 end184 else185 begin186 state <= 0;187 end188 end189190 5 : if((scl == 0) && (cnt < 8))//发送八位控制字191 begin192 flag <= 1; //获得总线控制权193 sda_buffer <= memory[15];194 cnt <= cnt + 1;195 memory <= {memory[14:0],memory[15]};196 state <= 5;197 end198 else199 begin200 if ((scl == 0) && (cnt == 8))201 begin202 cnt <= 0;203 flag <= 0; //释放总线控制权204 state <= 6;205 lut_cnt <= lut_cnt + 1; //指针寄存器+1206 end207 else208 begin209 state <= 5;210 end211 end212213 6 :214 if(scl) //在SCL高电平期间,接收ACK215 begin216 if(!sda)//检测应答信号217 begin218 state <= 7;219 end220 else221 begin222 state <= 0;223 end224 end225226 7 : if (scl == 0)227 begin228 flag <= 1;229 sda_buffer <= 0;//拉低数据线(为发送停止信号做准备)230 state <= 8;231 end232 else233 state <= 7;234235 8 : if (scl == 1) //发送停止信号236 begin237 sda_buffer <= 1;238 begin239 if (s == 8)240 begin241 if(lut_cnt < 70)242 begin243 state <= 0;244 s <= 0;245 end246 else247 config_done <= 1; //配置完成248 end249 else250 s <= s + 1;251 end252 end253 else254 state <= 8;255256 default : state <= 0;257 endcase258 end259260 always @ (*)261 begin262 case (lut_cnt)263 // OV7725 : VGA RGB565 Config264 //Read Data Index265 // 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 Index270 2 : lut_data = {8'h12, 8'h80}; // BIT[7]-Reset all the Reg271 3 : lut_data = {8'h3d, 8'h03}; //DC offset for analog process272 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'h80278 10 : lut_data = {8'h29, 8'hA0}; //VGA: 8'hA0; QVGA: 8'hF0279 11 : lut_data = {8'h2C, 8'hF0}; //VGA: 8'hF0; QVGA: 8'h78280 //如果不使用内部PLL,这个命令是无效的281 12 : lut_data = {8'h0d, 8'h41}; //Bypass PLL 00:0 01:4x 10:6x 11:8x282 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;QVGA285 //BIT[3:2]: 01:RGB565286 //VGA: 00:YUV; 01:Processed Bayer RGB; 10:RGB; 11:Bayer RAW; BIT[7]-Reset all the Reg287 15 : lut_data = {8'h0C, 8'h10}; //COM3: Bit[7:6]:Vertical/Horizontal mirror image ON/OFF, Bit[0]:Color bar; Default:8'h10288 //DSP control289 16 : lut_data = {8'h42, 8'h7f}; //BLC Blue Channel Target Value, Default: 8'h80290 17 : lut_data = {8'h4d, 8'h09}; //BLC Red Channel Target Value, Default: 8'h80291 18 : lut_data = {8'h63, 8'hf0}; //AWB Control292 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:VYUY295 22 : lut_data = {8'h67, 8'h00}; //DSP_Ctrl4:00/01: YUV or RGB; 10: RAW8; 11: RAW10296 //AGC AEC AWB297 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'h09301 27 : lut_data = {8'h23, 8'h03}; //Banding Filter Maximum Step302 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 Region305 31 : lut_data = {8'h2b, 8'h9e}; //TaiWan: 8'h00:60Hz Filter; Mainland: 8'h9e:50Hz Filter306 32 : lut_data = {8'h6b, 8'haa}; //AWB Control 3307 33 : lut_data = {8'h13, 8'hff}; //8'hff: AGC AEC AWB Enable; 8'hf0: AGC AEC AWB Disable;308 //matrix sharpness brightness contrast UV309 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}; //Brightness321 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 correction329 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 //Others346 69 : lut_data = {8'h0e, 8'h65};//night mode auto frame rate control347 default : lut_data = {8'h1C, 8'h7F};348 endcase349 end350351 endmodule
图像实时捕获模块的主要代码:
2 frame_data, frame_clk, frame_href, frame_vsync, cmos_fps_rate);34 input clk_cmos; //24Mhz驱动时钟输入5 input rst_n;6 input pclk; //输入的像素时钟7 input vsync; //输入场同步信号8 input href; //输入的行同步信号9 input [7:0] din; //输入的像素数据1011 output xclk; //输出的CMOS Sensor的驱动时钟 24Mhz12 output frame_clk; //输出拼接后的像素数据的时钟13 output [15:0] frame_data; //输出拼接后的像素数据14 output frame_href; //输出同步的行同步信号15 output frame_vsync; //输出同步的场同步信号16 output reg cmos_fps_rate; //输出帧率1718 assign xclk = clk_cmos;1920 //-------------检测场、行同步信号------------21 reg href_r, vsync_r;22 always @(posedge pclk or negedge rst_n)23 begin24 if (!rst_n)25 begin26 href_r <= 1;27 vsync_r <= 1;28 end29 else30 begin31 href_r <= href;32 vsync_r <= vsync;33 end34 end35 //行同步信号由低电平变为高电平时,说明数据有效36 assign pose_href = (~href_r) & href;37 //场同步信号由高电平变为低电平时,说明一帧数据接收完毕38 assign nege_vsync = vsync_r & (~vsync);3940 //----------延时10帧产生一个标志编号----------41 reg frame_cnt_end; //延时10帧数据结束标志42 reg [3:0] frame_cnt; //帧计数器43 always @(posedge pclk or negedge rst_n)44 begin45 if(!rst_n)46 begin47 frame_cnt <= 0;48 frame_cnt_end <= 0;49 end50 else if (frame_cnt == 10)51 frame_cnt_end <= 1;52 else if(nege_vsync)53 frame_cnt <= frame_cnt + 1;54 else55 frame_cnt <= frame_cnt;56 end5758 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 begin64 if(!rst_n)65 begin66 byte_flag <= 0;67 din_buffer1 <= 0;68 din_buffer2 <= 0;69 cnt <= 0;70 end71 else if(href)72 begin73 cnt <= cnt + 1;74 din_buffer1 <= din;75 if(cnt >= 1278)76 byte_flag <= 0;77 else78 byte_flag <= ~byte_flag;7980 if(byte_flag == 1)81 din_buffer2 <= {din_buffer1,din};82 else83 din_buffer2 <= din_buffer2;84 end85 else86 begin87 byte_flag <= 0;88 din_buffer1 <= 0;89 din_buffer2 <= din_buffer2;90 cnt <= 0;91 end92 end9394 reg byte_flag_r;95 always@(posedge pclk or negedge rst_n)96 begin97 if(!rst_n)98 byte_flag_r <= 0;99 else100 byte_flag_r <= byte_flag;101 end102103 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;107108 reg [27:0] delay_cnt;109 always@(posedge pclk or negedge rst_n)110 begin111 if(!rst_n)112 delay_cnt <= 0;113 else if(delay_cnt < 48000000 - 1'b1)114 delay_cnt <= delay_cnt + 1'b1;115 else116 delay_cnt <= 0;117 end118 wire delay_2s = (delay_cnt == 48000000 - 1'b1) ? 1'b1 : 1'b0;119120 reg [8:0] cmos_fps_cnt;121 always @(posedge pclk or negedge rst_n)122 begin123 if(!rst_n)124 begin125 cmos_fps_cnt <= 0;126 cmos_fps_rate <= 0;127 end128 else if(delay_2s == 1'b0)129 begin130 cmos_fps_cnt <= nege_vsync ? cmos_fps_cnt + 1'b1 : cmos_fps_cnt;131 cmos_fps_rate <= cmos_fps_rate;132 end133 else134 begin135 cmos_fps_cnt <= 0;136 cmos_fps_rate <= cmos_fps_cnt[8:1];137 end138 end139140 endmodule
中值滤波模块的主要代码:
1 module zhongzhilvbo (clk, rst_n, data_in, fifo_empty, data_out, wrreq, rdreq);23 input clk;4 input rst_n;5 input [23:0] data_in;6 input fifo_empty;78 output [7:0] data_out;9 output reg wrreq;10 output reg rdreq;1112 reg [7:0] data [8:0];13 wire [7:0] data_n[8:0];14 reg shift;1516 assign data_out = data_n[4];1718 always @ (posedge clk or negedge rst_n)19 begin20 if (!rst_n)21 begin22 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 end32 else33 begin34 if (shift)35 begin36 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 end46 end47 end4849 reg compara_rst_n;50 genvar i;51 reg [7:0] temp;52 reg temp_rst_n;53 reg [3:0] count;5455 always @ (posedge clk or negedge temp_rst_n)56 begin57 if (!temp_rst_n)58 begin59 temp <= data [8];60 count <= 0;61 end62 else63 begin64 temp <= data[count];65 count <= count + 1;66 end6768 end69 generate70 for (i = 0; i < 9; i = i + 1)71 begin : compara72 if (i == 0)73 begin74 comparaer u1(.clk(clk), .rst_n(compara_rst_n), .ex_data(temp), .up_data(8'hff), .self_data(data_n[i]));75 end76 else77 begin78 comparaer comparaer(.clk(clk), .rst_n(compara_rst_n), .ex_data(temp), .up_data(data_n[i-1]), .self_data(data_n[i]));79 end80 end81 endgenerate8283 reg [2:0] state;84 reg [3:0] cnt;8586 always @ (posedge clk or negedge rst_n)87 begin88 if (!rst_n)89 begin90 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 end98 else99 begin100 case (state)101 0 : begin102 if (fifo_empty)103 begin104 state <= 0;105 wrreq <= 0;106 compara_rst_n <= 0;107 end108 else109 begin110 state <= 1;111 rdreq <= 1;112 wrreq <= 0;113 compara_rst_n <= 0;114 end115 end116117 1 : begin118 rdreq <= 0;119 shift <= 1;120 state <= 2;121 end122123 2 : begin124 shift <= 0;125 temp_rst_n <= 1;126 state <= 3;127 end128129 3 : begin130 if (cnt < 8)131 begin132 cnt <= cnt + 1;133 compara_rst_n <= 1;134 state <= 3;135 end136 else137 begin138 cnt <= 0;139 temp_rst_n <= 0;140 state <= 4;141 end142 end143144 4 : begin145 wrreq <= 1;146 state <= 0;147 end148149 endcase150 end151 end152 endmodule
边缘检测模块的主要代码:
1 module sob (clk, rst_n, data, result, fifo_wr, shift_en);23 input clk;4 input rst_n;5 input [23:0] data;6 input shift_en;78 output reg [7:0] result;9 output reg fifo_wr;101112 reg [7:0] O[-1:1][-1:1];13 reg signed [10:0] Dx, Dy;1415 function [10:0] abs ( input signed [10:0] x);16 abs = x >=0 ? x : -x ; // 取x的绝对值17 endfunction1819 always @ (posedge clk or negedge rst_n)20 begin21 if (!rst_n)22 begin23 result <= 8'd0;24 Dx <= 0;25 Dy <= 0;26 end27 else28 begin29 if ( shift_en )30 begin31 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 end58 end59 end60616263 reg [2:0] state;6465 always @ (posedge clk or negedge rst_n)66 begin67 if (!rst_n)68 begin69 fifo_wr <= 1'b0;70 state <= 0;71 end72 else73 begin74 case (state)75 0 : begin76 if (shift_en)77 begin78 state <= 2;79 fifo_wr <= 0;80 end81 else82 begin83 state <= 0;84 fifo_wr <= 0;85 end86 end8788 1 : begin89 if (shift_en)90 begin91 fifo_wr <= 1'b1;92 end93 else94 fifo_wr <= 0;95 end9697 2 : state <= 3;9899 3 : state <= 4;100101 4 : state <= 1;102103 default : state <= 0;104105 endcase106 end107 end108109 endmodule
图像缓存模块的主要代码:
1 `include "sdram_head.v"23 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);67 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;1617 // 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;2425 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;3334 localparam s0 = 3'b000;35 localparam s1 = 3'b001;36 localparam s2 = 3'b010;37 localparam s3 = 3'b011;38 localparam s4 = 3'b100;3940 reg [2:0] state;4142 reg rd,rd_en;4344 always @ (posedge sys_clk)45 begin46 if (!soft_rst_n)47 begin48 rd <= 0;49 end50 else51 begin52 if (local_rdreq && rd_en)53 rd <= local_rdreq;54 else55 if (!rd_en)56 rd <= 0;57 else58 rd <= rd;59 end60 end6162 reg wr,wr_en;6364 always @ (posedge sys_clk)65 begin66 if (!soft_rst_n)67 begin68 wr <= 0;69 end70 else71 begin72 if (local_wrreq && wr_en)73 wr <= local_wrreq;74 else75 if (!wr_en)76 wr <= 0;77 else78 wr <= wr;79 end80 end818283 always @ (posedge sys_clk)84 begin85 if (!soft_rst_n)86 begin87 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 end104 else105 case (state)106 s0 : if (!init_done)107 init_rst_n <= 1;108 else109 begin110 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 end118119 s1 : if ((ref_time < `ctREFR) && (!wr) && (!rd))120 state <= s1;121 else if (rd)122 begin123 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 end131 else if (wr)132 begin133 int_addr <= wr_ddr;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 end142 else if (ref_time >= `ctREFR)143 begin144 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 end151152 s2 : if (!ref_done)153 state <= s2;154 else155 begin156 state <= s1;157 time_rst_n <= 1;158 ref_rst_n <= 0;159 local_finish <= 1;160 local_ready <= 1;161 end162163 s3 : if (!rd_done)164 state <= s3;165 else166 begin167 local_ready <= 1;168 rd_finish <= 1;169 rd_rst_n <= 0;171 state <= s1;172 rd_en <= 1;173 end174175 s4 : if (!wr_done)176 state <= s4;177 else178 begin179 local_ready <= 1;180 wr_finish <= 1;181 wr_rst_n <= 0;182 state <= s1;183 wr_en <= 1;184 end185186 default : state <= s0;187 endcase188 end189 endmodule
图像实时显示模块的主要代码:
1 module lcd_driver2 (3 //global clock4 input clk, //system clock5 input rst_n, //sync reset67 //lcd interface8 output lcd_dclk, //lcd pixel clock9 output lcd_blank, //lcd blank10 output lcd_sync, //lcd sync11 output lcd_hs, //lcd horizontal sync12 output lcd_vs, //lcd vertical sync13 output lcd_en, //lcd display enable14 output [15:0] lcd_rgb, //lcd display data1516 //user interface17 output lcd_request, //lcd data request18 output [10:0] lcd_xpos, //lcd horizontal coordinate19 output [10:0] lcd_ypos, //lcd vertical coordinate20 input [15:0] lcd_data //lcd data2324/*******************************************25 SYNC--BACK--DISP--FRONT26*******************************************/27//------------------------------------------29 reg [10:0] hcnt;30 always @ (posedge clk or negedge rst_n)31 begin32 if (!rst_n)33 hcnt <= 11'd0;34 else35 begin36 if(hcnt < `H_TOTAL - 1'b1) //line over37 hcnt <= hcnt + 1'b1;38 else39 hcnt <= 11'd0;40 end41 end42 assign lcd_hs = (hcnt <= `H_SYNC - 1'b1) ? 1'b0 : 1'b1;4344//------------------------------------------46 reg [10:0] vcnt;47 always@(posedge clk or negedge rst_n)48 begin49 if (!rst_n)50 vcnt <= 11'b0;51 else if(hcnt == `H_TOTAL - 1'b1) //line over52 begin53 if(vcnt < `V_TOTAL - 1'b1) //frame over54 vcnt <= vcnt + 1'b1;55 else56 vcnt <= 11'd0;57 end58 end59 assign lcd_vs = (vcnt <= `V_SYNC - 1'b1) ? 1'b0 : 1'b1;6061//------------------------------------------63 assign lcd_dclk = ~clk;64 assign lcd_blank = lcd_hs & lcd_vs;65 assign lcd_sync = 1'b0;6667//-----------------------------------------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;7576//------------------------------------------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//-----------------------------------------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的实时图像边缘检测系统设计介绍完毕,各位大侠,关注不迷路哦,有缘再见。
END
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!
精彩推荐
一周掌握FPGA Verilog HDL语法 汇总篇
一周掌握 FPGA VHDL Day 7 暨汇总篇
FPGA 之 SOPC 系列 汇总篇
PCI Express 连载系列 第二阶段汇总(后十二篇)暨总汇总篇
FPGA Xilinx Zynq 系列 PART C 操作系统 & 系统集成(后四篇)汇总篇 暨总汇总篇
“FPGA产品设计与研发 ” 零基础入门及就业