文章目录
一、相关概念
1.VGA协议
VGA(Video Graphics Array)是IBM在1987年随PS/2机⼀起推出的⼀种视频,具有分辨率⾼、显⽰速率快、颜⾊丰富等优点,在彩 ⾊显⽰器领域得到了⼴泛的应⽤。不⽀持热插拔,不⽀持⾳频传输。对于⼀些嵌⼊式VGA显⽰系统,可以在不使⽤VGA显⽰卡和计算机的 情况下,实现VGA图像的显⽰和控制。VGA显⽰器具有成本低、结构简单、应⽤灵活的优点。
2.VGA端口结构
VGA端口是视频输出端口,端口一共包含15个管脚,如下图
15个管脚(包括3个基本红,绿,蓝三条基本色彩线和水平与垂直两条控制线)
3.⾊彩原理
设计RGB信号时,既可以R信号、G信号和B信号独⽴的赋值,最后连到端⼝上,也可以直接⽤RGB当做⼀个整体信号,RGB信号在使⽤时的位宽有三种常见格式,以你的VGA解码芯⽚的配置有关。(三基色)
RGB_8,R:G:B = 3:3:2,即RGB332
RGB_16,R:G:B = 5:6:5,即RGB565
RGB_24,R:G:B = 8:8:8,即RGB888
4.扫描原理
扫描方式
VGA显⽰器扫描⽅式分为逐⾏扫描和隔⾏扫描:逐⾏扫描是扫描从屏幕左上⾓⼀点开始,从左像右逐点扫描,每扫描完⼀⾏,电⼦束回 到屏幕的左边下⼀⾏的起始位置,在这期间,CRT对电⼦束进⾏消隐,每⾏结束时,⽤⾏同步信号进⾏同步;当扫描完所有的⾏,形成⼀ 帧,⽤场同步信号进⾏场同步,并使扫描回到屏幕左上⽅,同时进⾏场消隐,开始下⼀帧。隔⾏扫描是指电⼦束扫描时每隔⼀⾏扫⼀线,完成 ⼀屏后在返回来扫描剩下的线,隔⾏扫描的显⽰器闪烁的厉害,会让使⽤者的眼睛疲劳。因此我们⼀般都采⽤逐⾏扫描的⽅式。
逐行扫描
一行紧跟一行的扫描方式称为逐行扫描
电子束在在靶面上或者屏幕上的扫描轨迹称为扫描光栅
隔行扫描
隔行扫描所应满足的条件:
1.下一帧扫描起始点应上一帧起始点相同,以便保证各帧扫描光栅重叠。一帧的总行数Z必须为整数
⒉.相邻两场扫描光栅必须均匀镶嵌,以获得最高清晰度
一帧的总行数必须为奇数,或任何一场必须包含一个半行
5.⾏场信号
显示器的扫描方式:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,
电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;
当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。
行扫描为例子,在一行中由于需要行消隐,所以要求一定的时钟周期用于行消隐,当然也有行同步信号。
所以,一个行/场时序应该包括:a行同步脉冲,b行显示后沿,c行显示时序段,d行显示后沿,e行总时序
640:在一个完整的行扫描周期中,有效显示图像每一行有640个像素点
480:一帧完整的图像有480行
640*480 ≈ 300000个像素点,每个时钟进行一次像素点的扫描
60:帧率,每秒刷新图像60次,每秒显示60帧
行扫描周期 × 场扫描周期 × 帧率 = 每秒扫描像素点个数 = 时钟频率
ex. 840 × 500 × 75 = 31.5MHz
二、显示姓名学号(汉字显示)
1.生成字模
0000000000000000000000000000000000000000000000000000000000000000;
0000010000000000000000002000000000000102010000000000000030000000;
0000010303800000000000001C0000000000038307C00000000010001C000000;
00600383FF8000000100101C1800000000300703FF000000010199FC18000000;
00180603830000000183DFF818000000000E0E038300000001FF9E1819800000;
00071C030300000001F9981818E000000003B803030000000181981818780000;
0001F0030300000001819818183C00000000F0030300000001819810181C0000;
0000F8030300000001831BF8180C000000019C0303000000019F1FF818040000;
00030E060300000001FF980018000000000607860382000001C0080018000000;
000C038603FF000000800800180100000018018C01FF000000000020181F8000;
0030818C000000000000007019FFC00000C0C0980000000000807FF03FF80000;
0180E0300000000000FFFFF7FE0000000000602000C0000000FFE063D8000000;
0000604003F0000000C060600C080000000060003FE0000000C060600C0C0000;
0000639FFFC0000000C07F600C0C00000003FFC7E1C0000000DFFF600C1E0000;
07FFFE0001C0000000CFE0E00C1C000003FC60000180000000C060600C380000;
0180600F0380000000C060600C700000000060070300000000C060E00C600000;
001064038300000000CFFFF006E00000001866018700000000FFFF0007C00000;
001C6300C600000000F0600007800000001C63806E0000000040600007000000;
003861806C000000004060000F000000003061C03C000000000060000F000000;
006060E018000000000060383B80000000E060603C00000000007FFC71804000;
00C060607C00000001FFFFF0E1C0400001806060E600000003FFE001C0C06000;
03006000C300000001E0600380E0600003006001838000000000600600606000;
0620600381C000000000601C003060000C18600700C000000000603000386000;
080EE00E0060000000006060001C60000007C01C0078000000006000000E6000;
0003C030003C00000000E000000760000001C060001FF0000000E0000003F000;
0000C1C0001FF0000000E0000001F00000000300000C0000000060000000F000;
0000060000000000000060000000300000000800000000000000000000001000;
0000000000000000000000000000000000000000000000000000000000000000;
0000000000000000000000000000000000000000000000000000000000000000;
0000000000000000000000000000000000000000000000000000000000000000;
0000000000000000000000000000000000000000000000000000000000000000;
0000000000000000000000000000000000000000000000000000000000000000;
2.代码
module data_gen (
input wire clk ,
input wire rst_n ,
input wire [10:00] h_addr , //数据有效显示区域行地址
input wire [10:00] v_addr , //数据有效显示区域场地址
output reg [23:00]data_dis
);
// 定义(char_x, char_y)相对与(h_addr, v_addr)的开始坐标
parameter CHAR_B_H = 10'd192, //字符开始X轴坐标
CHAR_B_V = 10'd208; //字符开始Y轴坐标
parameter CHAR_W = 10'd112, //字符宽度
CHAR_H = 10'd32; //字符高度
parameter BLACK = 16'h0000, //黑色
GOLDEN = 16'hFEC0; //金色
wire [ 9: 0] char_x;
wire [ 9: 0] char_y;
assign char_x = (((h_addr >= CHAR_B_H) && (h_addr < (CHAR_B_H + CHAR_W)))
&& ((v_addr >= CHAR_B_V) && (v_addr < (CHAR_B_V + CHAR_H))))
? (h_addr - CHAR_B_H) : 10'h3ff;
assign char_y = (((h_addr >= CHAR_B_H) && (h_addr < (CHAR_B_H + CHAR_W)))
&& ((v_addr >= CHAR_B_V) && (v_addr < (CHAR_B_V + CHAR_H))))
? (v_addr - CHAR_B_V) : 10'h3ff;
// 引入字模数据
reg [255:0] char [31:0]; // 256 * 31
always @(posedge clk or negedge rst_n) begin
char[ 0]<=256'h0000000000000000000000000000000000000000000000000000000000000000;
char[ 1]<=256'h0000010000000000000000002000000000