三基色是指通过其他颜色的混合无法得到的“基本色”。由于人的肉眼有感知RGB(红绿蓝)三种不同颜色的锥体细胞,因此色彩空间通常可以由RGB三种基本色来表达。
& m+ B* E' H* ~! R, ?: T) s
自然界中的绝大部分彩色,都可以由三种基色按一定比例混合得到。
- J( k; e: A( d; q% X7 G
所以VGA接口中,表示颜色分量的只有红绿蓝三种基色。由于VGA接口的三基色为模拟信号值,FPGA无法输出,所以在FPGA的IO到VGA接口中间要有对应的数字量转模拟量的电路。
0 G, z$ L3 a% r' S' ^
SANXIN – B01中采用电阻网络来实现数字量转模拟量的功能。
; X( u0 j3 c4 r R5 D7 z$ d2 P
% R2 V2 |) H3 z: |( R, V
: q7 E& n; x$ i% l% r: \$ d
2 v% r6 E$ t# M# T
2 O. t1 j2 Y+ J
- `, y6 t: K% Y2 w5 I% t3 X" c
图片在数字设备中,都是由像素点构成。
4 _0 ]' L: \" b
像素是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子。可以将像素视为整个图像中不可分割的单位或者是元素。不可分割的意思是它不能够再切割成更小单位,它是以一个单一颜色的小格存在。每一个点阵图像包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小。
" Z. l- H4 M+ _2 `" d% a5 p1 q
VGA显示器上每一个像素点可以很多种颜色,由R、G、B三种颜色构成。如果每个像素点采用3位二进制数表示,即R用1bit表示,G用1bit表示,B用1bit表示,则此像素点一共可以显示8种颜色;如果每个像素点采用8位二进制数表示,即R用3bit表示,G用3bit表示,B用2bit表示,则此像素点一共可以显示256种颜色。在SANXIN – B01开发板中,采用RGB332的进行表示。
2 j* l- x1 i& e0 w: Q' c6 `
在VGA显示器中,像素点RGB的二进制数越多,能够表示的颜色就越多,此时,显示的图像就会越清晰。
. F0 J3 ~) ^. T1 g
在VGA显示器中,像素点的个数也是一个非常重要的一个指标。
Z& W/ q* n; `2 w+ y( s+ l
我们可以打开自己电脑的显示分辨率。
6 x6 P7 Z1 {! Z" d* l
; r3 j4 ]1 B$ Q& {& _) `& G
7 a+ d6 ~7 B+ d& A$ s
* ?' l1 y" Z9 E+ g7 Y
- n% D8 d. H( H
2 ^+ n2 P- r& P8 c
分频率有各种模式,但是基本都是固定好的。分辨率都是长乘宽,前面的数为长,后面的数为宽。长表示屏幕横向可以有多少个像素点;宽表示屏幕纵向可以用多少个像素点。一般来说屏幕都是扁平的,所以长一般都会比宽大。
# d: K* j3 o4 G7 \7 m+ r- ]
像素的多少不改变实际物理的尺寸大小,只是呈现的清晰度不同。可以对比500万像素的相机拍的图片和2000万像素的相机拍的图片,大小相同的情况下,清晰度是不同的。
# a# x* t( \2 n$ h" P) K
只要我们按照显示器能够支持的分辨率的长和宽,将对应的像素点传输给VGA接口就可以了。但是VGA协议中,要求进行传输像素点的同时,还需要去传输一部分的同步信号。
5 Y) x# x: K- y4 z! ^
显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,开始下一帧。隔行扫描是指电子束扫描时每隔一行扫一线,完成一屏后在返回来扫描剩下的线,隔行扫描的显示器闪烁的厉害,会让使用者的眼睛疲劳。在此我们选择逐行扫描的方式。
/ Z+ K. d4 K- n2 S% b
) S; O( n! m O- v k& u. P
4 O9 L: s8 P" x; O
) k9 P' }, ?8 Z$ O$ V y
4 I, R/ c7 t4 e; f9 u% m
2 |8 U9 h+ t. z1 K4 b
VGA的时序主要包括行时序与场时序两个部分。其中行时序主要包括:行同步(Hor Sync) 、行消隐(Hor Back Porch) 、行视频有效(Hor Active Video)和行前肩(Hor Front Porch)这四个参数,行时序的时序图如下图所示:
; ^7 \2 o5 ]. \# w8 {' j- q1 |
, L6 ?) N: A, _- K6 T! G6 _" _
9 t& E1 ?0 i$ m& _
: |# s# Y- o" n( k& Q( Z
" h8 c( \$ U7 ?7 @, i" H/ t" k- ]
场时序主要包括:场同步(Ver Sync) 、场消隐(Ver Back Porch) 、场视频有效(Ver Active Video)和场前肩(Ver Front Porch)这四个参数,场时序的时序图如下图所示:
; |4 p+ `) S7 [/ C1 v& B
% V. V: Z+ ?0 E4 P. q
6 }- w `! [8 u1 T' a) \" H+ ]
, s0 T( d( r: V- N# l- V! j+ C
需要注意的有三点:
1、行时序是以”像素”为单位的, 场时序是以”行”为单位的。
2、VGA 工业标准显示模式要求:行同步,场同步都为负极性,即同步脉冲要求是负脉冲。
3、VGA 行时序对行同步时间、 消隐时间、 行视频有效时间和行前肩时间有特定的规范, 场时序也是如此。常用VGA 分辨率时序参数如下表所示:
8 l1 M9 {* s& a6 J! i5 T% [! B
1 O" x, \# h! W% P) l
$ ]0 k6 J0 o+ G- _+ O$ r' v
7 c: S) \$ e$ {) Z- U! B& x
) |# ~. ^) T) M; u& h; o
本实验中选择640x480@60Hz。时钟的速率为25.175MHz,我们在设计时,时钟速率选择为25MHz 即可。
" l. y) q) f9 U: ~+ R
- 设计要求1 q- ^. G' W5 f, G) W
控制VGA显示器显示全屏红色或者其他颜色。
5 S( O. @/ P+ |; [
- 设计分析
, X/ D. V! Q3 D! Q% C
当我们选择640x480@60Hz的标准后,根据对应格式可以发现,此标准的一行为800个像素值,共有525行。也就是说并不是所有的像素值都可以显示出来,显示出来的只有中间的640列和480行,其他的像素值不显示(要求其他的像素值为黑色,即RGB全部给0)。
& Z8 b0 p' G/ f3 e" o
选择标准需要25MHz的时钟,我们可以选择使用锁相环来进行生成25MHz的时钟。
3 f# o3 y& R3 D+ s0 ^: P. x, f' h
扫描方式为逐行扫描,从左上角开始。定义一个列坐标计数器(cnt_hs),每个驱动时钟周期加1,当一行结束后,计数器也同时清零。一行为800个像素值,所以计数器将会在0到799无限循环。HSYNC信号在此计数器的前96的计数值拉低,其他时间拉高即可。
# h% x$ C, W8 O3 Y" p8 c
定义一个行坐标计数器(cnt_vs),扫描完一行后,进行加一,当一帧图片结束后,计数器清零。一行为800个像素值,所以等cnt_hs为799时,cnt_vs进行加一或者清零,由于一帧图片共有525行,所以计数器在0到524之间无限循环。VSYNC信号在此计数器的前两个计数器拉低,其他时间拉高即可。
* M3 W3 z, a" ^1 R
根据cnt_hs和cnt_vs,按照对应的标准,就可以得出显示的640列和480行的具体位置。
列显示的范围为:hs_a+hs_b+hs_c>cnt_hs>hs_a+hs_b-1.
行显示的范围为:vs_f+vs_g+vs_h>cnt_vs>vs_f+vs_g-1.
9 X; j9 t) _6 ]6 V2 b
同时在两个有效显示区范围内,就可以显示出来。
4 `0 Z5 ?6 m+ Z+ B6 y4 G0 h
- 设计架构和信号说明7 ~* Q$ n& \2 A7 w
此设计命名为vga_drive。
* Z2 S1 @& h5 s" _$ q
8 v7 z/ q, _( }3 Z. s+ G0 e% O
9 u+ p- b- ^! F
- i8 A0 J' a1 x) K3 |: c5 K
pll_vga为锁相环,利用外部输入的50MHz的时钟,产生VGA协议所需要的25MHz的时钟。
" G5 g, {: X8 f" u' z! X: o) `
vga_ctrl为VGA协议的驱动模块。
$ y) e8 @8 d5 Q- C6 M* Q4 ]
0 p) t/ Q' k) b' }3 H2 Q
7 [" {6 _$ l- v/ t J0 l# ]: t5 O
& z$ O. h5 H& b! k3 q
6 m% Z5 }% g' h
- vga_ctrl设计实现
+ d/ O- m# q- ~1 _: r. z
9 p1 y- i1 p9 R9 X) U. |# }2 v0 s
按照设计分析中的设计方法,进行设计即可。
6 \; |4 y' W' ^( n6 a
hs_en为列有效显示的表示信号;vs_en为行有效显示的表示信号。
, s7 B2 F0 F% }2 A% \
设计代码为:
4 k) ^6 r8 U. U6 M
& g# G2 ]8 W2 X, r+ {$ t) [$ b( a
$ t7 P2 d, ^9 D. p, M' z1 Q
在设计中,给出的全屏颜色为红色。
# {4 H: o) l3 G: x2 a; V4 H+ s
- vga_drive设计实现
' _3 `: Q: q k: r& N7 n
2 O, ^% b' Y3 v) F0 l1 y2 V. R4 e
调用锁相环,产生25MHz的时钟。
6 v3 S' t: |. o/ x- ]) Q
利用锁相环的输出锁定信号当作后续模块的复位信号使用。
) W1 Z; B- q3 Z8 r+ h- C+ W
设计代码为:
7 U0 q# E4 `& v& E$ g/ k) @+ }
2 J& q' |4 h0 ]8 L+ l# O
: X" ]/ o4 P! T. ~7 G1 r8 i, r" D7 f3 k! u5 h1 H$ ~! }; F# y
仿真时只需要给出clk和rst_n的信号即可,在此不做介绍。设计者可以通过modelsim观看是否每一行输出640个红色值,以及是否每一帧输出480行。仿真时间较长,大约等待20ms,就可以仿真完一帧图像。
' U+ Q, C J; B
- 板级测试1 e$ o+ t; F5 |% {2 k- J/ g
; f0 c, K- `4 m4 \2 A1 R
利用VGA线,将开发板的VGA接口和显示屏幕的VGA接口相连接,打开显示器。
. h6 m9 |' p# n
分配管脚,生成配置文件后,进行下板。
$ X1 J. V, F8 t
红色全屏如下:
- H% K" O; e# h! q# C
& l. C5 B' V8 v" s8 L: I2 I' L6 q
, L7 {2 R: U9 `/ k3 t7 I, t
! d- R3 a9 D/ _
9 ?+ A! `" [ |8 x3 J
6 v; [5 R8 y( n( T- P
更改颜色为绿色,vga_rgb <= 8’b000_111_00,生成配置文件后,下板。
/ K9 A( \/ v l. t
绿色全屏为:
7 V. K" | s, V
, e& ]4 z) J2 B+ l1 e! j
& k9 U% O! n- y6 {- N
, Z( |3 s, H; }. R3 e" A( B) g
& r: d s4 [) U& b
2 l* n9 s& D1 J% P
根据RGB332的排列,可以自由更改。不同的基色也可以进行混搭,进行验证。