FPGA VGA显示器驱动设计(RGB565)显示彩条

1、VGA显示原理

        VGA,英文全称“Video Graphics Array”,译为视频图形阵列,是一种使用模拟信号进行视频传输的标准协议。

        VGA接口电路原理图如下:

        VGA只能识别模拟信号,而FPGA输出的图像信息为数字信号,在VGA的图像显示中,想要将数字图像信号转换为VGA能够识别的模拟信号有两种方法。

1.使用专用的转换芯片进行转换,但这样的成本也比较高。

2.如上图所示,采用权电阻网络的方式实现数模转换。

VGAD[15:0]:RGB565图像数据;

VGA_HSYNC:VGA行同步信号,TTL电平;

VGA_VSYNC:VGA场同步信号,TTL电平。

        VGA显示器显示图像,并不是直接让图像在显示器上显示出来,而是采用扫描的方式,将构成图像的像素点,在行同步信号和场同步信号的同步下,按照从上到下、由左到右的顺序扫描到显示屏上。VGA显示器扫描方式,具体见下图:

2、VGA时序标准

行时序参数:a:行同步脉冲  b:行后沿  c:行有效  d:行前沿

场时序参数:a:场同步脉冲  b:场后沿  c:场有效  d:场前沿

只有行、场的有效时序交叉区域的数据才有效,也就是图上的黄色区域。 

640*480@60

640x480是指VGA的分辨率,640是指有效显示图像每一行有640个像素点,480是指每一帧图像有480行,@60是指VGA显示图像的刷新频率。

时钟(MHz):25.175MHz

这是VGA显示的工作时钟。

3、模块划分

        一共分为三部分,接口模块、数据产生模块和一个顶层模块。

参考代码

顶层文件代码

/**************************************************************
@File    :   ct_top.v
@Time    :   2024/05/06 15:56:55
@Author  :   renchenglong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   彩条显示顶层
**************************************************************/
`include"../param.vh"
module ct_top(
    input                       clk         ,
    input                       rst_n       ,
    output  [`VGA_DATA_W-1:0]   vga_data    ,
    output                      vga_hsync   ,
    output                      vga_vsync    
);

    wire        clk_vga;
    wire        locked;
    vga_if_pll	vga_if_pll_inst (
        .areset ( ~rst_n    ),
        .inclk0 ( clk       ),
        .c0     ( clk_vga   ),
        .locked ( locked    )
        );

    wire                     st_ready;
    wire                     st_vld  ;
    wire                     st_sop  ;
    wire                     st_eop  ;
    wire  [`VGA_DATA_W-1:0]  st_data ;

    data_gen data_gen(
        /*input                    */ .clk_vga  (clk_vga    ),
        /*input                    */ .rst_n    (locked     ),
        /*input                    */ .st_ready (st_ready   ),
        /*output                   */ .st_vld   (st_vld     ),
        /*output                   */ .st_sop   (st_sop     ),
        /*output                   */ .st_eop   (st_eop     ),
        /*output  [`VGA_DATA_W-1:0]*/ .st_data  (st_data    ) 
    );

    vga_interface vga_interface(
        /*input                    */ .clk_vga   (clk_vga   ),   //25.175M
        /*input                    */ .rst_n     (locked    ),
        /*input                    */ .st_clk    (clk_vga   ),                  
        /*input                    */ .st_sop    (st_sop    ), //数据包开始信号
        /*input                    */ .st_eop    (st_eop    ), //数据包结束信号
        /*input   [`VGA_DATA_W-1:0]*/ .st_data   (st_data   ),
        /*input                    */ .st_vld    (st_vld    ),
        /*output                   */ .st_ready  (st_ready  ),
        /*output  [`VGA_DATA_W-1:0]*/ .vga_data  (vga_data  ), //图像色彩信息
        /*output                   */ .vga_hsync (vga_hsync ), //行
        /*output                   */ .vga_vsync (vga_vsync )  //场
    );


endmodule

接口模块代码

