10. 基于rom的vga图像显示弹跳特效

我们在为计算机设置屏保时会发现,计算机屏保图片的显示往往可以设置一些特效,其中比较经典的特效就是弹跳特效。那么这种弹跳特效是怎么实现的呢?

在本章节,我们在上一章节设计实验工程基础上,稍作修改,赋予显示图片弹跳特效,使其在显示区域内触框反弹。

10.1. 理论学习

本章节涉及的VGA理论知识,详见 “VGA显示器驱动设计与验证”章节的“理论学习”小结;待显示图片预处理操作,详见,“基于ROM的VGA图像显示”章节的“理论学习”小结,在此不再赘述。

10.2. 实战演练

10.2.1. 实验目标

实验目标:以十色等宽彩条做背景,将存储于ROM中的图片显示在VGA显示器上,图片显示初始位置为有效显示区域左上角,图片沿着与水平方向45度夹角的方向,向右下角运动,运动过程中,当图片边沿触及显示区域边沿,图片向反方向运动,实现图片弹跳特效。图片分辨率为100*100,VGA显示模式为640x480@ 60。

实验效果,具体见图 39‑1。

ROMVGA002

图 39‑1 基于ROM的VGA图像显示(弹跳特效)实验效果图

10.2.2. 硬件资源

详见“VGA显示器驱动设计与验证”章节的“硬件资源”介绍。

10.2.3. 程序设计

本章节的实验工程是在“基于ROM的VGA图像显示”章节实验工程的基础上修改得到,只修改了图像数据生成模块vga_pic。在本小结的讲解中,我们先讲一下弹跳特效的实现方法,然后讲解一下改动较大的vga_pic模块,整体模块的说明和其他子功能模块的讲解,请读者参阅“基于ROM的VGA图像显示”章节。

10.2.3.1. 弹跳特效的实现方法

由实验目标小节可知,本实验工程要将存储于ROM中的图片显示在VGA显示器上,图片显示初始位置为有效显示区域左上角,图片沿着与水平方向45度夹角的方向,向右下角运动,运动过程中,当图片边沿触及显示区域边沿,图片向反方向运动,实现图片弹跳特效。

读者肯定会心存疑惑,图片是如何运动起来的?运动方向如何实现与水平方向45度夹角?怎样实现图片触框反弹?对于这些问题我们将会一一作答。

问题1:图片是如何运动起来的?

在“基于ROM的VGA显示章节”中,我们将图片固定显示在VGA显示器中间位置,只会在VGA显示器中间的图片显示位置读取ROM中的图片数据。模块实现的部分参考代码如下。

47 //rd_en:ROM读使能

48 assign rd_en = (((pix_x >= (((H_VALID - H_PIC)/2) - 1’b1))

49 && (pix_x < (((H_VALID - H_PIC)/2) + H_PIC - 1’b1)))

50 &&((pix_y >= ((V_VALID - W_PIC)/2))

51 && ((pix_y < (((V_VALID - W_PIC)/2) + W_PIC)))));

52

53 //pic_valid:图片数据有效信号

54 always@(posedge vga_clk or negedge sys_rst_n)

55 if(sys_rst_n == 1’b0)

56 pic_valid <= 1’b1;

57 else

58 pic_valid <= rd_en;

59

60 //pix_data_out:输出VGA显示图像数据

61 assign pix_data_out = (pic_valid == 1’b1) ? pic_data : pix_data;

62

90 //rom_addr:读ROM地址

91 always@(posedge vga_clk or negedge sys_rst_n)

92 if(sys_rst_n == 1’b0)

93 rom_addr <= 14’d0;

94 else if(rom_addr == (PIC_SIZE - 1’b1))

95 rom_addr <= 14’d0;

96 else if(rd_en == 1’b1)

97 rom_addr <= rom_addr + 1’b1;

98

103 //————- rom_pic_inst ————-

104 rom_pic rom_pic_inst

105 (

106 .address (rom_addr ), //输入读ROM地址,14bit

107 .clock (vga_clk ), //输入读时钟,vga_clk,频率25MHz,1bit

108 .rden (rd_en ), //输入读使能,1bit

109

110 .q (pic_data ) //输出读数据,16bit

111 );

由参考代码可以看出,ROM的读使能信号rd_en和图像数据有效信号pic_valid的约束条件都是固定参数,这使它们只能在固定显示区域有效。假如我们每次在一帧图像显示完成后对图像的显示区域重新定义,是否就可以实现显示图片显示位置的变化。

