VGA成像原理与简单实现_vga消隐-程序员宅基地

技术标签: fpga开发  FPGA代码分享  

VGA系列文章目录:
(1)VGA成像原理与简单实现
(2)VGA显示板级验证
(3)VGA显示-多分辨率输入
(4)串口发送+RAM+VGA传图


前言

本篇文章简单记录VGA成像原理与时序解析,使用Verilog初步实现。如有错误,还请批评指正,谢谢。


提示:以下是本篇文章正文内容,下面案例可供参考

一、VGA成像原理

在 VGA 标准兴起的时候,常见的彩色显示器一般由 CRT(阴极射线管)构成,色彩是由 RGB 三基色组成。显示是用逐行扫描的方式解决。阴极射线枪发出的电子束打在涂有荧光粉的荧光屏上,产生 RGB 三基色,合成一个彩色像素,扫描从屏幕的左上方开始,从左到右,从上到下进行扫描,每扫完一行,电子束都回到屏幕的下一行左边的起始位置。
图片扫描方式

在这期间,CRT 对电子束进行消隐。每行结束时,用行同步信号进行行同步;扫描完所有行,用场同步信号进行场同步,并使扫描回到屏幕的左上方。同时进行场消隐,预备下一场的扫描。

二、VGA成像时序详解

1.下图为VGA成像的综合时序:下图中,黑底的JAMES人物图像就是我们希望显示的图像内容。我们的目的就是要让该图像恰好完全显示在显示器上。而 CRT 显示器是基于电子枪的,通过电子轰击荧光粉来产生明暗不同的亮度,从而实现图像线索。所以这一幅图像,可以理解为横向的很多行图像向下依次平铺构成的,而每一行图像,又可以理解为由多个像素点从左向右依次平铺构成的。电子枪每次只能点亮一个点上的荧光粉,所以需要像我们人眼看文章一样,从左向右一个字一个字的看,看完一行内容后,再把视线回到左侧,另起一行开始看,这也就是 CRT 的成像方式。VGA成像综合时序图

2.行扫描:虽然扫描的时候是按照一行一行的方式进行的,但不是扫描完一行有效数据段之后就立马返回,而是会继续向右扫描一段区域,这个区域称为右边界区域( horizontal right border ),该区域己经不在有效的显示范围内,如果从物理结构的角度来说,这一段对应的荧光屏玻璃上就不再有荧光粉了,但是电子枪还在继续向右走,大家可以形象理解为显示器右边的黑边。同样的,显示器左边也有这样一段黑边,在开始显示有效数据之前,电子枪扫描到的这段区城同样也是没有荧光粉的,不会显示图像,这个区城称为左边界区域( horizontal left border )。

当电子枪扫描一行图像到达荧光屏的最右端后,其并不会自动回到最左边准备下一行,而是需要有一个通知信号,通知其回去,这个通知信号就是行同步信号脉冲( horizontal sync pulse )。行同步信号是一个脉冲,当该脉冲出现后,电子枪的指向会在一定时间内从最右侧回到显示屏的最左侧。而这个回去的过程需要耗费一定的时间,这个时间就称为 (horizontal back porch) 。这也是这个名词中 back 的意义所在,即出现行同步信号后,电子尬从显示屏最石侧回到最左侧的时间。当电子枪扫描过了右侧没有荧光粉的区城后还没有收到回到最左侧的命令(行同步信号脉冲)之前,电子枪需要关闭以实现消隐,这个消隐的时间段就称为 (horizontal front porch),直观一点理解就是完成了一行图像的扫描,但还没收到回到最左侧命令之前的一段时间。
行扫描时序图
3.场扫描:场扫描与行扫描原理类似。
场扫描时序图

三、VGA成像设计

设计VGA成像需要找到几个关键时间节点:
行扫描时间节点:(以640*480为例)
1.行脉冲的开始位置HS_Begin(HS_YC下降沿) =0
2.行脉冲的结束位置HS_End (HS_YC上升沿)=96(Pclk)
3.行数据开始输出位置Hdata_Begin=96+40+8
4.行数据停止输出位置Hdata_End=96+40+8+640
5.行同步信号的结束位置Hsync_end=96+40+8+640+8+8 = 800
场扫描时间节点:
1.场脉冲的开始位置VS_Begin(VS_YC下降沿)=0
2.场脉冲的结束位置VS_End (VS_YC上升沿)=2(Line)
3.场数据开始输出位置Vdata_Begin=2+25+8
4.场数据停止输出位置Vdata_End=2+25+8+480
5.场同步信号的结束位置Vsync_end=2+25+8+480+8+2 = 525
相关参数如下表表所示:
相关参数数据表

