首页 | 期刊简介 | 编辑部 | 广告部 | 发行部 | 在线投稿 | 联系我们 | 产品信息索取
2024年5月3日星期五
2011年第01期
 
2010年第12期
 
2010年第11期
2010年第11期
 
2010年第10期
2010年第10期
 
2010年第09期
2010年第09期
 
2010年第09期
2010年第08期
 
2010年第07期
2010年第07期
 
2010年第06期
2010年第06期
 
2010年第05期
2010年第05期
 
2010年第04期
2010年第04期
 
2010年第03期
2010年第03期
 
2010年第02期
2010年第02期
 
2010年第01期
2010年第01期
 
2009年第12期
2009年第12期
 
2009年第11期
2009年第11期
 
2009年第10期
2009年第10期
 
2009年第9期
2009年第9期
 
2009年第8期
2009年第8期
 
2009年第7期
2009年第7期
 
2009年第6期
2009年第6期
 
2009年第5期
2009年第5期
 
2009年第4期
2009年第4期
 
2009年第3期
2009年第3期
 
2009年第2期
2009年第2期
 
2009年第1期
2009年第1期
 
2008年第12期
2008年第12期
 
2008年第11期
2008年第11期
 
2008年第10期
2008年第10期
 
2008年第9期
2008年第9期
 
2008年第8期
2008年第8期
 
2008年第7期
2008年第7期
 
2008年第6期
2008年第6期
 
2008年第5期
2008年第5期
 
2008年第4期
2008年第4期
 
2008年第3期
2008年第3期
 
2008年第2期
2008年第2期
 
2008年第1期
2008年第1期
基于FPGA的VGA显示系统

A VGA Display System Based On FPGA

金蜂通信有限责任公司 段磊



引言

LCD和CRT显示器作为一种通用型显示设备,如今已广泛应用于我们的工作和生活中。与嵌入式系统中常用的显示器件相比,它具有显示面积大、色彩丰富、承载信息量大、接口简单等优点,如果将其应用到嵌入式系统中,可以显著提升产品的视觉效果。

Altera公司生产的Cyclone II系列FPGA具有很高的性价比,作为该系列中最便宜的一款FPGA,EP2C5T144C8提供了4608个逻辑单元、26个M4K RAM块、13个18*18嵌入乘法器、2个PLL和89个用户I/O引脚。这个VGA显示系统可以在NIOS内核的控制下,在屏幕上显示出任意的文字或图形。


VGA接口概述

VGA接口为显示器提供两类信号,一类是数据信号,一类是控制信号。数据信号包括红(Red)、绿(Green)、蓝(Blue)信号,简称RGB信号,控制信号包括水平同步信号和垂直同步信号。输出不同分辨率时,水平同步信号和垂直同步信号的频率也不同。下表是在部分分辨率条件下使用的相应频率。

当分辨率为640*480时,显示器每行占用840(31.5MHz/37.5kHz)个数据位,其中640个数据位用于显示像素,另外200(840-640)个数据位用于输出水平同步信号和水平消隐信号。垂直方向有500(37.5kHz/75Hz)行,其中480行用于显示像素,其余20(500-480)行用于输出垂直同步信号和垂直消隐信号。水平同步信号和垂直同步信号都采用低电平同步方式。水平同步信号低电平约保持2μs,相当于63个数据位长度。垂直同步信号低电平约保持80μs,相当于3行数据位长度。


系统实现

本设计参考了PC机中显卡的工作方式,即在NIOS和VGA显示系统之间增设一个双口RAM(DPRAM)作为显示存储器(VRAM)。NIOS每次把要显示的内容写入VRAM中,VGA显示系统根据显示时序依次读取VRAM中的数据发送给显示器。因为每个像素在VRAM中都有对应的地址,所以NIOS只要修改VRAM的内容就可以实现控制显示输出的目的。

