基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)

目录

  • 前言
  • 一、先看效果
  • 二、硬件选择
  • 三、系统框架
  • 四、程序模块
    • 1、系统顶层模块
    • 2、图像处理顶层模块
    • 3、LCD驱动顶层模块
    • 4、SDRAM控制器顶层模块
    • 5、上位机发送模块
  • 五、工程及套件获取
    • 1、工程获取
    • 2、套件

前言

      最早做了基于FPGA:运动目标检测(VGA显示,原理图+源码+硬件选择),有网友反应,VGA一个大大的屏幕,做起来很不方便,并且功能过于单一。
     因此,在上个工程的基础上,修改成了TFT-LCD屏幕检测,并且将检测结果通过串口输出到电脑上位机上,以便大家做扩展开发。

一、先看效果

      话不多说,先上视频看效果。

基于FPGA运动目标检测(LCD显示-串口输出)

二、硬件选择

开发板Altera:EP4CE6F17C8(兼容E10)
摄像头:OV5640
屏幕:TFT-LCD
缓存数据:SDRAM
板子是自制的

三、系统框架

      本系统在图像采集之前,由于板载晶振与摄像头模块及 TFT-LCD 模块频率不一致,所以在系统工作之前,需要设计锁相环模块输出与OV5640摄像头一致的时钟信号。时钟输入后,根据 OV5640 的手册进行寄存器配置,使 OV5640 的工作模式符合本系统的设计需求。CMOS 传感器采集进来的图像进入到图像处理模块,输出当前帧的灰度,用于写入SDRAM。同时从SDRAM中读出前一帧的灰度(与当前输出相差一个时钟周期)重新进入图像处理模块进行帧差法的图像处理(即运动目标检测相关的处理)。
      在本系统中,满足选择功能的情况下,更需要满足实时性,所以选择只输入一路视频流。并且根据时钟域不同,设计了异步 FIFO 完成数据传输缓存。最后将处理结果通过 ILI9488 驱动模块显示在屏幕上,并将检测信息通过串口输出到上位机上。

基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第1张图片

四、程序模块

      代码框架:本设计基本使用纯Verilog设计,运用了较少的IP,如:PLL,FIFO。代码附带注释,可读性强,便于大家移植,参加竞赛、毕设。

基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第2张图片
      部分模块仿真:

基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第3张图片基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第4张图片

1、系统顶层模块

module dmk_photo_uart(
	input                       clk,
	input                       rst_n,             //KEY4(o) 即OK按键作为复位

	//CMOS Port
	inout                       cmos_scl,          //cmos i2c clock
	inout                       cmos_sda,          //cmos i2c data
	input                       cmos_vsync,        //cmos vsync
	input                       cmos_href,         //cmos hsync refrence,data valid
	input                       cmos_pclk,         //cmos pxiel clock
	output                      cmos_xclk,         //cmos externl clock
	input   [7:0]               cmos_db,           //cmos data
	output                      cmos_rst_n,        //cmos reset
	output                      cmos_pwdn,         //cmos power down
    
	//LCD ILI9488 Port
	output             			WR,
	output             			RD, 
	output             			CS,
	output             			RS,
	output             			BL_cnt,
	output [15:0]      			data,
	output             			RESET,
    
	//LED
	output  [3:0]               led,
	
	//uart
	input                       uart_rxd,          //uart 串行数据接收
	output                      uart_txd,          //uart 串行数据发送	
    
	//SDRAM Port
	output                      sdram_clk,         //sdram clock
	output                      sdram_cke,         //sdram clock enable
	output                      sdram_cs_n,        //sdram chip select
	output                      sdram_we_n,        //sdram write enable
	output                      sdram_cas_n,       //sdram column address strobe
	output                      sdram_ras_n,       //sdram row address strobe
	output[1:0]                 sdram_dqm,         //sdram data enable
	output[1:0]                 sdram_ba,          //sdram bank address
	output[12:0]                sdram_addr,        //sdram address
	inout[15:0]                 sdram_dq           //sdram data
);

// parameter  CMOS_H_PIXEL = 24'd640    ;  //CMOS水平方向像素个数,用于设置SDRAM缓存大小
// parameter  CMOS_V_PIXEL = 24'd480     ;  //CMOS垂直方向像素个数,用于设置SDRAM缓存大小

parameter  CMOS_H_PIXEL = 24'd480    ;  //CMOS水平方向像素个数,用于设置SDRAM缓存大小
parameter  CMOS_V_PIXEL = 24'd320     ;  //CMOS垂直方向像素个数,用于设置SDRAM缓存大小

parameter  Diff_Threshold = 8'd40	  ;  //帧差检测阈值	

assign cmos_rst_n = 1'b1;
assign cmos_pwdn  = 1'b0;

wire clk_ref;
wire clk_refout;//sdram控制器100M工作时钟、给SDRAM芯片的100M时钟
wire clk_lcd_w; //LCD驱动模块工作时钟,12.5MHz
wire pll_lock_w;
wire sys_rst_n;
wire lcd_init_done;

//PLL模块
sys_pll u_sys_pll_0(
	.areset         (!rst_n),
	.inclk0         (clk),
    
	.c0             (clk_ref   ),//sdram控制器100M 工作时钟
	.c1             (clk_refout),//SDRAM芯片 100M 时钟
	.c2             (cmos_xclk),//CMOS XCLK 24M 时钟
	.c3             (clk_lcd_w),//LCD驱动模块工作时钟,12.5MHz
	.locked         (pll_lock_w)
	);
    
//延迟复位模块
delay_reset u_delay_reset_0(
    .clk            (clk),
	.rst_n          (rst_n && pll_lock_w && lcd_init_done),
    
	.reset_n        (sys_rst_n)
);

//摄像头I2C配置模块
ov5640_config    #(
     .CMOS_H_PIXEL      (CMOS_H_PIXEL),
     .CMOS_V_PIXEL      (CMOS_V_PIXEL)
    )  u_ov5640_config_0(
	.rst_n          (sys_rst_n),
	.clk            (clk),
    
	.i2c_scl        (cmos_scl),
	.i2c_sda        (cmos_sda)
	);
    
    
wire			cmos_frame_vsync;	 
wire			cmos_frame_href;	 
wire			cmos_frame_clken;	 
wire	[15:0]	cmos_frame_data;	 
                                     
//CMOS图像数据采集模块
cmos_capture_data u_cmos_capture_data(  //系统初始化完成之后再开始采集数据 
    .rst_n              (sys_rst_n && sdram_init_done), 
        
    .cam_pclk           (cmos_pclk),   
    .cam_vsync          (cmos_vsync),  
    .cam_href           (cmos_href),   
    .cam_data           (cmos_db),     
        
    .cmos_frame_vsync   (cmos_frame_vsync   ),
    .cmos_frame_href    (cmos_frame_href    ),
    .cmos_frame_valid   (cmos_frame_clken   ),       //数据有效使能信号
    .cmos_frame_data    (cmos_frame_data    )      //有效数据 
    );


//----------------------------------------------------
//Video Image processor module.
wire			per_frame_vsync	=	cmos_frame_vsync;	                                 
wire			per_frame_href	=	cmos_frame_href;	                                 
wire			per_frame_clken	=	cmos_frame_clken;

