【FPGA】VGA驱动:行同步时序+场同步时序

行场都是一样的,唯一不同的是时序的长短

以下说明都建立在640 * 480 的分辨率下:

在行同步

  1. 在行计数器计数到a-96是,行使能输出拉高
  2. 行计数然后会一直计算到800,然后到0时,行使能拉低
  3. 此时 场计数器  由0加1,得到1
  4. 再经过一轮800行计数器,场计数器就自加到2,则达到条件,场使能输出拉高
  5. 一直等到 场计数器一直加到 35时 这才开始传送数据
  6. 但是并不是 场计数一到35就传输的,还必须等到行计数器达到显示后延才行

总体来看:分成段

  1. 行场使能由低拉高,然后输出:使用的时序:800 * 2 = 1600
  2. 行场的显示后延,缓冲阶段:期间度过时序:800 * 33 = 26400
  3. 显示阶段,时钟周期为:480 * 640 = 。。。。
  4. 显示后延

VGA驱动代码:

module vga_driver(
    input           vga_clk,      //VGA驱动时钟
    input           sys_rst_n,    //复位信号
    //VGA接口                          
    output          vga_hs,       //行同步信号
    output          vga_vs,       //场同步信号
    output  [15:0]  vga_rgb,      //红绿蓝三原色输出
    
    input   [15:0]  pixel_data,   //像素点数据
    output  [ 9:0]  pixel_xpos,   //像素点横坐标
    output  [ 9:0]  pixel_ypos    //像素点纵坐标    
    );                             
                                                        
//parameter define  
parameter  H_SYNC   =  10'd96;    //行同步
parameter  H_BACK   =  10'd48;    //行显示后沿
parameter  H_DISP   =  10'd640;   //行有效数据
parameter  H_FRONT  =  10'd16;    //行显示前沿
parameter  H_TOTAL  =  10'd800;   //行扫描周期

parameter  V_SYNC   =  10'd2;     //场同步
parameter  V_BACK   =  10'd33;    //场显示后沿
parameter  V_DISP   =  10'd480;   //场有效数据
parameter  V_FRONT  =  10'd10;    //场显示前沿
parameter  V_TOTAL  =  10'd525;   //场扫描周期
          
//reg define                                     
reg  [9:0] cnt_h;
reg  [9:0] cnt_v;

//wire define
wire       vga_en;
wire       data_req; 

//*****************************************************
//**                    main code
//*****************************************************
//VGA行场同步信号
assign vga_hs  = (cnt_h <= H_SYNC - 1'b1) ? 1'b0 : 1'b1;
assign vga_vs  = (cnt_v <= V_SYNC - 1'b1) ? 1'b0 : 1'b1;

//使能RGB565数据输出,颜色输出的开关
assign vga_en  = (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))		// 判断行信号在有效数据段内
                 &&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))		// 判断场信号在有效数据段内
                 ?  1'b1 : 1'b0;
                 
//RGB565数据输出                 
assign vga_rgb = vga_en ? pixel_data : 16'd0;		// 如果满足要求则能输出颜色信号

//请求像素点颜色数据输入,颜色位置的开关     
assign data_req = (((cnt_h >= H_SYNC+H_BACK-1'b1) && (cnt_h < H_SYNC+H_BACK+H_DISP-1'b1))
                  && ((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
                  ?  1'b1 : 1'b0;

//像素点坐标                
assign pixel_xpos = data_req ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 10'd0;		// 如果满足条件则输出像素对应的位置
assign pixel_ypos = data_req ? (cnt_v - (V_SYNC + V_BACK - 1'b1)) : 10'd0;		// 如果满足条件则输出像素对应的位置

/*
	上述是设计两个开关来控制输出信号
	
*/

//行计数器对像素时钟计数
always @(posedge vga_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n)
        cnt_h <= 10'd0;                                  
    else begin
        if(cnt_h < H_TOTAL - 1'b1)                                               
            cnt_h <= cnt_h + 1'b1;                               
        else 
            cnt_h <= 10'd0;  
    end
end

//场计数器对行计数
always @(posedge vga_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n)
        cnt_v <= 10'd0;                                  
    else if(cnt_h == H_TOTAL - 1'b1) begin
        if(cnt_v < V_TOTAL - 1'b1)                                               
            cnt_v <= cnt_v + 1'b1;                               
        else 
            cnt_v <= 10'd0;  
    end
end

endmodule 

驱动测试代码:

`timescale 1ns/1ps

`define clock_period 20

module VGA_driver_tb;

	reg				sys_clk		;
	reg				sys_rst_n	;
	reg	[15:0]	pixel_data	;
	
	
	wire				vga_hs			;
	wire				vga_vs			;
	wire	[15:0]	vga_rgb		;
	
	wire	[ 9:0]	xpos			;
	wire	[ 9:0]	ypos			;
	
	
	
	vga_driver a1(
    .vga_clk	(sys_clk),      //VGA驱动时钟
    .sys_rst_n	(sys_rst_n),    //复位信号
                      
    .vga_hs		(vga_hs),       //行同步信号
    .vga_vs		(vga_vs),       //场同步信号
    .vga_rgb	(vga_rgb),      //红绿蓝三原色输出
    
    .pixel_data(pixel_data),   //像素点数据
    .pixel_xpos	(xpos),   //像素点横坐标
    .pixel_ypos 	(ypos)   //像素点纵坐标    
    );    

	initial sys_clk = 1;	
	always #(`clock_period / 2) sys_clk = ~sys_clk;
	
	initial begin
		sys_rst_n = 0 ;
		pixel_data = 0;
		
		#(`clock_period * 20 +1);
		sys_rst_n = 1 ;
		pixel_data = 16'h1234;
		
		#(`clock_period * 500_000);
		#20;
		
		
		
		$stop;	
	end

endmodule


总结:

可以看见,VGA驱动模块的功能为:

1.接收16像素数据

2.运行,行+场 同步时序

        2.1 在 行+场 的发送时序,像素数据,发送出去

        2.2 在 行+场 的发送时序,将此时此刻的,横纵坐标,发送出去

 大概就是这样子了

猜你喜欢

转载自blog.csdn.net/qq_42792802/article/details/127032032