01_VGA 显示器驱动设计与验证

1. VGA

1.1 VGA 简介

在这里插入图片描述

1.2 VGA接口及引脚定义

在这里插入图片描述
在这里插入图片描述

1.3 VGA 显示原理

在这里插入图片描述

1.4 VGA 时序标准

在这里插入图片描述

1.4.1 Hsync行同步

行扫描周期的单位是像素
在这里插入图片描述

1.4.2 Vsync 场同步

场扫描周期得单位是行,一个完整得行扫描周期
在这里插入图片描述

1.4.3 重合得部分就是显示部分

在这里插入图片描述

1.5 VGA 显示模式及相关参数

在这里插入图片描述
640 * 480 @ 60
640:一行 :行扫周期又 640个像素点。
480:每一帧图像有480行。
60:在这个模式下 每秒钟显示60次图像,刷新60次。

时钟频率的计算
在这里插入图片描述

2. 实验目标

实验目标:编写 VGA 驱动,使用 FPGA 开发板驱动 VGA 显示器显示十色等宽彩条,VGA 显示模式为 640x480@60。
在这里插入图片描述

3. VGA 硬件资源原理

权电阻网络数模转换
在这里插入图片描述
RGB 565 r:5 g:6 b:5 16位宽 [15:0]
在这里插入图片描述

4. 功能模块

4.1 顶层模块

整个系统的框图
locked 是高电平有效
在这里插入图片描述
在这里插入图片描述

4.2 时钟生成模块

本实验选用经典 VGA 显示模式 640x480@60,理论时钟频率应为 25.175MHz,为了便于时钟生成,我们使用 25MHz 的时钟代替25.175MHz 的时钟,不会对实验造成影响。本次实验工程中,而板卡晶振传入时钟频率为 50MHz。时钟生成模块的作用就是将 50MHz 晶振时钟分频为25MHz 的 VGA 工作时钟。
在这里插入图片描述
在这里插入图片描述

4.3 VGA 时序控制模块

在这里插入图片描述
在这里插入图片描述
产生行场信号,并且把输入的图像信息pix_data,给输出rgb
在这里插入图片描述
Pix_x,Pix_y 就是视频图中的坐标 用于生成图像

4.4 图像数据生成模块

在这里插入图片描述
在这里插入图片描述

5. 波形图

5.1 VGA 时序控制模块

在这里插入图片描述
由时序标准可知:行场信号在同步阶段拉高,设置行场信号计数器。
在这里插入图片描述
图像有效信号
在这里插入图片描述
由上文可知,VGA 只有在有效的显示区域内送入图像数据,图像才会被正确显示,那么在什么时候可以送入图像数据呢?我们可以声明一个有效信号,在图像有效显示区域赋值高电平,在非图像有效显示区域赋值低电平,以此信号为约束条件,控制图像信号的正确输入,定义此信号为图像显示有效信号(rgb_valid)。
当两个计数器计数到图像有效显示区域时,rgb_valid 赋值高电平,否则赋值低电平。 0-34 , 0-144
在这里插入图片描述
pix_x在这里插入图片描述
pix_y, 先扫描行,然后在扫描场
在这里插入图片描述
rgb
在这里插入图片描述
因为本次实验是 VGA 多色彩条的显示,图像数据生成模块 vga_pic 需要以坐标(pix_x,pix_y)为约束条件对 pix_data 信号进行赋值,只能使用时序逻辑的赋值方式,那么pix_data 的赋值时刻会滞后条件满足时刻一个时钟周期,显示图像会出现问题。
为了解决这一问题,我们需要声明新的图像数据请求信号 pix_data_req,该信号要超前
图像显示有效信号(rgb_valid)一个时钟周期,以抵消 pix_data 时序逻辑赋值带来的问题。
在这里插入图片描述
在这里插入图片描述

5.2 图像数据生成模块

在这里插入图片描述
在这里插入图片描述

6. RTL

6.1 vga_ctrl

module vga_ctrl(

    input  wire        vga_clk , //输入工作时钟,频率 25MHz
    input  wire        sys_rst_n , //输入复位信号,低电平有效
    input  wire [15:0] pix_data , //输入像素点色彩信息
    
    output wire [9:0]   pix_x , //输出有效显示区域像素点 X 轴坐标
    output wire [9:0]   pix_y , //输出有效显示区域像素点 Y 轴坐标
	// pix_x 和 pix_y 目的就是为了 rgb 的有效显示
    output wire [15:0]  rgb, //输出像素点色彩信息
	
    output wire         hsync , //输出行同步信号
    output wire         vsync  //输出场同步信号
	
);