wire	[7:0]	per_img_red		=	{cmos_frame_data[15:11], cmos_frame_data[15:13]};	 
wire	[7:0]	per_img_green	=	{cmos_frame_data[10:5], cmos_frame_data[10:9]};		 
wire	[7:0]	per_img_blue	=	{cmos_frame_data[4:0], cmos_frame_data[4:2]};		 

wire			post_frame_vsync;	 
wire			post_frame_href;	 
wire			post_frame_clken;	 

wire			post_img_Bit;		 
wire [7:0]	    post_img_red;		 
wire [7:0]	    post_img_green;	     
wire [7:0]	    post_img_blue;		 
wire [15:0]	    post_frame_data ;

assign post_frame_data  =  {post_img_red[7:3],post_img_green[7:2],post_img_blue[7:3]} ;	

wire 			YCbCr_frame_vsync ;
wire 			YCbCr_frame_href  ;
wire 			YCbCr_frame_clken ;
wire [7:0]	    YCbCr_img_Y_current;	//当前帧灰度
wire [15:0]	    YCbCr_img_Y_pre;		//前一帧灰度

wire target_detect;

Video_Image_Processor     #(
     .IMG_HDISP      (CMOS_H_PIXEL),
     .IMG_VDISP      (CMOS_V_PIXEL)
    )  	u_Video_Image_Processor
(
	//global clock
	.clk					(cmos_pclk),  			         
	.rst_n					(sys_rst_n && sdram_init_done),  

	//Image data prepred to be processd
	.per_frame_vsync		(per_frame_vsync),		 
	.per_frame_href		    (per_frame_href),		 
	.per_frame_clken		(per_frame_clken),		 
	.per_img_red			(per_img_red),			 
	.per_img_green			(per_img_green),		 
	.per_img_blue			(per_img_blue),			 
	
	//RGB2YCbCr output 
	.YCbCr_frame_vsync	    (YCbCr_frame_vsync),						
	.YCbCr_frame_href		(YCbCr_frame_href ),						
	.YCbCr_frame_clken	    (YCbCr_frame_clken),	
	.YCbCr_img_Y_current	(YCbCr_img_Y_current),			
	.YCbCr_img_Y_pre		(YCbCr_img_Y_pre[7:0]),

	//Image data has been processd
	.post_frame_vsync		(post_frame_vsync),		 
	.post_frame_href		(post_frame_href),		 
	.post_frame_clken		(post_frame_clken),		 
	.post_img_red			(post_img_red	),		 
	.post_img_green		    (post_img_green),		 
	.post_img_blue			(post_img_blue	),		 
                                                     
	//User interface                                 
	.Diff_Threshold		    (Diff_Threshold),
    .target_detect          (target_detect)
    );

//sdram read & write
wire        wr1_wrreq;
wire [15:0] wr1_data;
wire        rd1_rdreq;
wire [15:0] rd1_data;

assign wr1_wrreq    = YCbCr_frame_clken;
assign wr1_data     = {8'd0,YCbCr_img_Y_current};

assign rd1_rdreq        = YCbCr_frame_clken;
assign YCbCr_img_Y_pre  = rd1_data;

//摄像头采集模块,dvp转avalon-st裸流
wire [15:0] data_w0;
wire valid_w0,ready_w0,sop_w0,eop_w0;	

cmos_to_st_top     #(
     .WIDTH         (CMOS_H_PIXEL),
     .HEIGHT        (CMOS_V_PIXEL),
     .DWIDTH        (16)
    )  u_cmos_to_st_top( 
	.clk            (clk),
	.rst_n          (sys_rst_n && sdram_init_done),
    
    .cmos_pclk      (cmos_pclk),
    
	.cmos_vsync		(post_frame_vsync   ),		 
	.cmos_href 	    (post_frame_href    ),		 
	.cmos_clken		(post_frame_clken   ),		 
	.cmos_data 		(post_frame_data    ),		 
    
	// .cmos_vsync		(YCbCr_frame_vsync  ),		 
	// .cmos_href 	    (YCbCr_frame_href   ),		 
	// .cmos_clken		(YCbCr_frame_clken  ),		 
	// .cmos_data 		( {YCbCr_img_Y_current[7:3],YCbCr_img_Y_current[7:2],YCbCr_img_Y_current[7:3]}    ),		

	.source_sop     (sop_w0),
	.source_valid   (valid_w0),
	.source_data    (data_w0),
	.source_eop     (eop_w0),
	.source_ready   (ready_w0)
);


//TFTLCD模块
vip_ILI9488 u_vip_ILI9488_0(
	.clk            (clk),
	.clk12p5M       (clk_lcd_w),                      
	.rst_n          (rst_n),
    
	//Avalon-ST Sink
    .sink_sop       (sop_w0),
    .sink_valid     (valid_w0),
    .sink_data      (data_w0),
    .sink_eop       (eop_w0),
    .sink_ready     (ready_w0),
    
    .lcd_intdone    (lcd_init_done),
    
	//TFTLCD interface
	.WR             (WR),             
	.RD             (RD),             
	.CS             (CS),             
	.RS             (RS),             
	.BL_cnt         (BL_cnt),         
	.data           (data),           
	.RESET          (RESET)           
);	

wire wr_full_1/*synthesis keep*/;
wire wr_full_2;
wire rd_empty_1;
wire rd_empty_2/*synthesis keep*/;

//assign led = {wr_full_1,1'b0,1'b0,rd_empty_1};