THCII-1实验板的VGA输出颜色数为256(2 8 )色,正好可以用VRAM的一个字节表示一个像素的颜色。全屏幕共有307200(640*480)个像素,需要300k字节的VRAM。这么大的VRAM在实验板上很难用FPGA(EP2C5)单独来实现,但是,如果用屏幕上10*10个像素所组成的矩形面积来 表示一个逻辑像素,人感受到的分辨率则变为64*48,此时VRAM仅占3072个字节,这在EP2C5内部实现起来就容易多了。当然,还应再增加一个永远为0x00的字节,当VGA电路输出同步信号和消隐信号时,输出地址都指向这个特殊字节,使RGB输出信号为0电平。按照以上的设计要求,VRAM地址范围从0x000至0xC00,共占用12条地址线。

VHDL程序设计

1)实体部分——实体部分定义了VGA显示系统的所有接口

entity VGA is
Port
(
Fosc : in std_logic; -- 36MHz时钟信号。
Data : in std_logic_vector(7 downto 0);
--VRAM数据线
Address : in std_logic_vector(11 downto 0);
--VRAM写地址
CE : in std_logic; --片选信号,
高电平有效
WREn : in std_logic; --写允许信号,
高电平有效
HS : out std_logic; --水平同步信号
VS : out std_logic; --垂直同步信号
RGB : out std_logic_vector(7 downto 0)
--色彩信号
);
end entity;

2)常量和信号

constant HSMax : integer := 840;
--每行840个数据位
constant HSNegative : integer := 63;
--水平同步信号低电平占63个数据位
constant VSMax : integer := 500;
--每帧有500行
constant VSNegative : integer := 3;
--垂直同步信号低电平占3行数据位
constant XMax : integer := 640;
--水平640个像素
constant YMax : integer := 480;
--垂直480个像素
constant Left : integer:= 184;
--每行首像素位置
constant Right : integer := Left + XMax -1;
--每行末像素位置
constant Top : integer := 16;--首行位置
constant Bottom : integer := Top + (YMax - 1);
--末行位置
constant PixelWide : integer := XMax / 64;
--逻辑像素宽度(10pixel)
constant PixelHigh : integer := YMax / 48;
--逻辑像素高度(10pixel)
signal Fvga : std_logic;
--31.5MHz时钟信号
signal H : std_logic;
--垂直同步计数允许信号
signal XAddress : std_logic_vector(11 downto 0);
--VRAM水平地址
signal YAddress : std_logic_vector(5 downto 0);
--VRAM垂直地址
signal VRA : std_logic_vector(11 downto 0);
--VRAM输出地址

3)DPRAM模块作为VRAM,为每个像素提供映射地址

Modular : DPRAM
port map
(
data => Data,
--VRAM写入数据,由NIOS写入
rdaddress => VRA,
--VRAM输出地址,由VGA显示系统提供
rdclock => Fvga,
--VRAM输出时钟,31.5MHz
wraddress => Address,
--VRAM写入地址
wrclock => Fosc,
--VRAM写入时钟
wren => WREn and CE,
--VRAM写允许信号,
WREn和CE为1时有效
q => RGB
--RGB输出信号
);

4)水平同步信号的产生和VRAM水平地址寻址

process(Fvga)
variable HSValue : integer range 0 to HSMax
- 1 := 0;
begin
if rising_edge(Fvga) then
--在Fvga(31.5MHz)的上升沿循环计数(0-839)
if HSValue = HSMax - 1 then
HSValue := 0;
else
HSValue := HSValue + 1;
end if;
--在计数值小于63时(0至62),水平同步信号输出低电平,否则输出高电平
if HSValue < HSNegative then
HS <= '0';
else
HS <= '1';
end if;
- -在计数值等于839时,垂直同步计数允许信号为1,否则为0
if HSValue = HSMax - 1 then
H <='1';
else
H <='0';
end if;
--每行从首像素到末像素,每10个像素对应一个VRAM水平地址,共64个水平地址
if HSValue >= Left + 0 * PixelWide and HSValue < Left + 1 * PixelWide then XAddress <= "000000000000";
elsif HSValue >= Left + 1 * PixelWide and HSValue < Left + 2 * PixelWide then XAddress <= "000000000001";
elsif HSValue >= Left + 2 * PixelWide and HSValue < Left + 3 * PixelWide then XAddress <= "000000000010";
……………………..--中间省略
elsif HSValue >= Left + 63 * PixelWide and HSValue < Left + 64 * PixelWide then XAddress <= "000000111111";
--超出首像素和末像素时,输出默认地址0x110000000000的0x00
else XAddress <= "110000000000";
end if;
end if;
end process;

