一、VGA工作流程

常见的彩色显示器,一般由CRT(阴极射线管)构成,彩色是由R、G、B(红、绿、蓝)三基色组成,CRT用逐行扫描或者隔行扫描的方式实现图像显示,由VGA控制模块产生的水平同步信号和垂直同步信号控制阴极射线枪产生的电子束,打在涂有荧光粉的荧光屏上,产生R、G、B三基色,合成一个彩色像素。扫描从屏幕的左上方开始,由左至右,由上至下,逐行进行扫描,每扫完一行,电子束回到屏幕下一行的起始位置,在回扫期间,CRT对电子束进行消隐,每行结束时用行同步信号HS进行行同步;扫描完所有行,再由场同步信号VS进行场同步,并使扫描回到屏幕的左上方,同时进行场消隐,预备下一场的扫描。

消隐分为两种:行消隐和场消隐,从上图可以清楚看出什么时候应该执行消隐

行消隐:当一行扫描完毕后然后电子枪又转到下一行的这段时间执行。

场消隐:当扫描完所有的行后电子枪回到第一行起始位的这段时间执行。

在消隐期间,数据是无效的,消隐这个动作是显示屏(CRT)执行的,我们在编程时只要注意有这个东西就行。

同步信号分为两种:行同步信号(HS)和场同步信号(VS),它们就相当于一个数据起始信号,表明数据马上就要开始了。

行同步信号产生:

constant HSYNC_A :std_logic_vector(15 downto 0):=x"0080";--128 行同步
--给VGA_HS赋值
process(clk,RST_N)
beginif RST_N='0' thenVGA_HS<='0';elsif clk'event and clk='1' thenVGA_HS<=VGA_HS_N;end if;
end process;--行同步信号
process(hsync_cnt)
beginif hsync_cnt<HSYNC_A then--行同步计数器<行同步VGA_HS_N<='0';elseVGA_HS_N<='1';end if;
end process;--给vsync_cnt赋值
process(clk,RST_N)
beginif RST_N='0' thenvsync_cnt<=x"0000";elsif clk'event and clk='1' thenvsync_cnt<=vsync_cnt_n;end if;
end process;

场同步信号产生:

--采用800*600*60Hz,时钟频率=HSYNC_D*VSYNC_R*60Hz=40MHz
--水平参数
constant HSYNC_A    :std_logic_vector(15 downto 0):=x"0080";--128 行同步
constant HSYNC_B    :std_logic_vector(15 downto 0):=x"00D8";--128+88 行同步+行后沿
constant HSYNC_C    :std_logic_vector(15 downto 0):=x"03F8";--128+88+800 行同步+行后沿+行有效时间
constant HSYNC_D    :std_logic_vector(15 downto 0):=x"0420";--128+88+800+40 行同步+行后沿+行有效时间+行前沿=行周期时间
--垂直参数
constant VSYNC_O    :std_logic_vector(15 downto 0):=x"0004";--4  场同步
constant VSYNC_P    :std_logic_vector(15 downto 0):=x"001B";--4+23 场同步+场后沿
constant VSYNC_Q    :std_logic_vector(15 downto 0):=x"0273";--4+23+600 场同步+场后沿+场有效时间
constant VSYNC_R    :std_logic_vector(15 downto 0):=x"0274";--4+23+600+1 场同步+场后沿+场有效时间+场前沿=场周期时间
--给vsync_cnt赋值
process(clk,RST_N)
beginif RST_N='0' thenvsync_cnt<=x"0000";elsif clk'event and clk='1' thenvsync_cnt<=vsync_cnt_n;end if;
end process;--场同步计数器
process(vsync_cnt,hsync_cnt)
beginif ((vsync_cnt=VSYNC_R) and (hsync_cnt=HSYNC_D)) thenvsync_cnt_n<=x"0000";elsif (hsync_cnt=HSYNC_D) thenvsync_cnt_n<=vsync_cnt+'1';elsevsync_cnt_n<=vsync_cnt;end if;
end process;--VGA_VS赋值
process(clk,RST_N)
beginif RST_N='0' thenVGA_VS<='0';elsif clk'event and clk='1' thenVGA_VS<=VGA_VS_N;end if;
end process;--生成场同步信号
process(vsync_cnt)
beginif vsync_cnt<VSYNC_O then VGA_VS_N<='0';elseVGA_VS_N<='1';end if;
end process;

