赞
踩
最早做了基于FPGA:运动目标检测(VGA显示,原理图+源码+硬件选择),有网友反应,VGA一个大大的屏幕,做起来很不方便,并且功能过于单一。
因此,在上个工程的基础上,修改成了TFT-LCD屏幕检测,并且将检测结果通过串口输出到电脑上位机上,以便大家做扩展开发。
话不多说,先上视频看效果。
基于FPGA运动目标检测(LCD显示-串口输出)
开发板Altera:EP4CE6F17C8(兼容E10)
摄像头:OV5640
屏幕:TFT-LCD
缓存数据:SDRAM
板子是自制的
本系统在图像采集之前,由于板载晶振与摄像头模块及 TFT-LCD 模块频率不一致,所以在系统工作之前,需要设计锁相环模块输出与OV5640摄像头一致的时钟信号。时钟输入后,根据 OV5640 的手册进行寄存器配置,使 OV5640 的工作模式符合本系统的设计需求。CMOS 传感器采集进来的图像进入到图像处理模块,输出当前帧的灰度,用于写入SDRAM。同时从SDRAM中读出前一帧的灰度(与当前输出相差一个时钟周期)重新进入图像处理模块进行帧差法的图像处理(即运动目标检测相关的处理)。
在本系统中,满足选择功能的情况下,更需要满足实时性,所以选择只输入一路视频流。并且根据时钟域不同,设计了异步 FIFO 完成数据传输缓存。最后将处理结果通过 ILI9488 驱动模块显示在屏幕上,并将检测信息通过串口输出到上位机上。
代码框架:本设计基本使用纯Verilog设计,运用了较少的IP,如:PLL,FIFO。代码附带注释,可读性强,便于大家移植,参加竞赛、毕设。
部分模块仿真:
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
`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
//功能: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
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
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
A:直接点击下载:基于FPGA:运动目标检测(LCD显示+串口输出,完整工程).zip
B:私信我或添加邮箱获取(完整原理图+源码工程+关键模块仿真)(另外赠送基于FPGA单目标运动检测VGA显示)
觉得调试麻烦的,我手上有几套调试好的套件,有需要的话,可以购买,上电就可以看现象,方便。有需要添加我邮箱:bumianzhe@126.com。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。