假如我们在每一帧图像显示完成后只改变水平方向的rd_en信号的显示范围,这就可以实现图片在水平方向显示位置的改变。若每次显示位置只向左或向右移动若干个相同的像素点个数,加之人眼的视觉暂留效果,就可以实现显示图片在水平方向上的左右移动。

同理,若每次显示位置只向上或向下移动若干个像素点个数,加之人眼的视觉暂留效果,就可以实现显示图片在竖直方向上的竖直上下移动。

读者要注意的是,左右或者上下移动的像素点个数的多少表示图片移动的快慢,数值越大移动也快,这个数值不固定,可自行设置,但不建议设置太大,数值设置太大图片移动会显的不太流畅,本实验工程设置移动数值为1个像素点,读者也可自行设置参数观察实验效果。

问题二:运动方向如何实现与水平方向45度夹角?

在上一问题的解答中我们实现了显示图片的水平和竖直方向的移动,假使水平方向和竖直方向的移动像素点个数相同,根据勾股定理,图片移动的方向就实现了与水平方向45度夹角。当然读者也可以根据自己喜好,通过更改水平方向和竖直方向的移动像素点个数使图片按照其他方向移动。

问题3:怎样实现图片触框反弹?

我们以水平方向图片移动为例来解答者这一问题。

在图片的第一帧图像显示中,图片的最左边一列像素点与显示区域左边框重合,每刷新一帧图像,图片向右移动若干个像素点;当图片的最右边的一列像素点与显示区域右边框重合,在下一帧图像刷新时,图片开始向反方向移动,这就实现了显示图片水平方向的触框反弹特效。同理,竖直方向也是如此。

10.2.3.2. 图像数据生成模块

在上面小结中,我们主要讲解了显示图片弹跳特效的实现,在本小节我们主要讲解弹跳特效的实现方法。

模块框图

设计本模块的目的是产生VGA彩条背景像素点色彩信息、读出ROM存储的图片数据并实现弹跳特效。模块框图,具体见图 39‑2。

ROMVGA003

图 39‑2 图像数据生成模块框图

由图 39‑2可知,图像数据生成模块包含4路输入、1路输出,共5路信号。输入输出信号简介,具体见表格 39‑1。

表格 39‑1 图像数据生成模块输入输出端口功能描述

信号

位宽

类型

功能描述

vga_clk

1Bit

Input

工作时钟,频率25MHz

sys_rst_n

1Bit

Input

复位信号,低电平有效

pix_x

10Bit

Input

VGA有效显示区域像素点X轴坐标

pix_y

10Bit

Input

VGA有效显示区域像素点Y轴坐标

pix_data

16Bit

Output

图像像素点色彩信息

输入信号中,时钟信号vga_clk,频率为25MHz,为VGA显示器工作时钟,由分频模块产生并输入;复位信号sys_rst_n为顶层模块的rst_n信号输入,低电平有效;(pix_x,pix_y)为VGA有效显示区域像素点坐标,由VGA时序控制模块生并输入。

输出信号pix_data为图像像素点色彩信息,在VGA有效显示区域像素点坐标(pix_x,pix_y)约束下生成,传输到VGA时序控制模块。

模块内部实例化ROM IP核,有三路输入,一路输出,输入信号为时钟、数据读使能和数据地址信号,输出为数据地址对应数据。

波形图绘制

在模块框图部分,我们介绍了图像数据生成模块的具体功能,对输入输出信号做了简单介绍,那么如何利用模块输入信号实现模块功能,输出我们想要得到的数据信号呢?在波形图绘制部分,我们会通过绘制波形图,并对各信号做详细讲解,带领读者学习掌握模块功能的实现方法。

图像数据生成模块波形图,具体见图 39‑3、图 39‑4、图 39‑5、图 39‑6。

ROMVGA004

图 39‑3 图像数据生成模块波形图(一)

ROMVGA005

图 39‑4 图像数据生成模块波形图(二)

ROMVGA006

图 39‑5 图像数据生成模块波形图(三)

ROMVGA007

图 39‑6 图像数据生成模块波形图(四)

上述4图是我们最终绘制生成的图像数据生成模块波形图,下面我们讲解一下波形图绘制的具体思路。

第一部分:彩条背景色彩信息(pix_data)波形图绘制思路

根据输入像素点坐标(pix_x,pix_y),在有效显示区域,将pix_x计数范围十等分,在不同的计数部分给pix_data赋值对应的色彩信息,因为采用时序逻辑的赋值方式,pix_data滞后pix_x、pix_y信号一个时钟周期。信号波形图如下:

