计算机显示器有许多现实标准,常见的有VGA、SVGA等,在这里我们用VGA接口来控制显示器,VGA是Video Graphics Adapter(Array)的缩写,即视频图形阵列。作为一种标准的显示接口得到广泛的应用。VGA接口常使用15针的DB15接口,该接口引脚功能如下表所示:
引脚
| 名称
| 注释
| 引脚
| 名称 | 注释 | 1 | RED
| 红基色75R,0.7VPP | 9
| KEY | 保留
| 2 | GREEN
| 绿基色75R,0.7VPP | 10
| SGND | 同步信号地
| 3 | BLUE
| 蓝基色75R,0.7VPP | 11
| ID0 | 显示器标识位0
| 4 | ID2
| 显示器标识位2
| 12
| ID1/SDA | 显示器标识位1
| 5 | GND
| 地 | 13
| HSYNC/CSYNC | 行同步或者复合同步
| 6 | RGND
| 红色地 | 14
| VSYNC | 场同步
| 7 | GGND
| 绿色地 | 15
| ID3/SCL | 显示器标识位3
| 8 | BGND
| 蓝色地 | | | |
VGA 扫描方式在VGA标准兴起的时候。常见的彩色显示器一般由CRT(阴极射线管)构成,色彩是由RGB(红、绿、蓝)三基色组成。显示是用逐行扫描的方式解决。阴极射线枪发出电子束打在涂有荧光粉的荧光屏上,产生RGB三基色,合成一个彩色像素,扫描从屏幕的左上方开始,从左到右,从上到下进行扫描,每扫完一行,电子束都回到屏幕的左边下一行的起始位置。在这期间,CRT对电子束进行消隐。每行结束时,用行同步信号进行行同步;扫描完所有行,用场同步信号进行场同步,并使扫描回到屏幕的左上方。同时进行场消隐,预备下一场的扫描。 随着显示技术的发展,出现了液晶显示器,液晶显示器的成像原理与CRT不同,液晶显示器是通过对液晶像素点单元施加电压与否,来实现液晶单元的透明程度,并添加三色滤光片、分别使R、G、B这3中光线透过滤光片,最后通过3个像素点合成一个彩色像素点,从而实现彩色显示。但是由于液晶显示技术后于CRT显示技术诞生,因此在液晶显示器诞生的时候,为了能够兼容传统的显示接口,因此液晶显示器通过内部电路实现了对VGA接口的完全兼容。因此,我们在使用显示器时,只要该显示器带有标准的VGA接口,我们就不用去关系其成像原理,直接使用标准的VGA时序即可驱动。 对于普通的显示器(无论是液晶还是CRT),共有5个信号:R、G、B三基色信号,行同步信号HS,场同步信号VS。对于时序驱动,VGA显示器要严格遵循“VGA工业标准”,即640*480*60Hz模式,否则可能会损害VGA显示器。 芯航线GM7123模块 GM7123芯片有3个10位的DAC分别用于RGB三个颜色通道的信号输出,芯航线GM7123模块选择GM7123芯片三个DAC通道的各高8位作为数据输入端口,低2位舍弃。因此默认最高支持RGB888格式,即24位色,这种图形质量已经完全达到PC的显示标准了。该模块对用户引出了VGA_HS、VGA_VS、CLOCK、BLK(BLANK)、R7~R0、G7~G0、B7~B0、3.3V、GND信号。对于用户来说,只需正确的连接这些信号并给出正确的VGA标准信号即可。 VGA 控制器设计
第一步,设计行扫描计数器行扫描计数器即每个像素时钟自加1,一旦加满到799(刚好800个时钟周期),计数器清零并重新技术,该部分代码可如下设计:
reg [9:0] hcount_r; //VGA行扫描计数器 //**********************VGA驱动部分********************** //行扫描计数器 always@(posedge Clk25M or negedge Rst_n) if(!Rst_n) //复位时,让行扫描计数器清零 hcount_r<=10'd0; else if(hcount_r==10'd799) //当一行数据扫完后,再次清零行扫描计数器 hcount_r<=10'd0; else //0~799之间,每个像素时钟时行扫描计数器自加1 hcount_r<=hcount_r+10'd1; |
第二步,设计场扫描计数器由于场扫描计数器是在每次一行扫描完成后加1的,即场扫描计数器的自加条件是行扫描计数器溢出。所以,场扫描计数器的自加条件为行扫描完成,即
“hcount_r==10'd799”,场扫描计数器代码如下所示:
reg [9:0] vcount_r; //VGA场扫描计数器 //场扫描 always@(posedge Clk25M or negedge Rst_n) if(!Rst_n) //复位时让场计数器清零 vcount_r<=10'd0; else if(hcount_r==10'd799) begin //每次一行扫描完成 if(vcount_r==10'd524) //每次一场扫描结束,清零计数器 vcount_r<=10'd0; else vcount_r<=vcount_r+10'd1;//场计数器在0~524,满足条件,自加1 end else //不满足行扫描结束条件器件,让场扫描计数器保持不变 vcount_r<=vcount_r;
|
第三步,产生行同步信号和场同步信号根据VGA工业标准时序,我们知道每一个完整的VGA帧都包含了数据段和消隐段,在消隐段期间,行同步信号和列同步信号有一段行同步头和场同步头,在同步期间,对应行同步信号或者场同步信号为低电平,因此我们可以根据行、场计数器的值来确定行、场同步信号的电平状态。对于行同步信号,其行同步头为一行扫描的前96个像素时钟周期,因此行同步信号可用如下的简单方式控制:
assign VGA_HS=(hcount_r>10’d95); | 对于场同步信号,其场同步头为一行扫描的前2个像素时钟周期,因此行同步信号可用如下的简单方式控制:
assign VGA_VS=(vcount_r>10’d1); |
第四步,输出数据 VGA控制器的设计目的是为了驱动VGA显示器显示需求的图像内容,因此需要设计数据输出部分,这里,数据来源可以为其它部分产生的图像信号,如摄像头数据、BMP图片数据。我们在驱动VGA时,只需要保证在扫描正确的像素点时,其它部分产生的图像信号能够与该像素点位置对应上,则不需要对图像数据再进行二次处理,但是,在行、场消隐期间,需要保证输出到VGA的RGB数据线上的数据全部为0,因此可以设置一个二选一多路器,只有在非消隐期间,VGA控制器才直接输出其他部分输入的图像数据,而消隐器件则强制输出全0。
我们可以首先产生一个图像数据有效标志信号,然后使用该标志信号控制VGA输出数据的内容,即切换二选一多路器的通道,从而实现消隐器件数据全0的功能。
图像数据有效标志信号产生代码如下所示:
//数据、同步信号输出 assign dat_act=((hcount_r>=10'd143)&&(hcount_r<10'd783)) &&((vcount_r>=10'd34)&&(vcount_r<10'd514)); | dat_act即为图像数据有效标志信号。
VGA_BLANK信号和dat_act信号功能一致,因此直接将dat_act信号赋值给VGA_BLANK即可。
assign VGA_BLK = dat_act; | 另外,也可以在消隐期间,设置RGB输出端口上数据为0来强制产生消隐效果。
消隐强制输出0二选一多路器代码如下所示:
assign VGA_RGB=(dat_act)?data_in:24'h000000; | 其中,VGA_RGB是输出到VGA接口上的数据,而data_in则是其他模块传递过来的正确的图像数据。
第五步,输出正确的行列扫描位置为了使其他模块能够根据当前扫描位置正确的输出图像数据,因此需要将VGA控制器的实时扫描位置输出,以供其他模块使用。
assign hcount=dat_act?(hcount_r-hdat_begin):10'd0; assign vcount=dat_act?(vcount_r-vdat_begin):10'd0; |
第六步,输出VGA输出芯片的DAC数据锁存时钟信号对于FPGA上实现的VGA控制器,在时钟信号的上升沿输出数据,而对于DAC芯片来说,需要在数据的中点采集数据,因此将VGA控制器的时钟取反后输出作为DAC的数据锁存信号,如下所示:
//将VGA控制器时钟信号取反输出,作为DAC数据锁存信号
assign VGA_CLK = ~Clk25M; |
|