课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx

上传人:b****5 文档编号:4319567 上传时间:2022-11-29 格式:DOCX 页数:19 大小:84.64KB
下载 相关 举报
课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx_第1页
第1页 / 共19页
课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx_第2页
第2页 / 共19页
课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx_第3页
第3页 / 共19页
课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx_第4页
第4页 / 共19页
课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx

《课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx》由会员分享,可在线阅读,更多相关《课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx(19页珍藏版)》请在冰豆网上搜索。

课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动.docx

课程设计基于FPGA的VGA图像显示设计图像旋转放大单步步进移动和屏保移动

课程设计-基于FPGA的VGA图像显示设计(图像旋转、放大、单步步进移动和屏保移动)

 

电子信息工程专业综合设计(报告)

(课程设计)

 

题目基于FPGA的VGA图像显示设计

(图像旋转、放大、单步步进移动和屏保移动)

二级学院电子信息与自动化学院

专业电子信息工程

班级

学生姓名学号

指导教师

时间2011.12.26-2012.01.13

 

 

图1.方案模块框图

1.2工作原理

根据VGA的显示协议,可以选择不同的显示分辨率。

本设计选择的是800*600的分辨率。

根据相应协议,在“VGA时序控制模块”对行扫描信号HS和场扫描信号VS进行相应的时序控制(具体控制详细信息见“VGA驱动原理”资料文档)。

“ROM内存地址控制模块”根据“按键扫描控制模块”获得的图片显示首坐标xx、yy信息和“VGA时序控制模块”传送过来的hcnt(列计数器值)、vcnt(行计数器值)及相关控制信号计算出正确的内存地址,从rom中取出所需要的像素点的三基色数据。

本设计的功能实现包括:

图像旋转、放大、单步步进移动和屏保移动功能。

其中图像的旋转运用了矩阵的转置原理,通过对图像的内存存储地址矩阵进行转置运算获得图像90°旋转的效果。

图像的放大是通过将包括原像素点在内,相邻的4个点填写相同的颜色来实现的。

1.模块设计及仿真

2.1VGA时序控制模块

VGA时序控制模块是整个显示控制器的关键部分,其实质就是完成VGA显示卡的功能。

主要作用就是在一定的工作频率下,产生准确的时序关系(VS-垂直同步信号,HS-水平同步信号,消隐信号之间的关系)。

及其在准确的时序下对ROM存储器数据进行读取。

其中产生准确的时序关系为此模块重点,在VGA显示过程中,完成一行扫描所需要的时间称为水平扫描时间,完成一帧(一屏)扫描所需要的时间称为垂直扫描时间。

每扫描完一行用行同步信号进行同步;扫描完所有行后用场同步信号进行同步。

本文设计采用的是800×600×75Hz模式。

依据时序标准,每显示行包含1056点,其中800点为有效显示区,256点为消隐区,每行的行同步脉冲低电平宽度为80个像素点;同理每场有625行,有效行为600行,其中场同步脉冲低电平宽度为3行。

其行、场时序如表1,时序图见图2。

 

表1行扫描、场扫描时序

Format

Pixel

Clock

MHz

Horizontal(inPixels)

Vertical(inlines)

Active

Video

Front

Porch

Sync

Pulse

Back

Porch

Active

Video

Front

Porch

Sync

Pulse

Back

Porch

800,600,

75Hz

49.50

800

16

80

160

600

1

3

21

依照这个标准,正好与开发板EP1C12外部晶振频率50MHz相近,可以直接引用外部晶振时钟作为其驱动时钟(只要所用时钟和协议要求的时钟相差不大,不会影响显示效果,最多就是显示的刷新频率不是真正等于75Hz而已)。

图2行HS、场VS时序图

2.2ROM内存地址控制模块

整个显示思路是在800*600分辨率的显示器上开辟一256*64的显示区域来显示图片,因为显示的图片的大小为256*64。

在此区域以外显示指定颜色,例如黑色、蓝色等,作为一个背景色显示。

在本模块中,通过在对ROM内存地址的控制,实现了图片的旋转和一倍放大功能。