四、VGA控制器Verilog设计实现

`timescale 1ns / 1ps
//

// Create Date: 2022/11/30 15:18:34
// Module Name: VGA_CTRL_640x480
// Project Name: 640x480图像输出
// Revision: VIVADO 2018.3
// Name:小王在努力...
//


module VGA_CTRL_640x480(
    clk,
    reset,
    Data,
    Data_request,
    HS_YS,
    VS_YS,
    VGA_BLK,
    RGB_output
    );
    input clk;
    input reset;
    input [23:0]Data;             //输入数据
    output  reg Data_request;     //数据请求脉冲信号
    output reg HS_YS;           //行同步脉冲信号
    output reg VS_YS;           //场同步脉冲信号
    output reg VGA_BLK;         //VGA有效数据显示脉冲信号
    output reg [23:0]RGB_output;      //RGB输出值 
      
    parameter [9:0]Hsync_end = 10'd800; 
    parameter [6:0]HS_END = 7'd96;
    parameter [9:0]Vsync_end = 10'd525;
    parameter [1:0]VS_END = 2'd2;
    parameter [7:0]Hdata_begin = 8'd144;
    parameter [9:0]Hdata_end = 10'd784;
    parameter [5:0]Vdata_begin = 6'd35;
    parameter [9:0]Vdata_end = 10'd515; 
    reg [9:0]H_cnt;
    always @ (posedge clk or negedge reset)
        if(!reset)
            H_cnt <= 0;
        else if(H_cnt >= Hsync_end -1 )
            H_cnt <= 0;
        else 
            H_cnt <= H_cnt + 1'b1;
    //  行同步脉冲信号      
    always @ (posedge clk)
        HS_YS <= (H_cnt <= HS_END-1 )?0:1;
        
        
     reg [9:0]V_cnt;
    always @ (posedge clk or negedge reset)
        if(!reset)
            V_cnt <= 0;
        else if( H_cnt == Hsync_end -1)begin
            if(V_cnt >= Vsync_end-1)
                V_cnt <= 0;
            else 
                V_cnt <= V_cnt + 1;
            end
        else 
             V_cnt <= V_cnt ;
    //场同步脉冲信号         
    always @ (posedge clk)
        VS_YS <= (V_cnt <= VS_END-1 )?0:1; 
    
    // Data_request 数据请求脉冲    
    always @ (posedge clk) 
        Data_request <= (H_cnt >= Hdata_begin - 1 )&&(H_cnt <= Hdata_end - 2)&&(V_cnt >= Vdata_begin)&&(V_cnt <= Vdata_end -1);
   
    //VGA_BLK数据开始发送脉冲 
    always @ (posedge clk) 
        VGA_BLK <= Data_request;
    //RGB_output 数据接收      
    always @ (posedge clk)
        RGB_output <= (Data_request) ?Data:0;
     
endmodule

五、TB文件展示

`timescale 1ns / 1ps
//
// Create Date: 2022/11/30 16:07:54
// Design Name: VGA_CTRL
// Module Name: VGA_CTRL_TB
// Project Name: VGA_CTRL
// Revision:2018.3
// Revision 0.01 - File Created
// Name:小王在努力...
//


module VGA_CTRL_TB();
    reg clk;
    reg reset;
    reg   [23:0]Data;             //输入数据
    wire  Data_request;     //数据请求信号
    wire  HS_YS;           //行同步脉冲信号
    wire  VS_YS;           //场同步脉冲信号
    wire  VGA_BLK;         //VGA有效数据显示脉冲信号
    wire  [23:0]RGB_output;      //RGB输出值 
    
  VGA_CTRL_640x480 VGA_CTRL_640x480_TB(
    clk,
    reset,
    Data,
    Data_request,
    HS_YS,
    VS_YS,
    VGA_BLK,
    RGB_output
    );

    initial clk = 1;
    always #20 clk = ~clk;
    
    initial begin
        reset = 0;
        #201;
        reset = 1;
        #20000000;
        $stop;
    end

    always @ (posedge clk or negedge reset)
        if(!reset)
            Data <= 0;
        else if(Data_request)
            Data <= Data + 1;
        else
            Data <= Data;