这HS和VS两个信号不就出来了嘛,有的人会问,“啊,你怎么知道这两个信号在什么时候拉低呢?”,欸,你别着急,现在就告诉你怎么判断的,请看不知传了多少手的表格:

我选择的是倒数第二个 800/600@60Hz的,Ta=同步脉冲,Tb+Tc=消隐后沿时间,Td=数据有效时间,Te+Tf=消隐前沿时间,Tg=周期,它们的数字对应的都是VGA的时钟周期个数,所以,你观察上面的时序图,你会发现他们的本质就是由一个低电平(也就是同步信号)加一个高电平(前沿+后沿+有效时间)构成,这样按照这个时序,写相同的vga时钟周期个数来构成一个占空比周期就可以了,其中刷新速率可以在你电脑上设置,桌面->右键->显示设置->高级显示设置->显示适配器属性->监视器->刷新频率。

的人也许早就发现了VGA时钟的计算方法,vga时钟=水平帧长*垂直帧长*频率

对于普通的VGA显示器,需要引出5个信号:R,G,B,HS,VS。你要是条件允许的话你可以把RGB三个信号分为24位,这样图像也不会失真,像我这样穷的人,只选择了三位。下面讲讲为什么RGB位数越多图像越清晰。(我怎么感觉我前面说的全是废话呢,刚刚进入正题?不要在意这些细节,毕竟第一次写得奖感言)。

首先,要显示一幅图像,必须有一个ROM,ROM里面装着.MIF,MIF里装着图像转换的1和0。用Bmp2RGB.exe把图像转换为mif,最后把数据转换成这样的就可以了,就在mif结尾要有“end;”。

这一步搞定了,那我们准备把大象装冰箱里吧,呸!把mif装到ROM里,首先建一个ROM的ip

这个选项要根据你当初转换mif的格式来选择,mif格式为8bit,此处就选8bit,mif深度为1200,那么rom的深度就要大于1200,点击下一步,把mif导入到FILE name中,下一步,直到完成。

把ROM添加到工程中

--图片参数
constant BMP1_W :std_logic_vector(15 downto 0):=x"001E"; --图片宽度30
constant BMP1_H :std_logic_vector(15 downto 0):=x"0028"; --图片高度40
constant BMP1_X :std_logic_vector(15 downto 0):=x"00e9"; --图片左上角x坐标(233,151)
constant BMP1_Y :std_logic_vector(15 downto 0):=x"0097"; --图片左上角y坐标--存储图片.mif的ROM
component BMPRom isport(address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);clock       : IN STD_LOGIC  := '1';q     : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
end component;uu1:BMPRom port map(clock=>clk,address=>bmp_rom_add,q=>bmp_rom_data);--产生bmp_add信号
tmp1<='1' when (vga_x>=(BMP1_X-X"03")) else '0';
tmp2<='1' when (vga_x<(BMP1_X+BMP1_W-X"03")) else '0';
tmp3<='1' when (vga_y>=BMP1_Y) else '0';
tmp4<='1' when (vga_y<=(BMP1_Y+BMP1_H)) else '0';tmp9<='1' when (vga_x=(BMP1_X-X"03")) else '0';
tmp10<='1' when (vga_y=BMP1_Y) else '0';--用于生成图片位置信号
bmp_add<=tmp1 and tmp2 and tmp3 and tmp4;
process(bmp_add,tmp9,tmp10,RST_N,clk)
beginif RST_N='0' then bmp_rom_add<=x"000";elsif clk'event and clk='1' thenif (tmp9='1' and tmp10='1') thenbmp_rom_add<=x"000";elsif bmp_add='1' thenbmp_rom_add<=bmp_rom_add+'1';elsebmp_rom_add<=bmp_rom_add;end if;end if;
end process;

最后输出RGB数据