以下通过一段关键代码详细讲解其实现原理。

(1)首先分析无旋转状态下的romaddr_control的计算原理:

romaddr_control<=(vcnt(5downto0)-count_tempv(5downto0))

&(hcnt(7downto0)-count_temph(7downto0));

注:

romaddr_control为从rom中取数据时所需要的地址,它对应着图片的没一个像素点的三基色数据;vcnt(5downto0)和hcnt(7downto0)分别表示取vcnt(9downto0)、hcnt(10downto0)的后6、后8个二进制位来做运算。

count_tempv(5downto0)和count_temph(7downto0)同理可以理解其含义。

Vcnt、hcnt实际上可以分别理解为屏幕显示的行和列计数器,count_tempv和count_temph可以分别理解为图片在屏幕上显示的起始行和列坐标。

抛开以上等式,按照正常思路,我们可以得到图片控制地址:

addr_control=(vcnt-count_tempv)*256+(hcnt–count_temph)

通过分析整个mid.vhdl文件,会发现其实上面代码是该等式的高效等效实现。

(2)从矩阵的角度分析90°旋转的实现

旋转的控制,将图片的显示分为4种状态,“00”表示0°旋转,“01”表示90°旋转,“10”表示180°旋转,“11”表示270°旋转。

首先对比0°旋转和90°旋转图片在屏幕上显示所对应的内存地址矩阵图:

0度显示对应内存地址矩阵:

0*256+0

0*256+1

0*256+254

0*256+255

1*256+0

1*256+1

1*256+254

1*256+255

.

.

.

.

.

.

.

62*256+0

62*256+1

62*256+254

62*256+255

63*256+0

63*256+1

63*256+254

63*256+255

90度显示对应内存地址矩阵:

63*256+0

62*256+0

1*256+0

0*256+0

63*256+1

62*256+1

1*256+1

0*256+1

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

63*256+254

62*256+254

1*256+254

0*256+254

63*256+255

62*256+255

1*256+255

0*256+255

观察前后变化规律,可以看成是进行了矩阵的转置运算。

根据矩阵的转制原理,我们可以根据0°状态下romaddr_control的算法获得90°状态下romaddr_control的算法。

romaddr_control<=(64-(hcnt(5downto0)-count_temph(5downto0)))

&(vcnt(7downto0)-count_tempv(7downto0));

同理可以计算出“10”、“11”状态下的地址控制表达式,即旋转到180°和270°状态的地址控制表达式。

(3)实现一倍放大

实现一倍放大的基本思路为将原来的像素点相邻的另外三个点填上同样的颜色,也就是一个地址对应屏幕上的四个像素位,从而实现放大的效果。

这个比较容易实现,也比较容易想到,将原来的算法改为:

romaddr_control<=(hcnt(6downto1)-count_temph(6downto1))

&(vcnt(8downto1)-count_tempv(8downto1));

2.3按键扫描控制模块

按键扫描控制采用的电平触发机制,5Hz左右的扫描频率,适合于人们的使用习惯。

其中按键的功能里包括了:

a.单步上下、左右的移动;b.放大和不放大两种模式的选择;c.顺时针90°旋转按钮;d.屏保模式自由移动和停止选择按钮。

2.4ROM内存模块

ROM内存中存储的是图片的依次行扫描三基色数据,作为显示时送给VGA显示器的RGB数据。

本设计存储的是一幅256*64的图片,所以定义了一256*64=16384byte的rom内存。

2.结果分析和调试

在调试过程中,我们遇到图片在靠近行和列的零边界线时,会出现整个图片突然消失的问题,而不是想象中的逐渐步入,逐渐消失。

经过查阅资料,发现VHDL中没有能表示负数的数据类型,而在程序的运算过程中,有会出现负数的可能性,即在对图片初始坐标的减运算过程中,可能会将图片的起始坐标减成负数,使图片初始坐标变量进入未知状态,致使图片在屏幕上立即消失的。