ROMVGA008

图 39‑7 pix_data信号波形图

第二部分:ROM读使能(rd_en)、ROM地址(rom_addr)波形图绘制思路

我们将要显示的的图片数据是事先写入ROM,ROM为调用IP核生成,写入照片分辨率为100*100。要想将写入ROM的图片读取出来,使能信号和地址信号必不可少,所以模块内部要声明ROM读使能信号(rd_en)和ROM地址(rom_addr)信号。

我们可以在图片显示区域拉高使能信号,将要读取数据地址写入ROM地址端口,读取地址对应图像数据,但有一点要注意,自ROM读取的数据是滞后使能信号和地址信号一个时钟周期的,比如,当使能信号为高电平,地址写入为999,但与地址999同步输出的数据为地址998的数据,所以ROM读使能信号(rd_en)和RO M地址(rom_addr)信号均要超前图片显示区域一个时钟周期,信号波形图绘制如下:

ROMVGA009

图 39‑8 rd_en、rom_addr信号

第三部分:图片显示有效信号(pic_valid)、待显示图像数据(pic_data_out)波形图绘制思路

想要在彩条图像背景上显示要显示的图片,我们需要在图片显示区域,使用图片数据覆盖彩条背景,那么如何确定图像显示区域呢?我们需要声明一个内部信号,那就是图片显示有效信号(pic_valid),在有效信号为高电平时,将自ROM读出的图片数据赋值给待显示图像数据(pic_data_out),覆盖彩条背景。

上文中我们提到ROM读使能信号(rd_en)超前图片显示区域一个时钟周期,可以利用此信号 延迟一个时钟周期生成图片显示有效信号(pic_valid);在有效信号为高电平时,将自ROM读出的图片数据赋值给待显示图像数据(pic_data_out),覆盖彩条背景。信号波形图如下:

ROMVGA010

图 39‑9 pic_valid、pic_data_out信号波形图

第四部分:水平移动变量(x_move)、竖直移动变量(y_move)、水平移动标志(x_flag)、竖直移动标志(y_flag)波形图绘制思路

在前文中我们说过,要想实现图片的移动就要不断移动图片显示区域,加之人眼的视觉暂留的原因就会感觉图片在移动。

以图片显示水平移动为例,要想实现显示图片的水平移动,就要改变图片有效信号pic_valid的水平有效区域,图片有效信号pic_valid是由ROM读使能信号rd_en打一拍得到,所以归根到底就是改变ROM读使能信号rd_en的水平有效区域。

这样的话我们需要声明一个变量x_move作为ROM读使能信号rd_en的水平方向约束条件,x_move初值为0,表示图片初始显示位置在显示器最左边;每完成一帧图像的显示,x_move信号自加1,表示移动速度为1个像素点;设图片每行像素点个数为H_PIC = 100,当pix_x信号在计数范围(x_move ≤ pix_x <x_move + H_PIC),约束条件pix_y信号不变时,ROM读使能信号rd_en信号有效,这样就实现了显示图片的水平向右移动。

同理,可声明竖直移动变量y_move,移动速度与水平移动变量x_move相同,实现显示图片竖直向右移动。将两者结合,可实现显示图片与水平方向45度夹角右下移动。当然,读者也可自定义移动速度,改变移动速度和移动方向。

介绍到这里,我们只是实现了显示图片的移动效果,如何实现显示图片的触框反弹呢?

我们就需要声明两个标志信号水平移动标志(x_flag)、竖直移动标志(y_flag)。水平移动标志信号x_flag,作用是控制水平方向上显示图片的左移右移,当x_flag信号为低电平时,每完成一帧图像的显示,x_move信号自加1,实现图片的向右移动;当图片的最右边与显示屏右边框重合时, x_flag信号赋值高电平,每完成一帧图像的显示,x_move信号自减1,实现图片的向左移动;当图片最左边与显示器最左边重合,x_flag信号变为低电平,每完成一帧图像的显示,x_move信号自加1,实现图片的向右移动。周而复始,实现了显示图片水平方向触框回弹的效果。

同理,可以使用竖直移动标志信号y_flag实现竖直方向上的显示图片触框回弹效果。两者结合,实现显示图片在显示器显示区域内触框反弹特效。各信号波形图如下。

ROMVGA011

图 39‑10 x_move、 y_move、x_flag、y_flag信号波形图(一)

ROMVGA012

图 39‑11 x_move、 y_move、x_flag、y_flag信号波形图(二)

ROMVGA013

图 39‑12 x_move、 y_move、x_flag、y_flag信号波形图(三)