tmp16<='1' when hsync_cnt>HSYNC_B else '0';
tmp11<='1' when hsync_cnt<=(HSYNC_B+X"A0") else '0';--彩条宽度=800/5=160tmp12<='1' when hsync_cnt>(HSYNC_B+x"A0") else '0';
tmp13<='1' when hsync_cnt<=(HSYNC_B+X"140") else '0';tmp14<='1' when hsync_cnt>(HSYNC_B+X"140") else '0';
tmp15<='1' when hsync_cnt<=(HSYNC_B+X"1E0") else '0';tmp17<='1' when hsync_cnt>(HSYNC_B+X"1E0") else '0';
tmp18<='1' when hsync_cnt<=(HSYNC_B+X"280") else '0';tmp19<='1' when hsync_cnt>(HSYNC_B+X"280") else '0';
tmp20<='1' when hsync_cnt<=(HSYNC_B+X"320") else '0';tmp_P<='1' when vsync_cnt>VSYNC_P else '0';
tmp_Q<='1' when vsync_cnt<VSYNC_Q else '0';
process(RST_N,clk,bmp_en,tmp11,tmp12,tmp13,tmp14,tmp15,tmp16,tmp17,tmp18,tmp19,tmp20,tmp_P,tmp_Q)
beginif RST_N='0' thenVGA_DATA_N<="110";--测试elsif clk'event and clk='1' thenif (bmp_en='1') then VGA_DATA_N<=bmp_rom_data(7)&bmp_rom_data(4)&bmp_rom_data(0);   --由于FPGA只有三个引脚关于VGA的,所以取中,VGA引脚越多,图像越精确。elsif ((tmp16='1')and(tmp11='1')and(tmp_P='1')and(tmp_Q='1'))then  --图片以外,用彩条填充VGA_DATA_N<="100";elsif((tmp12='1')and(tmp13='1')and(tmp_P='1')and(tmp_Q='1'))thenVGA_DATA_N<="110";elsif((tmp14='1')and(tmp15='1')and(tmp_P='1')and(tmp_Q='1'))thenVGA_DATA_N<="010";elsif((tmp17='1')and(tmp18='1')and(tmp_P='1')and(tmp_Q='1'))thenVGA_DATA_N<="011";elsif((tmp19='1')and(tmp20='1')and(tmp_P='1')and(tmp_Q='1'))thenVGA_DATA_N<="001";    elseVGA_DATA_N<="000";end if;end if;

基本就是这些内容,然后仿真

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;entity vga_tb is
--  port();
end vga_tb;architecture behave of vga_tb is
component vga isport(CLK_50M    :in std_logic;RST_N :in std_logic;VGA_HS,VGA_VS :out std_logic;--vga时钟、空白信号、同步信号、水平信号、垂直信号VGA_DATA  :out std_logic_vector(2 downto 0)   --vga数据端口 rgb三色);
end component;signal CLK_50M,RST_N,VGA_HS,VGA_VS:std_logic;
signal VGA_DATA:std_logic_vector(2 downto 0);constant clk_period:time:=20 ns;begin
uuu1:vga port map(CLK_50M=>CLK_50M,RST_N=>RST_N,VGA_HS=>VGA_HS,VGA_VS=>VGA_VS,VGA_DATA=>VGA_DATA);clock:process
beginCLK_50M<='1';wait for clk_period/2;CLK_50M<='0';wait for clk_period/2;
end process;reset:process
beginRST_N<='0';wait for clk_period*2;RST_N<='1';wait;
end process;end behave;

从前有个人叫仿真,他得了一种不长毛的病,大声说出来,仿真得了什么病。

效果图:(这就是RGB只用了三个输出的结果,哪怕有一点条件我都会用24bit)

图像,你细品,是不是这回事。

谢谢大家,我的演讲到此结束,不喜勿喷,有错误请指出。

源代码下载地址:https://download.csdn.net/download/qq_36956923/19144104