经过对程序的修改,排除了大部分的漏洞,让图片显示基本能按设想显示,不排除还存在部分Bug的可能性。

3.体会和感受

经过本次课程设计,学到了很多VHDL的知识,比纯粹的理论教学课堂上学到的知识更多,更加深刻。

实践教学方式对于我们工程运用专业是一个非常适合的教学方式,不仅锻炼了个人的动手能力,而且调动了学习的积极性,改变了我们的学习状态,是一种非常值得重视和推广的教学方式。

4.参考文献

【1】

【2】

【3】

【4】

【5】

【6】

【7】

【8】

【9】

【10】

 

5.附录(程序和元件清单)

(1)800*600VGA时序控制模块代码:

----------------------------------

libraryIEEE;

useIEEE.std_logic_1164.all;

useIEEE.STD_LOGIC_UNSIGNED.ALL;

entityvga800600is

port(

clk:

inSTD_LOGIC;

hs:

outSTD_LOGIc;

vs:

outSTD_LOGIc;

r:

outSTD_LOGIC_VECTOR(2downto0);

g:

outSTD_LOGIC_VECTOR(2downto0);

b:

outSTD_LOGIC_VECTOR(1downto0);

rgbin:

instd_logic_vector(7downto0);

hcntout:

outstd_logic_vector(10downto0);

vcntout:

outstd_logic_vector(9downto0));

endvga800600;

architectureONEofvga800600is

signalhcnt:

std_logic_vector(10downto0);

signalvcnt:

std_logic_vector(9downto0);

begin

hcntout<=hcnt;

vcntout<=vcnt;

process(clk)begin

if(rising_edge(clk))then

if(hcnt<1056)then

hcnt<=hcnt+1;

else

hcnt<=(others=>'0');

endif;

endif;

endprocess;

--thisisVerticalcounter

process(clk)begin

if(rising_edge(clk))then

if(hcnt=800+8)then

if(vcnt<625)then

vcnt<=vcnt+1;

else

vcnt<=(others=>'0');

endif;

endif;

endif;

endprocess;

--thisishspulse

process(clk)begin

if(rising_edge(clk))then

if((hcnt>=800+8+8)and(hcnt<800+8+8+80))then

hs<='0';

else

hs<='1';

endif;

endif;

endprocess;

--thisisvspulse

process(vcnt)begin

if((vcnt>=600+0+1)and(vcnt<600+0+1+3))then

vs<='0';

else

vs<='1';

endif;

endprocess;

process(clk)begin

if(rising_edge(clk))then

if(hcnt<800andvcnt<600)then

r(2downto0)<=rgbin(7downto5);

g(2downto0)<=rgbin(4downto2);

b(1downto0)<=rgbin(1downto0);

else

r<="000";

g<="000";

b<="00";

endif;

endif;

endprocess;

endONE;

(2)rom内存地址控制模块代码:

--------------------------------------

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entitymidis

port(

clk:

instd_logic;

fangda_temp:

instd_logic;

mode:

instd_logic_vector(1downto0);--key按键输入旋转90度信号,下降沿有效

qin:

instd_logic_vector(7downto0);

xx:

instd_logic_vector(9downto0);

yy:

instd_logic_vector(9downto0);

hcntin:

instd_logic_vector(10downto0);

vcntin:

instd_logic_vector(9downto0);

qout:

outstd_logic_vector(7downto0);

romaddr_control:

outstd_logic_vector(13downto0)

);

endmid;

architectureoneofmidis

signalxuanzhuanjiaodu:

std_logic_vector(1downto0);

signalhcnt:

std_logic_vector(10downto0);

signalvcnt:

std_logic_vector(9downto0);

signalqout_temp:

std_logic_vector(7downto0);

signalcount_temph:

std_logic_vector(9downto0);

signalcount_tempv:

std_logic_vector(9downto0);

signalwide:

integerrange0to1024;

signallong:

integerrange0to1024;

begin

--Assignpin

hcnt<=hcntin;

vcnt<=vcntin;

qout<=qout_temp;

xuanzhuanjiaodu<=mode;