ROMVGA014

图 39‑13 x_move、 y_move、x_flag、y_flag信号波形图(四)

ROMVGA015

图 39‑14 x_move、 y_move、x_flag、y_flag信号波形图(五)

各信号波形绘制思路讲解完毕,将所有信号整合后,就是本小节开始部分展示的模块波形图。

本设计思路只做参考,并非唯一方法,读者可利用所学知识,按照自己思路进行设计。

代码编写

模块波形图绘制完毕后,参照绘制波形图进行参考代码的编写。模块参考代码,具体见代码清单 39‑1。

 代码清单 39‑1 图像数据生成模块参考代码(vga_pic.v)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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 wire [15:0] pix_data_out //输出VGA显示图像数据

);

////
//\* Parameter and Internal Signal \//
////

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

parameter H_PIC = 10'd100 , //图片长度
W_PIC = 10'd100 , //图片宽度
PIC_SIZE= 14'd10000 ; //图片像素个数

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 ; //灰色

//wire define
wire rd_en ; //ROM读使能
wire [15:0] pic_data ; //自ROM读出的图片数据

//reg define
reg [13:0] rom_addr ; //读ROM地址
reg pic_valid ; //图片数据有效信号
reg [15:0] pix_data ; //背景色彩信息
reg [9:0] x_move ; //图片横向移动量
reg [9:0] y_move ; //图片纵向移动量
reg x_flag ; //图片左右移动标志
reg y_flag ; //图片上下移动标志

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