5)垂直同步信号的产生和VRAM垂直地址寻址

process(Fvga, H)
variable VSValue: integer range 0 to VSMax - 1 := 0;
begin
if rising_edge(Fvga) then
--在Fvga(31.5MHz)的上升沿,当垂直同步计数允许信号为1时,对行数循环计数(0~479)
if H = '1' then
if VSValue = VSMax - 1 then
VSValue := 0;
else
VSValue := VSValue + 1;
end if;
else
VSValue := VSValue;
end if;
--当行计数小于3时,垂直同步信号输出低电平,否则输出高电平
if VSValue < VSNegative then
VS <= '0';
else
VS <= '1';
end if;
--从首行到末行,每10个行对应一个VRAM垂直地址,共48个水平地址
if VSValue >= Top + 0 * PixelHigh and VSValue < Top + 1 * PixelHigh then YAddress <= "000000";
elsif VSValue >= Top + 1 * PixelHigh and VSValue < Top + 2 * PixelHigh then YAddress <= "000001";
elsif VSValue >= Top + 2 * PixelHigh and VSValue < Top + 3 * PixelHigh then YAddress <= "000010";
……………………..--中间省略
elsif VSValue >= Top + 47 * PixelHigh and VSValue < Top + 48 * PixelHigh then YAddress <= "101111";
--超出首行和末行时,输出默认地址0x110000000000的垂直地址部分0x110000
else YAddress <= "110000";
end if;
end if;
end process;

6)VRAM输出地址的合成

VRA <= YAddress & "000000" or XAddress;

NIOS程序设计

1)字模表。每个字符均由5*7个逻辑像素组成,占用5个字节。字符"1"的字模如下图所示。任意字符的ASCII码经过差值计算后就能得到该字符在字模表中的位置。

图(略)

unsigned char CHTAB[][5]=
{
{0x3E, 0x51, 0x49, 0x45, 0x3E}, //"0"=00h
{0x00, 0x42, 0x7F, 0x40, 0x00}, //"1"=01h
{0x42, 0x61, 0x51, 0x49, 0x46}, //"2"=02h
{0x21, 0x41, 0x45, 0x4B, 0x31}, //"3"=03h
{0x18, 0x14, 0x12, 0x7F, 0x10}, //"4"=04h
--中间省略
{0x00, 0x41, 0x36, 0x08, 0x00}, //"}"=5Dh
{0x02, 0x01, 0x02, 0x04, 0x02}, //"~"=5Fh
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F} //" "=60h
};

2)显示像素函数,负责向VRAM中指定行和列上的字节写入颜色值。VGA_0_BASE为VRAM的首地址。

void Pixel(unsigned char row, unsigned char column, unsigned char color)
{
unsigned short offset;
offset = row * 64 + column;
IOWR(VGA_0_BASE, offset, color);
}

3)字符显示函数

void Character(unsigned char row, unsigned char column, unsigned char *CH, unsigned char frontcolor, unsigned char backcolor)
{
unsigned char i, h, color;
for(h = 0; h < 5; h ++)//遍历字模占用的5个字节
{
for(i = 0; i < 8; i ++)//遍历字模中每个字节的8个bit
{
if(1 == ((*(CH + h) >> i) & 1))
{
color = frontcolor;//如果某bit为1,则显示前景颜色
}
else
{
color = backcolor;//如果某bit为0,则显示背景颜色值
}
Pixel(row + i, column + h, color);//显示像素
}
}
}

实验结果

经过实验证明,此VGA显示系统完全符合设计要求。如果在Flash中加入汉字库,还可以显示汉字。但是,由于受实验板和器件的限制,虽然VGA显示系统输出分辨率为640*480,但实际显示分辨率仅为64*48,因此仍需要对电路部分进行改进和完善。

《世界电子元器件》2007.9
         
版权所有《世界电子元器件》杂志社
地址:北京市海淀区上地东路35号颐泉汇 邮编:100085
电话:010-62985649
E-mail:dongmei@eccn.com