/**************************************************************
@File    :   vga_interface.v
@Time    :   2024/05/06 10:31:55
@Author  :   renchenglong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   VGA接口模块
**************************************************************/
`include"../param.vh"
module vga_interface(
    input                       clk_vga     ,
    input                       rst_n       ,
    input                       st_clk      ,
    input                       st_sop      , //数据包开始信号
    input                       st_eop      , //数据包结束信号
    input   [`VGA_DATA_W-1:0]   st_data     ,
    input                       st_vld      ,
    output                      st_ready    ,

    output  [`VGA_DATA_W-1:0]   vga_data    , //图像色彩信息
    output                      vga_hsync   , //行
    output                      vga_vsync     //场
);

    reg                             work_flag;
    reg	    [$clog2(`H_TOTAL)-1:0]  cnt_h;
    wire		                    add_h_cnt;
    wire                            end_h_cnt;
    reg	    [$clog2(`V_TOTAL)-1:0]  cnt_v;
    wire		                    add_v_cnt;
    wire                            end_v_cnt;	

    wire    [`VGA_DATA_W+2-1:0]     fifo_wr_data;
    wire                            fifo_wr_req ;
    wire                            fifo_rd_req ;
    wire    [`VGA_DATA_W+2-1:0]     fifo_rd_data;
    wire                            fifo_empty  ;
    wire                            fifo_full   ;
    wire                            vga_active  ;  //vga处于行场同时有效区域
/**************************************************************
            同步fifo,流接口转vga (采用fifo IP源代码,不用再去IP处修改参数,直接在这里改就可以了)
**************************************************************/
    assign fifo_wr_req  =   !fifo_full && st_vld && st_ready;
    assign fifo_wr_data =   {st_sop,st_eop,st_data};
    assign fifo_rd_req  =   !fifo_empty && vga_active;
    assign st_ready     =   !fifo_full;

	dcfifo	dcfifo_component (
				.aclr       (!rst_n         ),
				.data       (fifo_wr_data   ),
				.rdclk      (clk_vga        ),
				.rdreq      (fifo_rd_req    ),
				.wrclk      (st_clk         ),
				.wrreq      (fifo_wr_req    ),
				.q          (fifo_rd_data   ),
				.rdempty    (fifo_empty     ),
				.wrfull     (fifo_full      ),
				.eccstatus  (),
				.rdfull     (),
				.rdusedw    (),
				.wrempty    (),
				.wrusedw    ());
	defparam
		dcfifo_component.intended_device_family = "Cyclone IV E",
		dcfifo_component.lpm_numwords = `VGA_FIFO_DEPTH,            //fifo深度
		dcfifo_component.lpm_showahead = "ON",                      //前显模式
		dcfifo_component.lpm_type = "dcfifo",
		dcfifo_component.lpm_width = `VGA_DATA_W + 2,               //数据宽度 VGA数据位宽+sop+eop
		dcfifo_component.lpm_widthu = $clog2(`VGA_FIFO_DEPTH),
		dcfifo_component.overflow_checking = "ON",
		dcfifo_component.rdsync_delaypipe = 4,
		dcfifo_component.read_aclr_synch = "OFF",
		dcfifo_component.underflow_checking = "ON",
		dcfifo_component.use_eab = "ON",
		dcfifo_component.write_aclr_synch = "OFF",
		dcfifo_component.wrsync_delaypipe = 4;

/**************************************************************
                        行场计数器
**************************************************************/	
    always@(posedge clk_vga or negedge rst_n)
        if(!rst_n)
            work_flag <= 0;
        else if(fifo_rd_data[`VGA_DATA_W + 1])   //识别到sop
            work_flag <= 1;
        else if(end_v_cnt)          //一帧图像传输完成
            work_flag <= 0;     

    always@(posedge clk_vga or negedge rst_n)	
        if(!rst_n)								
            cnt_h <= 'd0;						
        else    if(add_h_cnt) begin				
            if(end_h_cnt)						
                cnt_h <= 'd0;  				
            else									
                cnt_h <= cnt_h + 1'b1;		
        end	
    assign add_h_cnt = work_flag ;
    assign end_h_cnt = add_h_cnt && cnt_h == `H_TOTAL - 1 ;

    always@(posedge clk_vga or negedge rst_n)	
        if(!rst_n)								
            cnt_v <= 'd0;						
        else    if(add_v_cnt) begin				
            if(end_v_cnt)						
                cnt_v <= 'd0;  				
            else									
                cnt_v <= cnt_v + 1'b1;		
        end		   									
    assign add_v_cnt = end_h_cnt ;
    assign end_v_cnt = add_v_cnt && cnt_v == `V_TOTAL - 1 ;

    assign vga_active = (cnt_h >= `H_SYNC + `H_BACK) && (cnt_h < `H_SYNC + `H_BACK + `H_AVLD) &&    //数据有效区域
                        (cnt_v >= `V_SYNC + `V_BACK) && (cnt_v < `V_SYNC + `V_BACK + `V_AVLD);

/**************************************************************
                        VGA输出
**************************************************************/
    assign vga_data  = vga_active? fifo_rd_data[15:0] : 0;
    assign vga_hsync = cnt_h >= `H_SYNC; 
    assign vga_vsync = cnt_v >= `V_SYNC;


endmodule

彩条数据产生模块

/**************************************************************
@File    :   data_gen.v
@Time    :   2024/05/06 14:05:35
@Author  :   renchenglong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   彩条数据提供模块
**************************************************************/
`include"../param.vh"
module data_gen(
    input                       clk_vga ,
    input                       rst_n   ,
    input                       st_ready,
    output                      st_vld  ,
    output                      st_sop  ,
    output                      st_eop  ,
    output  [`VGA_DATA_W-1:0]   st_data
);


    reg	    [$clog2(`H_AVLD)-1:0]   cnt_h;
    wire		                    add_h_cnt;
    wire                            end_h_cnt;
    reg	    [$clog2(`V_AVLD)-1:0]   cnt_v;
    wire		                    add_v_cnt;
    wire                            end_v_cnt;

    reg     [`VGA_DATA_W-1:0]       pix_data    ;

/**************************************************************
                    行、场计数器
**************************************************************/
    always@(posedge clk_vga or negedge rst_n)	
        if(!rst_n)								
            cnt_h <= 'd0;						
        else    if(add_h_cnt) begin				
            if(end_h_cnt)						
                cnt_h <= 'd0;  				
            else									
                cnt_h <= cnt_h + 1'b1;		
        end											
    assign add_h_cnt = st_ready ;
    assign end_h_cnt = add_h_cnt && cnt_h == `H_AVLD - 1 ;

    always@(posedge clk_vga or negedge rst_n)	
        if(!rst_n)								
            cnt_v <= 'd0;						
        else    if(add_v_cnt) begin				
            if(end_v_cnt)						
                cnt_v <= 'd0;  				
            else									
                cnt_v <= cnt_v + 1'b1;		
        end											
    assign add_v_cnt = end_h_cnt ;
    assign end_v_cnt = add_v_cnt && cnt_v ==`V_AVLD - 1 ;

/**************************************************************
                        输出彩条
**************************************************************/
    assign st_sop  = cnt_h == 0 && cnt_v == 0; //第一个像素
    assign st_eop  = end_v_cnt;                //最后一个像素
    assign st_vld  = add_h_cnt;
    assign st_data = pix_data ;

    always@(*)                              //十个彩条 可随意调节
        if(cnt_v < `V_AVLD*1/10)
            pix_data = `RED;
        else if(cnt_v < `V_AVLD*2/10)
            pix_data = `ORANGE;
        else if(cnt_v < `V_AVLD*3/10)
            pix_data = `YELLOW;
        else if(cnt_v < `V_AVLD*4/10)
            pix_data = `GREEN;
        else if(cnt_v < `V_AVLD*5/10)
            pix_data = `CYAN;
        else if(cnt_v < `V_AVLD*6/10)
            pix_data = `BLUE;
        else if(cnt_v < `V_AVLD*7/10)
            pix_data = `PURPPLE;
        else if(cnt_v < `V_AVLD*8/10)
            pix_data = `BLACK;
        else if(cnt_v < `V_AVLD*9/10)
            pix_data = `WHITE;
        else 
            pix_data = `GRAY;

endmodule

相关参数文件

/**************************************************************
@File    :   param.vh
@Time    :   2024/05/06 11:15:55
@Author  :   renchenglong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   参数定义
**************************************************************/

/**************************************************************
                    系统参数选择
**************************************************************/
   // `define     BMP     //仿真调试是否使用BMP图片输出,只能用于仿真

   //选择输出边缘检测的方法 二选一
   //`define     MID_SOBEL       //中间值
   //`define      GAUSS_SOBEL   //高斯

  //  `define     min  //仅用于仿真测试
    `define     pix_640x480
    `define     OV5640_LUT_NUM      252

    `define     VGA_FIFO_DEPTH      64
    `define     VDMA_FIFO_DEPTH     2048    //fifo深度
    `define     VDMA_FIFO_DATA_W    18      //VDMA数据位宽 + sop + eop

/**************************************************************
                    图像算法
**************************************************************/

    `define     VIP_DATA_W        8

/**************************************************************
                    VGA彩条测试
**************************************************************/
    `define RED        16'hF800    //红色
    `define ORANGE     16'hFC00    //橙色
    `define YELLOW     16'hFFE0    //黄色
    `define GREEN      16'h07E0    //绿色
    `define CYAN       16'h07FF    //青色
    `define BLUE       16'h001F    //蓝色
    `define PURPPLE    16'hF81F    //紫色
    `define BLACK      16'h0000    //黑色
    `define WHITE      16'hFFFF    //白色
    `define GRAY       16'hD69A    //灰色

/**************************************************************
                    VGA接口配置
**************************************************************/
    `define     VGA_DATA_W  16      //VGA数据位宽

    `ifdef pix_640x480
//640*480@60    时钟25.175Mhz
    `define  H_SYNC     96   //行 同步脉冲
    `define  H_BACK     48   //行 后沿
    `define  H_AVLD     640  //行 数据有效
    `define  H_FRONT    16   //行 前沿
    `define  V_SYNC     2    //列 同步脉冲
    `define  V_BACK     33   //列 后沿
    `define  V_AVLD     480  //列 数据有效
    `define  V_FRONT    10   //列 前沿

    `elsif min                  //仿真用
    `define  H_SYNC     96/10 
    `define  H_BACK     48/10 
    `define  H_AVLD     640/10
    `define  H_FRONT    16/10 
    `define  V_SYNC     2  
    `define  V_BACK     33/10 
    `define  V_AVLD     480/10
    `define  V_FRONT    10/10 

    `else 
    //1280*720@60   时钟74.25Mhz
    `define  H_SYNC     40 
    `define  H_BACK     220 
    `define  H_AVLD     1280
    `define  H_FRONT    110 
    `define  V_SYNC     5  
    `define  V_BACK     20 
    `define  V_AVLD     720
    `define  V_FRONT    5 
    `endif 


    `define  H_TOTAL   `H_SYNC+`H_BACK+`H_AVLD+`H_FRONT  //行 扫描周期
    `define  V_TOTAL   `V_SYNC+`V_BACK+`V_AVLD+`V_FRONT  //列 扫描周期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值