//x_flag:图片左右移动标志
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
x_flag <= 1'b0;
else if(x_move == 10'd0)
x_flag <= 1'b0;
else if((x_move == (H_VALID - H_PIC - 1'b1))
&& (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID - 1'b1)))
x_flag <= 1'b1;

//x_move:图片横向移动量
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
x_move <= 10'd0;
else if((x_flag == 1'b0) && (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID -1'b1)))
x_move <= x_move + 1'b1;
else if((x_flag == 1'b1) && (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID -1'b1)))
x_move <= x_move - 1'b1;

//y_flag:图片上下移动标志
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
y_flag <= 1'b0;
else if(y_move == 0)
y_flag <= 1'b0;
else if((y_move == (V_VALID - W_PIC - 1'b1))
&& (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID - 1'b1)))
y_flag <= 1'b1;

//y_move:图片纵向移动量
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
y_move <= 10'd0;
else if((y_flag == 1'b0) && (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID -1'b1)))
y_move <= y_move + 1'b1;
else if((y_flag == 1'b1) && (pix_x == (H_VALID - 1'b1))
&& (pix_y == (V_VALID -1'b1)))
y_move <= y_move - 1'b1;

//rd_en:ROM读使能
assign rd_en = (((pix_x >= (x_move))
&& (pix_x < (x_move + H_PIC)))
&&((pix_y >= (y_move))
&& ((pix_y < (y_move + W_PIC)))));

 //pic_valid:图片数据有效信号
 always@(posedge vga_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 pic_valid <= 1'b1;
 else
 pic_valid <= rd_en;

 //pix_data_out:输出VGA显示图像数据
 assign pix_data_out = (pic_valid == 1'b1) ? pic_data : 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;

 //rom_addr:读ROM地址
 always@(posedge vga_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 rom_addr <= 14'd0;
 else if(rom_addr == (PIC_SIZE - 1'b1))
 rom_addr <= 14'd0;
 else if(rd_en == 1'b1)
 rom_addr <= rom_addr + 1'b1;

 ////
 //\* Instantiation \//
 ////

 //-------------rom_pic_inst-------------
 rom_pic rom_pic_inst
 (
 .address (rom_addr ), //输入读ROM地址,14bit
 .clock (vga_clk ), //输入读时钟,vga_clk,频率25MHz,1bit
 .rden (rd_en ), //输入读使能,1bit

 .q (pic_data ) //输出读数据,16bit
 );

 endmodule

模块参考代码是参照绘制波形图进行编写的,在波形图绘制小节已经对模块各信号有了详细的说明,对各信号介绍不再过多叙述。

仿真代码编写

不再对模块进行单独仿真,直接对实验工程进行整体仿真,仿真参考代码,具体见代码清单 39‑2。

代码清单 39‑2 顶层模块仿真参考代码(tb_vga_rom_pic.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
module tb_vga_rom_pic_jump();

////
//\* 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_rom_pic_jump_inst -------------
 vga_rom_pic_jump vga_rom_pic_jump_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

顶层模块仿真参考代码内部实例化顶层模块,模拟产生50MHz时钟信号和复位信号,理解较为容易,不再讲解。

仿真波形分析

使用ModelSim软件对代码进行仿真,我们只经过改动的vga_pic模块的相关信号,仿真结果如下。

ROMVGA016

图 39‑15 图像数据生成模块整体仿真波形图

ROMVGA017

图 39‑16 图像数据生成模块局部仿真波形图(一)

ROMVGA018

图 39‑17 图像数据生成模块局部仿真波形图(二)

ROMVGA019

图 39‑18 图像数据生成模块局部仿真波形图(三)

ROMVGA020

图 39‑19 图像数据生成模块局部仿真波形图(四)

ROMVGA021

图 39‑20 图像数据生成模块局部仿真波形图(五)

ROMVGA022

图 39‑21 图像数据生成模块局部仿真波形图(六)

ROMVGA023

图 39‑22 图像数据生成模块局部仿真波形图(七)

ROMVGA024

图 39‑23 图像数据生成模块局部仿真波形图(八)

ROMVGA025

图 39‑24 图像数据生成模块局部仿真波形图(九)

ROMVGA026

图 39‑25 图像数据生成模块局部仿真波形图(十)

由仿真波形可以看出,各信号波形与绘制的参考波形图波形一致,模块通过仿真验证。

10.2.3.3. RTL视图

实验工程通过仿真验证后,使用Quartus软件对实验工程进行编译,编译完成后,我们查看一下RTL视图, RTL视图展示信息与顶层模块框图一致,各信号正确连接,具体见图 39‑26。

ROMVGA027

图 39‑26 RTL视图

10.3. 上板验证

10.3.1. 引脚约束

仿真验证通过后,准备上板验证,上板验证之前先要进行引脚约束。工程中各输入输出信号与开发板引脚对应关系如表格 39‑2所示。

表格 39‑2 引脚分配表

信号名

信号类型

对应引脚

备注

sys_clk

Input

E1

输入系统时钟

sys_rst_n

Input

M15

复位信号

hsync

Output

C2

行同步信号

vsync

Output

D1

场同步信号

rgb[15]

Output

A5

RGB色彩信息(红)

rgb[14]

Output

E6

RGB色彩信息(红)

rgb[13]

Output

E7

RGB色彩信息(红)

rgb[12]

Output

B8

RGB色彩信息(红)

rgb[11]

Output

A8

RGB色彩信息(红)

rgb[10]

Output

F8

RGB色彩信息(绿)

rgb[9]

Output

E8

RGB色彩信息(绿)

rgb[8]

Output

B7

RGB色彩信息(绿)

rgb[7]

Output

A7

RGB色彩信息(绿)

rgb[6]

Output

F7

RGB色彩信息(绿)

rgb[5]

Output

F6

RGB色彩信息(绿)

rgb[4]

Output

B6

RGB色彩信息(蓝)

rgb[3]

Output

A6

RGB色彩信息(蓝)

rgb[2]

Output

B5

RGB色彩信息(蓝)

rgb[1]

Output

A2

RGB色彩信息(蓝)

rgb[0]

Output

B4

RGB色彩信息(蓝)

下面进行管脚分配,管脚的分配方法在前面章节已有所讲解,在此就不再过多叙述,管脚的分配如下图 39‑27所示。

ROMVGA028

图 39‑27 管脚分配

10.3.1.1. 结果验证

如图 39‑28所示,开发板连接12V直流电源、USB-Blaster下载器JTAG端口以及VGA显示器。线路正确连接后,打开开关为板卡上电。

ROMVGA029

图 39‑28 程序下载连线图

如图 39‑29所示,使用“Programmer”为开发板下载程序。

ROMVGA030

图 39‑29 程序下载图

程序下载完成后,VGA显示器背景为十色彩条,其中野火标志出现触框反弹特效,和预期实验效果一致。

10.4. 章末总结

到这里,本章节讲解完毕,相信读者已经掌握了像素图像弹跳特效的实现方法。不过读者有一点需要注意,实验中我们可以通过设置每次左右或者上下移动的像素点个数的多少改变图片移动速度,数值越大移动也快,这个数值不固定,可自行设置,但不建议设置太大,数值设置太大图片移动会显的不太流畅。

10.5. 拓展训练

1、修改代码,改变每次左右或者上下移动的像素点个数,观察显示图像的移动速度和移动流畅度。

2、改变每次左右或者上下移动的像素点个数比值关系,观察显示图像的移动方向。