FPGA实现VGA显示图像(VHDL版)相关推荐

  1. FPGA——用VGA时序显示图像原理详解(2)

    目录 VGA时序 VGA显示 大家结合上一篇: FPGA--用VGA时序显示图像原理详解(1)_居安士的博客-CSDN博客 VGA时序 首先我们下载数据手册,我们可以根据自己的需求,选择图像大小,以及 ...

  2. 勘误发布:《数字滤波器的MATLAB与FPGA实现——Xilinx/VHDL版》P320

    <数字滤波器的MATLAB与FPGA实现--Xilinx/VHDL版> P320最后一行,N=2^m(m=3~6)修改为    N=2^m(m=3~16). 2019.5.3

  3. FPGA——用VGA时序显示图像(3)(代码)

    FPGA--用VGA时序显示图像原理详解(1)_居安士的博客-CSDN博客_vga时序 FPGA--用VGA时序显示图像原理详解(2)_居安士的博客-CSDN博客_vga显示时序 关于VGA时序的原理 ...

  4. 基于FPGA的VGA/LCD显示控制器设计(中)

    今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇.今天带来第二篇,中篇,VGA 显示原理以及VGA/LCD 显示控制器的基本框架,话不多说,上货. 之前也有图像处理以及V ...

  5. imut FPGA课设 基于FPGA的VGA弹球游戏设计 *秋昊

    写在前面的话: 本文主要呈现了一篇IMUT的FPGA课设报告. 课设报告内容(word版),视频演示,程序源码,专业创新实践简介,专业创新实践指导书均已放入下面的百度云链接中,也不大,总共不到20MB ...

  6. 新书预告:Xilix FPGA数字信号处理设计——基础版

    掌握FPGA数字信号处理设计需满足三个条件:熟悉FPGA设计方法.理解数字信号处理理论.掌握理论的工程实现方法.对初学者来讲,每个条件看似都难以逾越.杜勇老师完美融合课程教学与工程设计的需求特点,以独 ...

  7. 【接口协议】FPGA 驱动 VGA 显示实验(二)实验设计部分

    目录 实验任务 实验环境 实验设计 程序设计 VGA 时序模块 模块框图 仿真波形 顶层模块 约束文件 实验任务 利用FPGA驱动VGA实现彩条显示,分辨率为800 × 600@60Hz,分别显示三种 ...

  8. 基于FPGA的VGA显示对贪吃蛇游戏的设计

    基于FPGA的VGA显示对贪吃蛇游戏的设计 摘要 目前,电子数码产品已经进入了人生活的方方面面,而大多数电子产品都依靠显示屏来传递信息,由此可见用电路对显示屏进行控制的研究有很大的实用价值和市场需求. ...

  9. (74)FPGA模块调用(VHDL调用VHDL)

    (74)FPGA模块调用(VHDL调用VHDL) 1.1 目录 1)目录 2)FPGA简介 3)Verilog HDL简介 4)FPGA模块调用(VHDL调用VHDL) 5)结语 1.2 FPGA简介 ...

最新文章

  1. 利用三个点(trsf)来实现各种规则图形的实现
  2. #2002 Cannot log in to the MySQL server, PHPMyAdmin/MySQL
  3. Python赋值、浅拷贝、深拷贝
  4. 调试工具_Apifox for Mac(接口调试管理工具)
  5. sql while循环_SQL WHILE循环的简单示例
  6. 供应商层次分析法判断矩阵(文末附软件)
  7. clover windows安装_记一次使用AMD安装macOS Catalina的经历
  8. 计算机组成原理408
  9. struts中ActionForm有什么作用?
  10. 【百度编辑器】修改上传图片缩略图大小
  11. yolov5系列-yolov5模型部署到web端
  12. 现代软件工程讲义 5.1 软件的质量保证 (QA) 和测试 (Test)
  13. Andriod中如何新建lunch项
  14. 百度地图 AK 申请 / 签名获取及使用方式
  15. HP580G7服务器电流
  16. 用 VMware 12 Player 安装Ubuntu 14.04.5 分区时提示“没有定义根文件系统,请回到分区菜单以修正此错误”
  17. 设计模式05——结构型模式
  18. vim gvim技巧大全
  19. 笔记:Bootstrap导航与router-link 不和谐
  20. 前端大文件上传断点续传解决方案

热门文章

  1. long long类型上限_oracle long类型字段的处理
  2. python 矩阵操作
  3. 怎么解决长期戴口罩脸过敏的肌肤问题
  4. 当SDS遇见BlockChain 之二:区块链存储为什么势在必行?(SDS的新赛道 - 暗流涌动的区块链存储)...
  5. 安卓手机在高端市场再次败落,全靠中低端机型撑场
  6. 进程间的7种通信方式全解析及代码示例
  7. python可视化界面开发实例-python界面编程,python可视化窗口编程
  8. go binary包
  9. C# 错误代码为 0xc0000005。
  10. Java之Map循环方式