endmodule

六、仿真结果分析

1.验证行扫描时间节点
行同步脉冲结束时间
验证HS_End 根据上图HS_YS(白线与黄线间隔)低点平时间为3.84us。此处采用的clk时钟频率为25MHZ,于是根据计算(3.84*1000/40)=96,此处与第三节行脉冲的结束位置HS_End (HS_YC上升沿)=96(Pclk)吻合,故此处验证成功。
行数据开始输出时间
验证·Hdata_Begin 根据上图HS_YS与VGA_BLK之间时间(白线与蓝线)为5.76us,经计算为144个clk时间,于是行数据开始输出位置Hdata_Begin=96+40+8验证成立。
行数据停止输出时间
验证Hdata_End 根据上图HS_YS与VGA_BLK之间时间(白线与蓝线)为31.36us,经计算为784个clk时间,于是行数据停止输出位置Hdata_End=96+40+8+640验证成立。
行同步信号结束时间
验证Hsync_end 根据上图HS_YS(白线与蓝线间隔)时间为32us,经计算为800个clk时间。此处与第三节行同步信号的结束位置Hsync_end = 800吻合,故此处验证成功。
每行发送640个数据
根据640x480数据发送要求,每行应该有640个数据如上图发送Data为0-639而RGB_output接收也为640个数据,没有丢失,至此行数据节点验证完成。

1.验证场扫描时间节点场脉冲结束时间
验证VS_End 根据上图VS_YS(白线与黄线间隔)低点平时间为64us。此处采用的clk时钟频率为25MHZ,于是根据计算(64*1000/40/800)=2,此处与第三节场脉冲的结束位置VS_End (VS_YC上升沿)=2(Line)吻合,故此处验证成功。
场数据开始输出时间
验证·Vdata_Begin 根据上图VS_YS与VS_YS之间时间(白线与蓝线)为1120us,经计算为35个Line时间,于是场数据开始输出位置Vdata_Begin=35验证成立。
场数据停止输出时间
验证Hdata_End 根据上图HS_YS与VS_YS之间时间(蓝线与黄线)为16.48us,经计算为515个Line时间,于是场数据停止输出位置Vdata_End=515验证成立。
场同步信号结束时间
验证Vsync_end 根据上图VS_YS(白线与蓝线间隔)时间为18.8ms,经计算为525个clk时间。此处与第三节场同步信号的结束位置Vsync_end = 525吻合,故此处验证成功。
480列数据
根据640x480数据发送要求,每次应该有480行数据如上图发送Data时间间隔为(两个蓝线之间)15.36ms,经计算为480Line。而RGB_output接收也为480Line个数据,没有丢失,至此场数据节点验证完成。

【附件:】链接:https://pan.baidu.com/s/1uz4Npx6kqVGRXeGbd_HtnQ?pwd=cldn
提取码:cldn

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wd12306/article/details/128136287

智能推荐

Unity ShaderLab 中的内置变量_shaderlab 内置参数-程序员宅基地

文章浏览阅读1.5k次。点此获取官方文档地址所有的这些内置变量类型无需声明,直接使用,需要包含:UnityCG.cginc file.Transformationsfloat4x4 UNITYMATRIXMVP Current modelviewprojection matrixfloat4x4 UNITYMATRIXMV Current model*view matrixfloa_shaderlab 内置参数

MFC定义圆角矩形按钮_修改mfcgroupbox为圆角矩形-程序员宅基地