process(fangda_temp)

begin

if(fangda_temp='0')then

wide<=256;

long<=64;

else

wide<=512;

long<=128;

endif;

endprocess;

process(xuanzhuanjiaodu)

BEGIN

casexuanzhuanjiaoduIS

WHEN"00"=>

if(fangda_temp='0')then

romaddr_control<=(vcnt(5downto0)-count_tempv(5downto0))--0du

&(hcnt(7downto0)-count_temph(7downto0));

else

romaddr_control<=(vcnt(6downto1)-count_tempv(6downto1))--0du

&(hcnt(8downto1)-count_temph(8downto1));

endif;

WHEN"01"=>

if(fangda_temp='0')then

romaddr_control<=(64-(hcnt(5downto0)-count_temph(5downto0)))--90du

&(vcnt(7downto0)-count_tempv(7downto0));

else

romaddr_control<=(64-(hcnt(6downto1)-count_temph(6downto1)))--90du

&(vcnt(8downto1)-count_tempv(8downto1));

endif;

WHEN"10"=>

if(fangda_temp='0')then

romaddr_control<=(64-(vcnt(5downto0)-count_tempv(5downto0)))--180du

&(256-(hcnt(7downto0)-count_temph(7downto0)));

else

romaddr_control<=(64-(vcnt(6downto1)-count_tempv(6downto1)))--180du

&(256-(hcnt(8downto1)-count_temph(8downto1)));

endif;

WHENOTHERS=>

if(fangda_temp='0')then

romaddr_control<=((hcnt(5downto0)-count_temph(5downto0)))--270du

&(256-(vcnt(7downto0)-count_tempv(7downto0)));

else

romaddr_control<=((hcnt(6downto1)-count_temph(6downto1)))--270du

&(256-(vcnt(8downto1)-count_tempv(8downto1)));

endif;

endcase;

endprocess;

process(xx,yy)begin

if((vcnt=yy)and(hcnt=xx))then

count_temph<=xx;

count_tempv<=yy;

endif;

if((xuanzhuanjiaodu=1)or(xuanzhuanjiaodu=3))then

if((vcntyy+wide))thenqout_temp<="00000111";--cnt(31downto24);

elsif((hcnt>xx)and(hcnt

qout_temp<=qin;---------inputlogo.hex

else

qout_temp<="00000111";--cnt(31downto24);

endif;

else

if((vcntyy+long))thenqout_temp<="00000111";--cnt(31downto24);

elsif((hcnt>=xx)and(hcnt<=xx+wide))then

qout_temp<=qin;---------inputlogo.hex

else

qout_temp<="00000111";--cnt(31downto24);

endif;

endif;

endprocess;

endone;

 

(4)按键控制模块(图象显示顶层程序)

LIBRARYieee;--图象显示顶层程序

USEieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

ENTITYimgIS

port

(clk50MHz:

INSTD_LOGIC;

key1,key2,key3,key4,key,s2,s3:

instd_logic;

hs,vs:

OUTSTD_LOGIC;

r,g:

OUTSTD_LOGIC_VECTOR(2downto0);

b:

outSTD_LOGIC_VECTOR(1downto0)

);

ENDimg;

ARCHITECTUREmodelstruOFimgIS

componentvga800600--VGA显示控制模块

PORT(clk:

INSTD_LOGIC;

rgbin:

INSTD_LOGIC_VECTOR(7downto0);

hs,vs:

OUTSTD_LOGIC;

r,g:

OUTSTD_LOGIC_VECTOR(2downto0);

b:

OUTSTD_LOGIC_VECTOR(1downto0);

hcntout:

OUTSTD_LOGIC_VECTOR(10downto0);

vcntout:

OUTSTD_LOGIC_VECTOR(9downto0)

);

endcomponent;

componentimgrom--图象数据ROM,数据线8位;地址线12位

PORT(clock:

INSTD_LOGIC;

address:

INSTD_LOGIC_VECTOR(13downto0);

q:

OUTSTD_LOGIC_VECTOR(7downto0)

);

endcomponent;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1