//4port SDRAM控制器模块
Sdram_Control_4Port Sdram_Control_4Port(
	.REF_CLK        (clk_ref),
	.OUT_CLK        (clk_refout),
	.RESET_N        (sys_rst_n),	                //复位输入,低电平复位
                
	.WR1_DATA       (wr1_data),		                //写入端口1的数据输入端,16bit
	.WR1            (wr1_wrreq),	                //写入端口1的写使能端,高电平写入
	.WR1_ADDR       (0),			                //写入端口1的写起始地址
	.WR1_MAX_ADDR   (CMOS_H_PIXEL*CMOS_V_PIXEL),    		            //写入端口1的写入最大地址
	.WR1_LENGTH     (256),			                //一次性写入数据长度
	.WR1_LOAD       (~sys_rst_n),	                //写入端口1清零请求,高电平清零写入地址和fifo
	.WR1_CLK        (cmos_pclk ),			                //写入端口1 fifo写入时钟
	.WR1_FULL       (wr_full_1),			                    //写入端口1 fifo写满信号
	.WR1_USE        (),				                //写入端口1 fifo已经写入的数据长度
            
            
	.WR2_DATA       ( ),	                        //写入端口2的数据输入端,16bit
	.WR2            (0),	                        //写入端口2的写使能端,高电平写入
	.WR2_ADDR       (CMOS_H_PIXEL*CMOS_V_PIXEL),    //写入端口2的写起始地址
	.WR2_MAX_ADDR   (CMOS_H_PIXEL*CMOS_V_PIXEL*2),  //写入端口2的写入最大地址
	.WR2_LENGTH     (256),			                //一次性写入数据长度
	.WR2_LOAD       (~sys_rst_n),	                //写入端口2清零请求,高电平清零写入地址和fifo
	.WR2_CLK        (clk),			                //写入端口2 fifo写入时钟
	.WR2_FULL       (wr_full_2),			                    //写入端口2 fifo写满信号
	.WR2_USE        (),				                //写入端口2 fifo已经写入的数据长度
                
                
	.RD1_DATA       (rd1_data),		                //读出端口1的数据输出端,16bit
	.RD1            (rd1_rdreq),	                //读出端口1的读使能端,高电平读出
	.RD1_ADDR       (0),			                //读出端口1的读起始地址
	.RD1_MAX_ADDR   (CMOS_H_PIXEL*CMOS_V_PIXEL),    //读出端口1的读出最大地址
	.RD1_LENGTH     (256),			                //一次性读出数据长度
	.RD1_LOAD       (~sys_rst_n),	                //读出端口1 清零请求,高电平清零读出地址和fifo
	.RD1_CLK        (cmos_pclk),			                //读出端口1 fifo读取时钟
	.RD1_EMPTY      (rd_empty_1),	                //读出端口1 fifo读空信号
	.RD1_USE        (),				                //读出端口1 fifo已经还可以读取的数据长度
                
	.RD2_DATA       (),			                    //读出端口2的数据输出端,16bit
	.RD2            (0),                            //读出端口2的读使能端,高电平读出
	.RD2_ADDR       (CMOS_H_PIXEL*CMOS_V_PIXEL),    //读出端口2的读起始地址
	.RD2_MAX_ADDR   (CMOS_H_PIXEL*CMOS_V_PIXEL*2),  //读出端口2的读出最大地址
	.RD2_LENGTH     (256),			                //一次性读出数据长度
	.RD2_LOAD       (~sys_rst_n),	                //读出端口2清零请求,高电平清零读出地址和fifo
	.RD2_CLK        (clk),			                //读出端口2 fifo读取时钟
	.RD2_EMPTY      (rd_empty_2),	                //读出端口2 fifo读空信号
	.RD2_USE        (),				                //读出端口2 fifo已经还可以读取的数据长度
       
           
	.SA             (sdram_addr),		            //SDRAM 地址线,
	.BA             (sdram_ba),		                //SDRAM bank地址线
	.CS_N           (sdram_cs_n),		            //SDRAM 片选信号
	.CKE            (sdram_cke),		            //SDRAM 时钟使能
	.RAS_N          (sdram_ras_n),	                //SDRAM 行选中信号
	.CAS_N          (sdram_cas_n),	                //SDRAM 列选中信号
	.WE_N           (sdram_we_n),		            //SDRAM 写请求信号
	.DQ             (sdram_dq),		                //SDRAM 双向数据总线
	.SDR_CLK        (sdram_clk),       
	.DQM            (),		                        //SDRAM 数据总线高低字节屏蔽信号
    
	.Sdram_Init_Done(sdram_init_done)
	);

assign sdram_dqm = 2'b00;



///串口波特率

parameter  CLK_FREQ = 50000000;      
parameter  UART_BPS = 9600;
    
    
wire [7:0] uart_tx_data  ; 
wire       uart_tx_en    ; 
wire       uart_tx_done  ; 

    
uart_tx_ctrl uart_tx_ctrl(
	.clk                (clk),
	.rst_n              (rst_n),

	.target_detect      (target_detect),

	.uart_tx_en         (uart_tx_en),
	.uart_tx_data       (uart_tx_data),

    .uart_tx_done       (uart_tx_done)
);

// 串口 发送
uart_send #(
    .CLK_FREQ                       (CLK_FREQ),        
    .UART_BPS                       (UART_BPS)
    )        
rj45_1_send_mode1(                                 
    .sys_clk                        (clk),
    .sys_rst_n                      (rst_n),

    .uart_din                       (uart_tx_data  ),
    .uart_en                        (uart_tx_en    ),
 
    .uart_txd                       (uart_txd),
    .tx_flag                        (),
    
    .tx_done                        (uart_tx_done)
    );

// 串口 接收
uart_recv #(                           
    .CLK_FREQ                       (CLK_FREQ),        
    .UART_BPS                       (UART_BPS)
    )        
rs485_1_recv(                                         
    .sys_clk                        (clk),         
    .sys_rst_n                      (rst_n),           
                                                    
    .uart_rxd                       (uart_rxd),      
                                                    
    .uart_done                      ( ),     
    .uart_data                      ( ),
    
    .uart_valid                     ( )   
    );  

assign led[0] = target_detect;
assign led[1] = target_detect;

assign led[3] = uart_txd ;

    
endmodule 

2、图像处理顶层模块