//parameter define
parameter H_SYNC = 10'd96 , //行同步
          H_BACK = 10'd40 , //行时序后沿
          H_LEFT = 10'd8 , //行时序左边框
          H_VALID = 10'd640 , //行有效数据
          H_RIGHT = 10'd8 , //行时序右边框
          H_FRONT = 10'd8 , //行时序前沿
          H_TOTAL = 10'd800 ; //行扫描周期
		  
parameter V_SYNC = 10'd2 , //场同步
          V_BACK = 10'd25 , //场时序后沿
          V_TOP = 10'd8 , //场时序上边框
          V_VALID = 10'd480 , //场有效数据
          V_BOTTOM = 10'd8 , //场时序下边框
          V_FRONT = 10'd2 , //场时序前沿
          V_TOTAL = 10'd525 ; //场扫描周期
		  
		  
//wire define
wire rgb_valid ; //VGA 有效显示区域
wire pix_data_req ; //像素点色彩信息请求信号

//reg define
reg [9:0] cnt_h ; //行同步信号计数器
reg [9:0] cnt_v ; //场同步信号计数器



//cnt_h:行同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cnt_h <= 10'd0 ;
	else if(cnt_h == H_TOTAL - 1'd1)
		cnt_h <= 10'd0 ;
	else
		cnt_h <= cnt_h + 1'd1 ;
		
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;

//cnt_v:场同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cnt_v <= 10'd0 ;
	else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
		cnt_v <= 10'd0 ;
	else if(cnt_h == H_TOTAL - 1'd1)
		cnt_v <= cnt_v + 1'd1 ;
	else	
		cnt_v <= cnt_v ;
		

//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;

//rgb_valid:VGA 有效显示区域
assign rgb_valid = (((cnt_h >= H_SYNC + H_BACK + H_LEFT)
					&& (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID))
					&&((cnt_v >= V_SYNC + V_BACK + V_TOP)
					&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
					? 1'b1 : 1'b0;


//pix_data_req:像素点色彩信息请求信号,超前 rgb_valid 信号一个时钟周期
assign pix_data_req = (((cnt_h >= H_SYNC + H_BACK + H_LEFT - 1'b1)
                    && (cnt_h<H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1))
                    &&((cnt_v >= V_SYNC + V_BACK + V_TOP)
                    && (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
                    ? 1'b1 : 1'b0;
					

//pix_x,pix_y:VGA 有效显示区域像素点坐标
assign pix_x = (pix_data_req == 1'b1)
				? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 10'h3ff;


assign pix_y = (pix_data_req == 1'b1)
				? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 10'h3ff;
				
//rgb:输出像素点色彩信息
assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;

		



endmodule

6.2 vga_pic

module vga_pic(
    input wire vga_clk , //输入工作时钟,频率 25MHz
    input wire sys_rst_n , //输入复位信号,低电平有效
	
    input wire [9:0] pix_x , //输入有效显示区域像素点 X 轴坐标
    input wire [9:0] pix_y , //输入有效显示区域像素点 Y 轴坐标
 
    output reg [15:0] pix_data //输出像素点色彩信息
);

parameter H_VALID = 10'd640 , //行有效数据
          V_VALID = 10'd480 ; //场有效数据

parameter RED = 16'hF800, //红色
          ORANGE = 16'hFC00, //橙色
          YELLOW = 16'hFFE0, //黄色
          GREEN = 16'h07E0, //绿色
          CYAN = 16'h07FF, //青色
          BLUE = 16'h001F, //蓝色
          PURPPLE = 16'hF81F, //紫色
          BLACK = 16'h0000, //黑色
          WHITE = 16'hFFFF, //白色
          GRAY = 16'hD69A; //灰色

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge vga_clk or negedge sys_rst_n)
     if(sys_rst_n == 1'b0)
        pix_data <= 16'd0;
     else if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
        pix_data <= RED;
     else if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
        pix_data <= ORANGE;
     else if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
        pix_data <= YELLOW;
     else if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
        pix_data <= GREEN;
     else if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
        pix_data <= CYAN;
     else if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
        pix_data <= BLUE;
     else if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
        pix_data <= PURPPLE;
     else if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
        pix_data <= BLACK;
     else if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
        pix_data <= WHITE;
     else if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
        pix_data <= GRAY;
     else
        pix_data <= BLACK;

endmodule


6.3 vga_colorbar

module vga_colorbar(

    input wire sys_clk , //输入工作时钟,频率 50MHz
    input wire sys_rst_n , //输入复位信号,低电平有效
    
    output wire hsync , //输出行同步信号
    output wire vsync , //输出场同步信号
    output wire [15:0] rgb //输出像素信息

);
 
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//wire define
wire vga_clk ; //VGA 工作时钟,频率 25MHz
wire locked ; //PLL locked 信号
wire rst_n ; //VGA 模块复位信号
wire [9:0] pix_x ; //VGA 有效显示区域 X 轴坐标
wire [9:0] pix_y ; //VGA 有效显示区域 Y 轴坐标
wire [15:0] pix_data; //VGA 像素点色彩信息

//rst_n:VGA 模块复位信号
assign rst_n = (sys_rst_n & locked);

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- clk_gen_inst -------------
ip_pll	ip_pll_inst
(
    .areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
    .inclk0 (sys_clk ), //输入 50MHz 晶振时钟,1bit
    
    .c0 (vga_clk ), //输出 VGA 工作时钟,频率 25MHz,1bit
    .locked (locked ) //输出 pll locked 信号,1bit
);

//------------- vga_ctrl_inst -------------
vga_ctrl vga_ctrl_inst
(
    .vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
    .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
    .pix_data (pix_data ), //输入像素点色彩信息,16bit
    
    .pix_x (pix_x ), //输出 VGA 有效显示区域像素点 X 轴坐标,10bit
    .pix_y (pix_y ), //输出 VGA 有效显示区域像素点 Y 轴坐标,10bit
    .hsync (hsync ), //输出行同步信号,1bit
    .vsync (vsync ), //输出场同步信号,1bit
    .rgb (rgb ) //输出像素点色彩信息,16bit
 );
 
 //------------- vga_pic_inst -------------
 vga_pic vga_pic_inst
 (
    .vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
    .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
    .pix_x (pix_x ), //输入 VGA 有效显示区域像素点 X 轴坐标,10bit
    .pix_y (pix_y ), //输入 VGA 有效显示区域像素点 Y 轴坐标,10bit
    
    .pix_data (pix_data ) //输出像素点色彩信息,16bit
 );
 
 endmodule

7. Testbench

7.1 tb_vga_ctrl

`timescale 1ns/1ns
module tb_vga_ctrl();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire locked ;
wire rst_n ;
wire vga_clk ;
reg sys_clk ;
reg sys_rst_n ;
reg [15:0] pix_data ;

//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//

//sys_clk,sys_rst_n 初始赋值
initial
   begin
      sys_clk = 1'b1;
      sys_rst_n <= 1'b0;
      #200
      sys_rst_n <= 1'b1;
   end

//sys_clk:产生时钟
always #10 sys_clk = ~sys_clk;

//rst_n:VGA 模块复位信号
assign rst_n = (sys_rst_n & locked);

//pix_data:输入像素点色彩信息
always@(posedge vga_clk or negedge rst_n)
   if(rst_n == 1'b0)
     pix_data <= 16'h0000;
   else
     pix_data <= 16'hffff;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- clk_gen_inst -------------
ip_pll	ip_pll_inst
(
    .areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
    .inclk0 (sys_clk ), //输入 50MHz 晶振时钟,1bit
    .c0 (vga_clk ), //输出 VGA 工作时钟,频率 25MHz,1bit
    .locked (locked ) //输出 pll locked 信号,1bit
);

//------------- vga_ctrl_inst -------------
vga_ctrl vga_ctrl_inst
(
    .vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
    .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
    .pix_data (pix_data ), //输入像素点色彩信息,16bit
    
    .pix_x (pix_x ), //输出 VGA 有效显示区域像素点 X 轴坐标,10bit
    .pix_y (pix_y ), //输出 VGA 有效显示区域像素点 Y 轴坐标,10bit
    .hsync (hsync ), //输出行同步信号,1bit
    .vsync (vsync ), //输出场同步信号,1bit
    .rgb (rgb ) //输出像素点色彩信息,16bit
);

endmodule

7.2 tb_vga_colorbar

`timescale 1ns/1ns

module tb_vga_colorbar();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire hsync ;
wire [15:0] rgb ;
wire vsync ;

//reg define
reg sys_clk ;
reg sys_rst_n ;

//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//

//sys_clk,sys_rst_n 初始赋值
initial
   begin
     sys_clk = 1'b1;
     sys_rst_n <= 1'b0;
     #200
     sys_rst_n <= 1'b1;
   end

//sys_clk:产生时钟
always #10 sys_clk = ~sys_clk ;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//

//------------- vga_colorbar_inst -------------
vga_colorbar vga_colorbar_inst
(
    .sys_clk (sys_clk ), //输入晶振时钟,频率 50MHz,1bit
    .sys_rst_n (sys_rst_n ), //输入复位信号,低电平有效,1bit
    
    .hsync (hsync ), //输出行同步信号,1bit
    .vsync (vsync ), //输出场同步信号,1bit
    .rgb (rgb ) //输出 RGB 图像信息,16bit
);

endmodule

猜你喜欢

转载自blog.csdn.net/HeElLose/article/details/131391916