文章浏览阅读6.8k次。使用仅需两步!第一步:CButton替换为CBtnNoImg。第二步:设置各个状态的颜色,和字体(字体设置可选) { CFont *pFont = new CFont(); pFont->CreateFont(11, //以逻辑单位方式指定字体的高度 0, //以逻辑单位方式指定字体中字符的平均宽度 0, //指定偏离垂线和X轴在显示面上的夹角(单位:0.1_修改mfcgroupbox为圆角矩形

xml配置文件引用properties文件报错_xml文件找不到propertycommonconfigurer.class-程序员宅基地

文章浏览阅读1.6k次。一般是配置文件引用失败引起的正确的配置:<bean id="propertyConfigurer" class="com.jcl.common.spring.web.***PropertyPlaceholderConfigurer"> <property name="envPropFiles"> <lis..._xml文件找不到propertycommonconfigurer.class

Linux结构目录详解-程序员宅基地

文章浏览阅读1.1k次,点赞26次,收藏15次。Linux在Linux中,系统默认的用户是root,其实和 windows 的 administrator 类似,root 用户可以操作操作系统的任何文件和设备,所以在生产环境就不要乱用root了,权利越大,责任越大。学习Linux,就要习惯通过命令行的方式学习,。目前的Linux导图如下。

unity scrollview滚动到指定的位置_unity scrollview滚动到指定位置-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏5次。unity scrollview 滚动到指定位置,需要使用 normalizedPosition,或者 verticalNormalizedPosition,或者 horizontalNormalizedPosition_unity scrollview滚动到指定位置

人脸识别技术优势-程序员宅基地

文章浏览阅读693次。当下人们对信息安全问题格外的注重,并且信息安全也成为这个时代的热门话题。基于密码、个人识别码、磁卡和钥匙等传统的安全措施已不能完全满足社会要求,所以人们把目光投向了生物特征识别技术——利用人体固有的生理特征或行..._人脸识别技术的优点

随便推点

pip命令使用详解-程序员宅基地

文章浏览阅读10w+次,点赞29次,收藏188次。pip很像CentOS系统中的yum命令,用于安装及维护Python包。pip的安装windows其实在windows下是默认安装了pip工具的,只是没有将其所在目录加入Path,导致命令查找不到。 将python安装目录下的scripts目录加入环境变量Path中即可。Linux执行下面命令即可完成安装# wget https://bootstrap.pyp..._pip

2013.9.7 CISA pass的一点感想-程序员宅基地

文章浏览阅读68次。2013.9.7 CISA pass的一点感想 先说一个本人基本情况从事信息安全和BCM工作,考试前没有参加培训机构的培训,从6月中旬开始复习CISA,复习材料就是汇哲的教材书和2本红宝书。 看到论坛上各位大牛600+通过,我的通过分数4开头,就不拿出来show了,以免丢人现眼。在此就和大家分享几点个人复习和备考的感受。1、看到论坛上有大..._cisa 初步成绩报告 not pass

SpringSecurity的使用_spring security 3.7使用-程序员宅基地

文章浏览阅读3.9k次。Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!使用步骤:1:加入依赖 <dependency> <groupId>org.springframework.boot</groupId> _spring security 3.7使用

Linux 执行定时任务 shell脚本_linux定时任务shell脚本-程序员宅基地

文章浏览阅读540次。https://www.cnblogs.com/grimm/p/8794707.html Linux上面执行定时任务,我们可以利用crontab -e直接编辑定时任务 另外我们还可以写好shell脚本,定时去执行shell脚本,这两个方法都可以起到定时执行的作用下面我详细说一下入如何执行shell脚本1.声明一下我安装的lnmp环境,shell脚本存放的位置在 /usr/local..._linux定时任务shell脚本

给WordPress的文章插入数学公式_word公式在wordpress-程序员宅基地

文章浏览阅读5k次。这里是我的个人网站: https://endlesslethe.com/insert-math-formula-into-wordpress.html 有更多总结分享,最新更新也只会发布在我的个人网站上。排版也可能会更好看一点=v= 问题背景 我使用OneNote写总结。在总结数论相关的算法时,文章会包含数学公式。数学公式是MS特有的格式。直接将OneNote复制到WordPre_word公式在wordpress

递归函数求斐波那契数列的前n项_用递归方法编程计算fibonacci数列的前n项。其中fib(0)=0,fib(1)=1,fib(n-程序员宅基地

文章浏览阅读8.2k次,点赞6次,收藏28次。递归函数求斐波那契数列的前n项递归函数求斐波那契数列的前n项实验平台:codeBlocks#include<stdio.h>//函数定义int fib(int m){//前两项为 1 1 if(m==1 || m==2) return 1;//第i项为i-1项与i-2项之和 else return fib(m-1)+fib(m-2) ;}int main(){ int n, i; printf("请_用递归方法编程计算fibonacci数列的前n项。其中fib(0)=0,fib(1)=1,fib(n)=fib(n-1

推荐文章

热门文章

相关标签