`timescale 1ns/1ns
module Video_Image_Processor #(
	parameter	[9:0]	IMG_HDISP = 10'd480,	//640*480
	parameter	[9:0]	IMG_VDISP = 10'd320
)
(
	//global clock
	input					clk,  				//cmos video pixel clock
	input					rst_n,				//global reset

	//Image data prepred to be processd
	input					per_frame_vsync,	//Prepared Image data vsync valid signal
	input					per_frame_href,		//Prepared Image data href vaild  signal
	input					per_frame_clken,	//Prepared Image data output/capture enable clock
	input		[7:0]		per_img_red,		//Prepared Image red data to be processed
	input		[7:0]		per_img_green,		//Prepared Image green data to be processed
	input		[7:0]		per_img_blue,		//Prepared Image blue data to be processed

	output				YCbCr_frame_vsync,	
	output				YCbCr_frame_href,		
	output				YCbCr_frame_clken,	
	output	[7:0]		YCbCr_img_Y_current,	//输出当前帧的灰度,用于写入SDRAM
	input 	[7:0]		YCbCr_img_Y_pre,		//同时从SDRAM中读出前一帧的灰度,与当前输出相差一个时钟周期
	
	//Image data has been processd
	output				post_frame_vsync,	//Processed Image data vsync valid signal
	output				post_frame_href,	//Processed Image data href vaild  signal
	output				post_frame_clken,	//Processed Image data output/capture enable clock
	output	[7:0]		post_img_red,		//Processed Image red data to be processed
	output	[7:0]		post_img_green,	//Processed Image green data to be processed
	output	[7:0]		post_img_blue,		//Processed Image blue data to be processed
	
	//user interface
	input		[7:0]		Diff_Threshold,		//Frame Difference Threshold for move detect	
    output                  target_detect
   );

assign YCbCr_frame_vsync 	= post0_frame_vsync;
assign YCbCr_frame_href	 	= post0_frame_href ;	
assign YCbCr_frame_clken 	= post0_frame_clken;
assign YCbCr_img_Y_current	= post0_img_Y      ;		

//-------------------------------------
//Convert the RGB888 format to YCbCr444 format.
wire 			post0_frame_vsync;   
wire 			post0_frame_href ;   
wire 			post0_frame_clken;    
wire [7:0]	post0_img_Y      ;   
wire [7:0]	post0_img_Cb     ;   
wire [7:0]	post0_img_Cr     ;   

VIP_RGB888_YCbCr444	u_VIP_RGB888_YCbCr444
(
	//global clock
	.clk				(clk),					//cmos video pixel clock
	.rst_n				(rst_n),				//system reset

	//Image data prepred to be processd
	.per_frame_vsync	(per_frame_vsync),		//Prepared Image data vsync valid signal
	.per_frame_href	(per_frame_href),		//Prepared Image data href vaild  signal
	.per_frame_clken	(per_frame_clken),		//Prepared Image data output/capture enable clock
	.per_img_red		(per_img_red),			//Prepared Image red data input
	.per_img_green		(per_img_green),		//Prepared Image green data input
	.per_img_blue		(per_img_blue),			//Prepared Image blue data input
	
	//Image data has been processd
	.post_frame_vsync	(post0_frame_vsync),		//Processed Image frame data valid signal
	.post_frame_href	(post0_frame_href),		//Processed Image hsync data valid signal
	.post_frame_clken	(post0_frame_clken),		//Processed Image data output/capture enable clock
	.post_img_Y			(post0_img_Y),			//Processed Image brightness output
	.post_img_Cb		(post0_img_Cb),			//Processed Image blue shading output
	.post_img_Cr		(post0_img_Cr)			//Processed Image red shading output
);

//--------------------------------------
//frame difference 
wire			post1_frame_vsync;	//Processed Image data vsync valid signal
wire			post1_frame_href;		//Processed Image data href vaild  signal
wire			post1_frame_clken;	//Processed Image data output/capture enable clock
wire			post1_img_Bit;			//Processed Image Bit flag outout(1: Value, 0:inValid)

VIP_Frame_Difference u_VIP_Frame_Difference(
	//global clock
	.clk						(clk),  						//cmos video pixel clock
	.rst_n					(rst_n),						//global reset

	//Image data prepred to be processd
	.per_frame_vsync		(post0_frame_vsync),		//Prepared Image data vsync valid signal
	.per_frame_href		(post0_frame_href),		//Prepared Image data href vaild  signal
	.per_frame_clken		(post0_frame_clken),		//Prepared Image data output/capture enable clock
	.per_img_Y				(post0_img_Y),				//Prepared Image brightness input

	.YCbCr_img_Y_pre		(YCbCr_img_Y_pre),
	
	//Image data has been processd
	.post_frame_vsync		(post1_frame_vsync),		//Processed Image data vsync valid signal
	.post_frame_href		(post1_frame_href),		//Processed Image data href vaild  signal
	.post_frame_clken		(post1_frame_clken),		//Processed Image data output/capture enable clock
	.post_img_Bit			(post1_img_Bit),			//Processed Image Bit flag outout(1: Value, 0:inValid)
	
	//User interface
	.Diff_Threshold		(Diff_Threshold)					//Sobel Threshold for image edge detect
);

//--------------------------------------
//Bit Image Process with Erosion before Dilation Detector.
wire			post2_frame_vsync;	//Processed Image data vsync valid signal
wire			post2_frame_href;	//Processed Image data href vaild  signal
wire			post2_frame_clken;	//Processed Image data output/capture enable clock
wire			post2_img_Bit;		//Processed Image Bit flag outout(1: Value, 0:inValid)
VIP_Bit_Erosion_Detector
#(
	.IMG_HDISP	(IMG_HDISP),	//640*480
	.IMG_VDISP	(IMG_VDISP)
)
u_VIP_Bit_Erosion_Detector
(
	//global clock
	.clk						(clk),  				//cmos video pixel clock
	.rst_n					(rst_n),				//global reset

	//Image data prepred to be processd
	.per_frame_vsync		(post1_frame_vsync),	//Prepared Image data vsync valid signal
	.per_frame_href		(post1_frame_href),	//Prepared Image data href vaild  signal
	.per_frame_clken		(post1_frame_clken),	//Prepared Image data output/capture enable clock
	.per_img_Bit			(post1_img_Bit),		//Processed Image Bit flag outout(1: Value, 0:inValid)

	//Image data has been processd
	.post_frame_vsync		(post2_frame_vsync),		//Processed Image data vsync valid signal
	.post_frame_href		(post2_frame_href),		//Processed Image data href vaild  signal
	.post_frame_clken		(post2_frame_clken),		//Processed Image data output/capture enable clock
	.post_img_Bit			(post2_img_Bit)			//Processed Image Bit flag outout(1: Value, 0:inValid)
);


//--------------------------------------
//Bit Image Process with Dilation after Erosion Detector.
wire			post3_frame_vsync;	//Processed Image data vsync valid signal
wire			post3_frame_href;	//Processed Image data href vaild  signal
wire			post3_frame_clken;	//Processed Image data output/capture enable clock
wire			post3_img_Bit;		//Processed Image Bit flag outout(1: Value, 0:inValid)

VIP_Bit_Dilation_Detector
#(
	.IMG_HDISP	(IMG_HDISP),	//640*480
	.IMG_VDISP	(IMG_VDISP)
)
u_VIP_Bit_Dilation_Detector
(
	//global clock
	.clk						(clk),  				//cmos video pixel clock
	.rst_n					(rst_n),				//global reset

	//Image data prepred to be processd
	.per_frame_vsync		(post2_frame_vsync),	//Prepared Image data vsync valid signal
	.per_frame_href		(post2_frame_href),	//Prepared Image data href vaild  signal
	.per_frame_clken		(post2_frame_clken),	//Prepared Image data output/capture enable clock
	.per_img_Bit			(post2_img_Bit),		//Processed Image Bit flag outout(1: Value, 0:inValid)

	//Image data has been processd
	.post_frame_vsync		(post3_frame_vsync),		//Processed Image data vsync valid signal
	.post_frame_href		(post3_frame_href),		//Processed Image data href vaild  signal
	.post_frame_clken		(post3_frame_clken),		//Processed Image data output/capture enable clock
	.post_img_Bit			(post3_img_Bit)				//Processed Image Bit flag outout(1: Value, 0:inValid)
);

wire [9:0] rectangular_up		;
wire [9:0] rectangular_down	;
wire [9:0] rectangular_left	;
wire [9:0] rectangular_right 	;
wire 		  rectangular_flag	;

//检测运动目标所在的矩形区域
VIP_detect_rectangular
#(
	.IMG_HDISP	(IMG_HDISP),	//640*480
	.IMG_VDISP	(IMG_VDISP)
)
u_VIP_detect_rectangular
(
	//global clock
	.clk						(clk),  				//cmos video pixel clock
	.rst_n					(rst_n),				//global reset

	//Image data prepred to be processd
	.per_frame_vsync		(post3_frame_vsync),	//Prepared Image data vsync valid signal
	.per_frame_href		(post3_frame_href),	//Prepared Image data href vaild  signal
	.per_frame_clken		(post3_frame_clken),	//Prepared Image data output/capture enable clock
	.per_img_Bit			(post3_img_Bit),		//Processed Image Bit flag outout(1: Value, 0:inValid)

	//检测出的矩形边界
	.rectangular_up		(rectangular_up	),
	.rectangular_down		(rectangular_down	),
	.rectangular_left		(rectangular_left	),
	.rectangular_right	(rectangular_right), 
	.rectangular_flag		(rectangular_flag)
);

//在输入视频上叠加检测出的矩形框
VIP_Video_add_rectangular
#(
	.IMG_HDISP	(IMG_HDISP),	//640*480
	.IMG_VDISP	(IMG_VDISP)
)
u_VIP_Video_add_rectangular
(
	//global clock
	.clk						(clk),  				//cmos video pixel clock
	.rst_n					(rst_n),				//global reset

	//Image data prepred to be processd
	.per_frame_vsync		(per_frame_vsync),		//Prepared Image data vsync valid signal
	.per_frame_href		(per_frame_href),		//Prepared Image data href vaild  signal
	.per_frame_clken		(per_frame_clken),		//Prepared Image data output/capture enable clock
	.per_img_red			(per_img_red),			//Prepared Image red data input
	.per_img_green			(per_img_green),		//Prepared Image green data input
	.per_img_blue			(per_img_blue),			//Prepared Image blue data input
	
	//检测出的矩形边界
	.rectangular_up		(rectangular_up	),
	.rectangular_down		(rectangular_down	),
	.rectangular_left		(rectangular_left	),
	.rectangular_right	(rectangular_right),
	.rectangular_flag		(rectangular_flag),

	.post_frame_vsync		(post_frame_vsync),		//Prepared Image data vsync valid signal
	.post_frame_href		(post_frame_href),		//Prepared Image data href vaild  signal
	.post_frame_clken		(post_frame_clken),		//Prepared Image data output/capture enable clock
	.post_img_red			(post_img_red),			//Prepared Image red data input
	.post_img_green		(post_img_green),		//Prepared Image green data input
	.post_img_blue			(post_img_blue) 			//Prepared Image blue data input
);

assign target_detect = rectangular_flag;

endmodule

3、LCD驱动顶层模块

//功能:Avalon-ST视频流接口的ILI9488驱动模块
module vip_ILI9488(
	input         clk,
	input         clk12p5M,                      
	input         rst_n,
	//Avalon-ST Sink
    input         sink_sop,
    input         sink_valid,
    input  [15:0] sink_data,
    input         sink_eop,
    output        sink_ready,
    //Conduit
    output        lcd_intdone,
	//TFTLCD interface
	output        WR,
	output        RD,
	output        CS,
	output        RS,
	output        BL_cnt,
	output [15:0] data,
	output        RESET
);
wire sop_w0,eop_w0,valid_w0,ready_w0;
wire [15:0] data_w0;
wire        sop_w1;
wire [15:0] data_w1;
wire fifo_empty_w,fifo_rd_w;
wire [7:0] wrusedw_w;
wire pixelReady;
reg  valid_r1;
assign fifo_rd_w = !fifo_empty_w && pixelReady;
assign sink_ready = (wrusedw_w <= 8'd200);
always@(posedge clk12p5M or negedge rst_n)
begin
if(rst_n == 1'b0)
    begin
    valid_r1 <= 1'b0;
    end
else
    begin
    valid_r1 <= fifo_rd_w;
    end
end
vip_ili9488_dcfifo u_vip_ili9488_dcfifo_0 (
	.aclr(!rst_n),
	.data({sink_sop,sink_data}),
	.rdclk(clk12p5M),
	.rdreq(fifo_rd_w),
	.wrclk(clk),
	.wrreq(sink_valid),
	.q({sop_w1,data_w1}),
	.rdempty(fifo_empty_w),
	.wrusedw(wrusedw_w)
	);
ILI9488 u_ILI9488_0(
	.clk12p5M(clk12p5M),                      
	.rst_n(rst_n),
	.x_start(10'd0),//横坐标
	.x_end(10'd479),
	.y_start(10'd0),
	.y_end(10'd319),//纵坐标
	.color(data_w1),      //RGB565
	.sop(sop_w1),
	.write_en(valid_r1),   //high active
	.write_ready(pixelReady),//write_en拉高后必须等待write_ready为高才表示
	.lcd_intdone(lcd_intdone),//TFTLCD 初始化完成标志,高有效
	.WR(WR),
	.RD(RD),
	.CS(CS),
	.RS(RS),
	.BL_cnt(BL_cnt),
	.data(data),
	.RESET(RESET)
	);
endmodule 

4、SDRAM控制器顶层模块

module Sdram_Control_4Port(
		//	HOST Side
        REF_CLK,
		  OUT_CLK,
        RESET_N,
	//  	CLK,     //
		//CLK_18,  //
		//	FIFO Write Side 1
      WR1_DATA,
		WR1,
		WR1_ADDR,
		WR1_MAX_ADDR,
		WR1_LENGTH,
		WR1_LOAD,
		WR1_CLK,
		WR1_FULL,
		WR1_USE,
		//	FIFO Write Side 2
        WR2_DATA,
		WR2,
		WR2_ADDR,
		WR2_MAX_ADDR,
		WR2_LENGTH,
		WR2_LOAD,
		WR2_CLK,
		WR2_FULL,
		WR2_USE,
		//	FIFO Read Side 1
        RD1_DATA,
		RD1,
		RD1_ADDR,
		RD1_MAX_ADDR,
		RD1_LENGTH,
		RD1_LOAD,	
		RD1_CLK,
		RD1_EMPTY,
		RD1_USE,
		//	FIFO Read Side 2
        RD2_DATA,
		RD2,
		RD2_ADDR,
		RD2_MAX_ADDR,
		RD2_LENGTH,
		RD2_LOAD,
		RD2_CLK,
		RD2_EMPTY,
		RD2_USE,
		//	SDRAM Side
        SA,
        BA,
        CS_N,
        CKE,
        RAS_N,
        CAS_N,
        WE_N,
        DQ,
        DQM,
		SDR_CLK,
		// user inter
		Sdram_Init_Done
        );

		  

`include        "Sdram_Params.h"
//	HOST Side
input                           REF_CLK;                //System Clock
input                           OUT_CLK;
input                           RESET_N;                //System Reset
//	FIFO Write Side 1
input   [`DSIZE-1:0]            WR1_DATA;               //Data input
input							WR1;					//Write Request
input	[`ASIZE-1:0]			WR1_ADDR;				//Write start address
input	[`ASIZE-1:0]			WR1_MAX_ADDR;			//Write max address
input	[8:0]					WR1_LENGTH;				//Write length
input							WR1_LOAD;				//Write register load & fifo clear
input							WR1_CLK;				//Write fifo clock
output							WR1_FULL;				//Write fifo full
output	[15:0]					WR1_USE;				//Write fifo usedw
//	FIFO Write Side 2
input   [`DSIZE-1:0]            WR2_DATA;               //Data input
input							WR2;					//Write Request
input	[`ASIZE-1:0]			WR2_ADDR;				//Write start address
input	[`ASIZE-1:0]			WR2_MAX_ADDR;			//Write max address
input	[8:0]					WR2_LENGTH;				//Write length
input							WR2_LOAD;				//Write register load & fifo clear
input							WR2_CLK;				//Write fifo clock
output							WR2_FULL;				//Write fifo full
output	[15:0]					WR2_USE;				//Write fifo usedw
//	FIFO Read Side 1
output  [`DSIZE-1:0]            RD1_DATA;               //Data output
input							RD1;					//Read Request
input	[`ASIZE-1:0]			RD1_ADDR;				//Read start address
input	[`ASIZE-1:0]			RD1_MAX_ADDR;			//Read max address
input	[8:0]					RD1_LENGTH;				//Read length
input							RD1_LOAD;				//Read register load & fifo clear
input							RD1_CLK;				//Read fifo clock
output							RD1_EMPTY;				//Read fifo empty
output	[15:0]					RD1_USE;				//Read fifo usedw
//	FIFO Read Side 2
output  [`DSIZE-1:0]            RD2_DATA;               //Data output
input							RD2;					//Read Request
input	[`ASIZE-1:0]			RD2_ADDR;				//Read start address
input	[`ASIZE-1:0]			RD2_MAX_ADDR;			//Read max address
input	[8:0]					RD2_LENGTH;				//Read length
input							RD2_LOAD;				//Read register load & fifo clear
input							RD2_CLK;				//Read fifo clock
output							RD2_EMPTY;				//Read fifo empty
output	[15:0]					RD2_USE;				//Read fifo usedw
//	SDRAM Side
output  [11:0]                  SA;                     //SDRAM address output
output  [1:0]                   BA;                     //SDRAM bank address
output  [1:0]                   CS_N;                   //SDRAM Chip Selects
output                          CKE;                    //SDRAM clock enable
output                          RAS_N;                  //SDRAM Row address Strobe
output                          CAS_N;                  //SDRAM Column address Strobe
output                          WE_N;                   //SDRAM write enable
inout   [`DSIZE-1:0]            DQ;                     //SDRAM data bus
output  [`DSIZE/8-1:0]          DQM;                    //SDRAM data mask lines
output							SDR_CLK;				//SDRAM clock
assign SDR_CLK=OUT_CLK;
wire   CLK=REF_CLK;
output    Sdram_Init_Done;
//	Internal Registers/Wires
//	Controller
reg		[`ASIZE-1:0]			mADDR;					//Internal address
reg		[8:0]					mLENGTH;				//Internal length
reg		[`ASIZE-1:0]			rWR1_ADDR;				//Register write address				
reg		[`ASIZE-1:0]			rWR1_MAX_ADDR;			//Register max write address				
reg		[8:0]					rWR1_LENGTH;			//Register write length
reg		[`ASIZE-1:0]			rWR2_ADDR;				//Register write address				
reg		[`ASIZE-1:0]			rWR2_MAX_ADDR;			//Register max write address				
reg		[8:0]					rWR2_LENGTH;			//Register write length
reg		[`ASIZE-1:0]			rRD1_ADDR;				//Register read address
reg		[`ASIZE-1:0]			rRD1_MAX_ADDR;			//Register max read address
reg		[8:0]					rRD1_LENGTH;			//Register read length
reg		[`ASIZE-1:0]			rRD2_ADDR;				//Register read address
reg		[`ASIZE-1:0]			rRD2_MAX_ADDR;			//Register max read address
reg		[8:0]					rRD2_LENGTH;			//Register read length
reg		[1:0]					WR_MASK;				//Write port active mask
reg		[1:0]					RD_MASK;				//Read port active mask
reg								mWR_DONE;				//Flag write done, 1 pulse SDR_CLK
reg								mRD_DONE;				//Flag read done, 1 pulse SDR_CLK
reg								mWR,Pre_WR;				//Internal WR edge capture
reg								mRD,Pre_RD;				//Internal RD edge capture
reg 	[9:0] 					ST;						//Controller status
reg		[1:0] 					CMD;					//Controller command
reg								PM_STOP;				//Flag page mode stop
reg								PM_DONE;				//Flag page mode done
reg								Read;					//Flag read active
reg								Write;					//Flag write active
reg	    [`DSIZE-1:0]           	mDATAOUT;               //Controller Data output
wire    [`DSIZE-1:0]           	mDATAIN;                //Controller Data input
wire    [`DSIZE-1:0]           	mDATAIN1;                //Controller Data input 1
wire    [`DSIZE-1:0]           	mDATAIN2;                //Controller Data input 2
wire                          	CMDACK;                 //Controller command acknowledgement
//	DRAM Control
reg  	[`DSIZE/8-1:0]          DQM;                    //SDRAM data mask lines
reg     [11:0]                  SA;                     //SDRAM address output
reg     [1:0]                   BA;                     //SDRAM bank address
reg     [1:0]                   CS_N;                   //SDRAM Chip Selects
reg                             CKE;                    //SDRAM clock enable
reg                             RAS_N;                  //SDRAM Row address Strobe
reg                             CAS_N;                  //SDRAM Column address Strobe
reg                             WE_N;                   //SDRAM write enable
wire    [`DSIZE-1:0]            DQOUT;					//SDRAM data out link
wire  	[`DSIZE/8-1:0]          IDQM;                   //SDRAM data mask lines
wire    [11:0]                  ISA;                    //SDRAM address output
wire    [1:0]                   IBA;                    //SDRAM bank address
wire    [1:0]                   ICS_N;                  //SDRAM Chip Selects
wire                            ICKE;                   //SDRAM clock enable
wire                            IRAS_N;                 //SDRAM Row address Strobe
wire                            ICAS_N;                 //SDRAM Column address Strobe
wire                            IWE_N;                  //SDRAM write enable
//	FIFO Control
reg								OUT_VALID;				//Output data request to read side fifo
reg								IN_REQ;					//Input	data request to write side fifo
wire	[15:0]					write_side_fifo_rusedw1;
wire	[15:0]					read_side_fifo_wusedw1;
wire	[15:0]					write_side_fifo_rusedw2;
wire	[15:0]					read_side_fifo_wusedw2;
//	DRAM Internal Control
wire    [`ASIZE-1:0]            saddr;
wire                            load_mode;
wire                            nop;
wire                            reada;
wire                            writea;
wire                            refresh;
wire                            precharge;
wire                            oe;
wire							ref_ack;
wire							ref_req;
wire							init_req;
wire							cm_ack;
wire							active;

/*
Sdram_PLL sdram_pll1	(
				.inclk0(REF_CLK),
				.c0(CLK),
				.c1(SDR_CLK),
				.c2(CLK_18)
				);
*/				

control_interface control1 (
                .CLK(CLK),
                .RESET_N(RESET_N),
                .CMD(CMD),
                .ADDR(mADDR),
                .REF_ACK(ref_ack),
                .CM_ACK(cm_ack),
                .NOP(nop),
                .READA(reada),
                .WRITEA(writea),
                .REFRESH(refresh),
                .PRECHARGE(precharge),
                .LOAD_MODE(load_mode),
                .SADDR(saddr),
                .REF_REQ(ref_req),
		    		.INIT_REQ(init_req),
                .CMD_ACK(CMDACK),
					 .Sdram_Init_Done(Sdram_Init_Done)
                );

command command1(
                .CLK(CLK),
                .RESET_N(RESET_N),
                .SADDR(saddr),
                .NOP(nop),
                .READA(reada),
                .WRITEA(writea),
                .REFRESH(refresh),
				.LOAD_MODE(load_mode),
                .PRECHARGE(precharge),
                .REF_REQ(ref_req),
				.INIT_REQ(init_req),
                .REF_ACK(ref_ack),
                .CM_ACK(cm_ack),
                .OE(oe),
				.PM_STOP(PM_STOP),
				.PM_DONE(PM_DONE),
                .SA(ISA),
                .BA(IBA),
                .CS_N(ICS_N),
                .CKE(ICKE),
                .RAS_N(IRAS_N),
                .CAS_N(ICAS_N),
                .WE_N(IWE_N)
                );
                
sdr_data_path data_path1(
                .CLK(CLK),
                .RESET_N(RESET_N),
                .DATAIN(mDATAIN),
                .DM(2'b00),
                .DQOUT(DQOUT),
                .DQM(IDQM)
                );

Sdram_WR_FIFO 	write_fifo1(
				.data(WR1_DATA),
				.wrreq(WR1),
				.wrclk(WR1_CLK),
				.aclr(WR1_LOAD),
				.rdreq(IN_REQ&WR_MASK[0]),
				.rdclk(CLK),
				.q(mDATAIN1),
				.wrfull(WR1_FULL),
				.wrusedw(WR1_USE),
				.rdusedw(write_side_fifo_rusedw1)
				);

Sdram_WR_FIFO 	write_fifo2(
				.data(WR2_DATA),
				.wrreq(WR2),
				.wrclk(WR2_CLK),
				.aclr(WR2_LOAD),
				.rdreq(IN_REQ&WR_MASK[1]),
				.rdclk(CLK),
				.q(mDATAIN2),
				.wrfull(WR2_FULL),
				.wrusedw(WR2_USE),
				.rdusedw(write_side_fifo_rusedw2)
				);
				
assign	mDATAIN	=	(WR_MASK[0])	?	mDATAIN1	:
										mDATAIN2	;

Sdram_RD_FIFO 	read_fifo1(
				.data(mDATAOUT),
				.wrreq(OUT_VALID&RD_MASK[0]),
				.wrclk(CLK),
				.aclr(RD1_LOAD),
				.rdreq(RD1),
				.rdclk(RD1_CLK),
				.q(RD1_DATA),
				.wrusedw(read_side_fifo_wusedw1),
				.rdempty(RD1_EMPTY),
				.rdusedw(RD1_USE)
				);
				
Sdram_RD_FIFO 	read_fifo2(
				.data(mDATAOUT),
				.wrreq(OUT_VALID&RD_MASK[1]),
				.wrclk(CLK),
				.aclr(RD2_LOAD),
				.rdreq(RD2),
				.rdclk(RD2_CLK),
				.q(RD2_DATA),
				.wrusedw(read_side_fifo_wusedw2),
				.rdempty(RD2_EMPTY),
				.rdusedw(RD2_USE)
				);

always @(posedge CLK)
begin
	SA      <= (ST==SC_CL+mLENGTH)			?	12'h200	:	ISA;
    BA      <= IBA;
    CS_N    <= ICS_N;
    CKE     <= ICKE;
    RAS_N   <= (ST==SC_CL+mLENGTH)			?	1'b0	:	IRAS_N;
    CAS_N   <= (ST==SC_CL+mLENGTH)			?	1'b1	:	ICAS_N;
    WE_N    <= (ST==SC_CL+mLENGTH)			?	1'b0	:	IWE_N;
	PM_STOP	<= (ST==SC_CL+mLENGTH)			?	1'b1	:	1'b0;
	PM_DONE	<= (ST==SC_CL+SC_RCD+mLENGTH+2)	?	1'b1	:	1'b0;
	DQM	   <= {(`DSIZE/8){1'b0}}; //( active && (ST>=SC_CL) )	?	(	((ST==SC_CL+mLENGTH) && Write)?	2'b11	:	2'b00	)	:	2'b11	;
	mDATAOUT<= DQ;
end

assign  DQ = oe ? DQOUT : `DSIZE'hzzzz;
assign	active	=	Read | Write;

always@(posedge CLK or negedge RESET_N)
begin
	if(RESET_N==0)
	begin
		CMD			<=  0;
		ST			<=  0;
		Pre_RD		<=  0;
		Pre_WR		<=  0;
		Read		<=	0;
		Write		<=	0;
		OUT_VALID	<=	0;
		IN_REQ		<=	0;
		mWR_DONE	<=	0;
		mRD_DONE	<=	0;
	end
	else
	begin
		Pre_RD	<=	mRD;
		Pre_WR	<=	mWR;
		case(ST)
		0:	begin
				if({Pre_RD,mRD}==2'b01)
				begin
					Read	<=	1;
					Write	<=	0;
					CMD		<=	2'b01;
					ST		<=	1;
				end
				else if({Pre_WR,mWR}==2'b01)
				begin
					Read	<=	0;
					Write	<=	1;
					CMD		<=	2'b10;
					ST		<=	1;
				end
			end
		1:	begin
				if(CMDACK==1)
				begin
					CMD<=2'b00;
					ST<=2;
				end
			end
		default:	
			begin	
				if(ST!=SC_CL+SC_RCD+mLENGTH+1)
				ST<=ST+1;
				else
				ST<=0;
			end
		endcase
	
		if(Read)
		begin
			if(ST==SC_CL+SC_RCD+1)
			OUT_VALID	<=	1;
			else if(ST==SC_CL+SC_RCD+mLENGTH+1)
			begin
				OUT_VALID	<=	0;
				Read		<=	0;
				mRD_DONE	<=	1;
			end
		end
		else
		mRD_DONE	<=	0;
		
		if(Write)
		begin
			if(ST==SC_CL-1)
			IN_REQ	<=	1;
			else if(ST==SC_CL+mLENGTH-1)
			IN_REQ	<=	0;
			else if(ST==SC_CL+SC_RCD+mLENGTH)
			begin
				Write	<=	0;
				mWR_DONE<=	1;
			end
		end
		else
		mWR_DONE<=	0;

	end
end
//	Internal Address & Length Control
always@(posedge CLK or negedge RESET_N)
begin
	if(!RESET_N)
	begin
		rWR1_ADDR		<=	WR1_ADDR;
		rWR1_MAX_ADDR	<=	WR1_MAX_ADDR;
		rWR2_ADDR		<=	WR2_ADDR;
		rWR2_MAX_ADDR	<=	WR2_MAX_ADDR;
		rRD1_ADDR		<=	RD1_ADDR;
		rRD1_MAX_ADDR	<=	RD1_MAX_ADDR;
		rRD2_ADDR		<=	RD2_ADDR;
		rRD2_MAX_ADDR	<=	RD2_MAX_ADDR;
		rWR1_LENGTH		<=WR1_LENGTH;
		rRD1_LENGTH		<=RD1_LENGTH;
		rWR2_LENGTH		<=WR2_LENGTH;
		rRD2_LENGTH		<=RD2_LENGTH;
	end
	else
	begin
		//	Write Side 1
		if(WR1_LOAD)
		begin
			rWR1_ADDR	<=	WR1_ADDR;
			rWR1_LENGTH	<=	WR1_LENGTH;
		end
		else if(mWR_DONE&WR_MASK[0])
		begin
			if(rWR1_ADDR<rWR1_MAX_ADDR-rWR1_LENGTH)
			rWR1_ADDR	<=	rWR1_ADDR+rWR1_LENGTH;
			else
			rWR1_ADDR	<=	WR1_ADDR;
		end
		//	Write Side 2
		if(WR2_LOAD)
		begin
			rWR2_ADDR	<=	WR2_ADDR;
			rWR2_LENGTH	<=	WR2_LENGTH;
		end
		else if(mWR_DONE&WR_MASK[1])
		begin
			if(rWR2_ADDR<rWR2_MAX_ADDR-rWR2_LENGTH)
			rWR2_ADDR	<=	rWR2_ADDR+rWR2_LENGTH;
			else
			rWR2_ADDR	<=	WR2_ADDR;
		end
		//	Read Side 1
		if(RD1_LOAD)
		begin
			rRD1_ADDR	<=	RD1_ADDR;
			rRD1_LENGTH	<=	RD1_LENGTH;
		end
		else if(mRD_DONE&RD_MASK[0])
		begin
			if(rRD1_ADDR<rRD1_MAX_ADDR-rRD1_LENGTH)
			rRD1_ADDR	<=	rRD1_ADDR+rRD1_LENGTH;
			else
			rRD1_ADDR	<=	RD1_ADDR;
		end
		//	Read Side 2
		if(RD2_LOAD)
		begin
			rRD2_ADDR	<=	RD2_ADDR;
			rRD2_LENGTH	<=	RD2_LENGTH;
		end
		else if(mRD_DONE&RD_MASK[1])
		begin
			if(rRD2_ADDR<rRD2_MAX_ADDR-rRD2_LENGTH)
			rRD2_ADDR	<=	rRD2_ADDR+rRD2_LENGTH;
			else
			rRD2_ADDR	<=	RD2_ADDR;
		end
	end
end
//	Auto Read/Write Control
always@(posedge CLK or negedge RESET_N)
begin
	if(!RESET_N)
	begin
		mWR		<=	0;
		mRD		<=	0;
		mADDR	<=	0;
		mLENGTH	<=	0;
	   RD_MASK <= 0;
	   WR_MASK <= 0; 
	end
	else if(Sdram_Init_Done)
	begin
		if( (mWR==0) && (mRD==0) && (ST==0) &&
			(WR_MASK==0)	&&	(RD_MASK==0) &&
			(WR1_LOAD==0)	&&	(RD1_LOAD==0) &&
			(WR2_LOAD==0)	&&	(RD2_LOAD==0) )
		begin
			//	Read Side 1
			if( (read_side_fifo_wusedw1 < rRD1_LENGTH) )
			begin
				mADDR	<=	rRD1_ADDR;
				mLENGTH	<=	rRD1_LENGTH;
				WR_MASK	<=	2'b00;
				RD_MASK	<=	2'b01;
				mWR		<=	0;
				mRD		<=	1;				
			end
			//	Read Side 2
			else if( (read_side_fifo_wusedw2 < rRD2_LENGTH) )
			begin
				mADDR	<=	rRD2_ADDR;
				mLENGTH	<=	rRD2_LENGTH;
				WR_MASK	<=	2'b00;
				RD_MASK	<=	2'b10;
				mWR		<=	0;
				mRD		<=	1;
			end
			//	Write Side 1
			else if( (write_side_fifo_rusedw1 >= rWR1_LENGTH) && (rWR1_LENGTH!=0) )
			begin
				mADDR	<=	rWR1_ADDR;
				mLENGTH	<=	rWR1_LENGTH;
				WR_MASK	<=	2'b01;
				RD_MASK	<=	2'b00;
				mWR		<=	1;
				mRD		<=	0;
			end
			//	Write Side 2
			else if( (write_side_fifo_rusedw2 >= rWR2_LENGTH) && (rWR2_LENGTH!=0) )
			begin
				mADDR	<=	rWR2_ADDR;
				mLENGTH	<=	rWR2_LENGTH;
				WR_MASK	<=	2'b10;
				RD_MASK	<=	2'b00;
				mWR		<=	1;
				mRD		<=	0;
			end
		end
		if(mWR_DONE)
		begin
			WR_MASK	<=	0;
			mWR		<=	0;
		end
		if(mRD_DONE)
		begin
			RD_MASK	<=	0;
			mRD		<=	0;
		end
	end
end

endmodule

5、上位机发送模块


module uart_tx_ctrl(
	input 				clk,
	input 				rst_n,
	
	input 				target_detect,
	
	output reg 			uart_tx_en  ,
	output reg [7:0]	uart_tx_data,
    
    input               uart_tx_done
);

wire [ 7:0] string_data [15:0];      //待发送字符串

assign string_data[0] = "I";
assign string_data[1] = "n";
assign string_data[2] = "t";
assign string_data[3] = "r";
assign string_data[4] = "u";
assign string_data[5] = "d";
assign string_data[6] = "e";
assign string_data[7] = "r";
assign string_data[8] = 8'h21;  // '!'
assign string_data[9] = 8'h0A;  // '\n'

reg [4:0] ctrl_state  ;
reg [3:0] cmd_byte_cnt;

//状态机, 
always @(posedge clk or negedge rst_n) begin 
    if (!rst_n) begin 
        ctrl_state      <= 5'd0;
        cmd_byte_cnt    <= 4'd0;
        uart_tx_en      <= 1'b0;
        uart_tx_data    <= 8'd0;
    end
    else begin
        case(ctrl_state)
            //Idle,无数据发送状态
            5'd0: begin
                cmd_byte_cnt   <= 4'd0;
                uart_tx_en     <= 1'b0;
                uart_tx_data   <= 8'd0;
            
                if(target_detect  == 1'b1) begin   //有目标出现  
                    ctrl_state     <= 5'd1;          
                end
                else begin                      
                    ctrl_state  <= 5'd0;            
                end
            end

            //开始发送串口数据
            5'd1: begin
                uart_tx_en      <= 1'b1;    //拉高发送使能
                uart_tx_data    <= string_data[cmd_byte_cnt];
                ctrl_state      <= 5'd2;    //等待发送完成
            end
            
            //等待字节发送完成 
            5'd2: begin
                uart_tx_en   <= 1'b0;
                
                if(uart_tx_done) begin   // 字节发送完成
                    if(cmd_byte_cnt < 4'd9) begin   
                        ctrl_state      <= 5'd1;    //字符串继续发送
                        cmd_byte_cnt    <= cmd_byte_cnt + 1'b1;
                    end
                    else begin
                        ctrl_state      <= 5'd0;    //字符串继续发送
                        cmd_byte_cnt    <= 4'd0;
                    end
                end
            end
            
            default: begin
                ctrl_state  <= 5'd0; 
            end

        endcase
    end
end

endmodule 

五、工程及套件获取

1、工程获取

A:直接点击下载:基于FPGA:运动目标检测(LCD显示+串口输出,完整工程).zip

B:私信我或添加邮箱获取(完整原理图+源码工程+关键模块仿真)(另外赠送基于FPGA单目标运动检测VGA显示)

2、套件

      觉得调试麻烦的,我手上有几套调试好的套件,有需要的话,可以购买,上电就可以看现象,方便。有需要添加我邮箱:[email protected]

基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第5张图片
基于FPGA:运动目标检测(LCD显示+串口输出,纯Verilog工程)_第6张图片

你可能感兴趣的:(FPGA,fpga开发,目标检测,LCD显示,串口输出)