VGA调试心得
以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题。通过这种方式也调试成功过几个显示屏,然后就以为自己对视频信号的调试已经有丰富的经验了,直到这次需要自己用FPGA写一个VGA的驱动程序,才发现原来自己还是半桶水。
这次谈一下将RGB888的视频信号转换为VGA信号时的调试心得,使用ADV7123将数字信号转换为VGA信号。
首先谈一下VGA,在这个网站上可以能看到各种VGA信号的标准:http://tinyvga.com/vga-timing
以1600*1200分辨率为例(这次我就是要产生一个这样的视频)
假如1秒显示60场,一场是1200行,一行有1600个像素点,那么时钟频率就是60*1200*1600=115.2MHz,但是实际上不能这样满打满算。如果从现在的思维来考虑,因为行和场同步信号需要一定的建立时间,因此需要的时钟频率会更高一些,但是只要高一点点,给行场同步信号一定的建立时间就可以了,但是实际频率162MHz与计算得到的115.2MHz差别未免也太大了吧。因为这是一个历史问题,以前的显示器是用电子枪扫描的,电子枪扫完一行后需要回到行首,这段时间叫行消隐时间,电子枪扫完一场(到达屏幕的右下角)后需要回到左上角,这段时间叫场消隐时间。由于行消隐和场消隐的存在,以至于实际扫描一帧的时间要比算出来的满打满算的时间要多。
消隐时间在以前是为了让电子枪归位而设定的,今天虽然行场同步的建立时间可以很短,但是毕竟是一代标准,不能轻易改变,因此消隐信号仍然保留了。
在网上很多地方可以找到VGA的时序说明,我这边粗略说一下。
一个行同步周期内包含4个段:行消隐前肩、行同步时间、行消隐后肩、行有效时间,如上图所示,1600*1200的标准中,行有效时间包含了1600个时钟,对应了1600个有效像素点,行消隐前肩包含64个时钟,行同步时间包含192个时钟,行消隐后肩包含304个时钟,所以一行加起来一共2160个时钟。
同样的,一个场同步周期内包含4个段:场消隐前肩、场同步时间、场消隐后肩、场有效时间,如上图所示,1600*1200的标准中,场有效时间包含了1200个行周期,对应显示器能显示出来的1200行,场消隐前肩包含1个行周期,场同步时间包含3个行周期,场消隐后肩包含46个行周期,所以一场加起来一共有1250个行周期。
接下来是重点了,行和场都包含有4个时间段,这4个时间段究竟是怎么排布的,网上我找到两种说法:
我使用这两种时序产生VGA信号,然后我用ADV7604来采,结果显示老不正常,我一直以为是BLANK信号(ADV7123有个BLANK信号,其实就是消隐信号)的原因,改来改去总不对,但是它采标准的1600*1200的图像是正常的,因此我干脆直接自己采一下标准的1600*1200的VGA信号。
我使用逻辑分析仪采行场同步和红色通道的(也可以是其他通道)信号,行场同步可以直接接逻辑分析仪,而彩色信号是一个模拟信号,最大电压是0.714V,逻辑分析仪采不到。当红色通道为0.714V时表示的是最红的那个颜色,因此我使用了一个放大器,将0.714V放大到5V,然后再接入逻辑分析仪。接着只要采一个纯红的视频就OK了,但问题是纯红的视频哪里来,我找到一个很妙的办法,我外接了一个HDMI转VGA的接头,这样相当于外扩了一个VGA的显示器,然后新建1个PPT,把背景改为纯红,然后PPT设定为演讲者模式(具体操作我忘了,我是早就设好的,这个网上一搜就能搜到),按win+R键将投影选择扩展,然后放映PPT。这个时候神奇的事情来了,第二显示器显示的是纯红的,没有半点杂质,而我的主显示器的可以将PPT最小化,这样就能在主显示器中运行逻辑分析仪软件了。
运行之后,采到的波形如下图所示:
注意到1个问题,场同步的同步时间段中包含有3个完整的行同步,同步时间段之前有1个没有数据的行同步,同步时间段之后包含46个没有数据的行同步,那这不就水落石出了吗,4个时间段的排序如下图,前肩后面是同步时间,接着是后肩,然后是有效数据,所以之前找到的那两种说法似乎不太对。
同样的,行同步信号中的4个时间段也是这样排的。
上图中abcd4个段分别表示行消隐前肩、行同步时间、行消隐后肩和行有效时间。
还有一个比较重要的点,之前没提到,就是ADV7123的BLANK信号,这个信号用于关断输出,当BLANK信号为低时,关断输出,当BLANK信号为高时才能有输出,当然如果此时RGB信号本来就为0那肯定还是没有输出的,因此如果把RGB信号控制好,是完全不需要BLANK信号的。
有了这个,那程序就好写了,直接附上程序:
1 module vga_out (
2 input sys_clk,
3 input sys_rst_n,
4
5 output vga_clk,
6 output reg vga_hs,
7 output reg vga_vs,
8 output reg vga_blk,
9
10 output reg [7:0] vga_r,
11 output reg [7:0] vga_g,
12 output reg [7:0] vga_b
13 );
14
15 wire locked;
16 wire rst_n;
17
18 reg [11:0] hcnt;
19 reg [11:0] vcnt;
20
21 assign rst_n = sys_rst_n & locked;
22
23 pll_clk u_pll_clk (
24 .areset (~sys_rst_n),
25 .inclk0 (sys_clk),
26 .c0 (vga_clk),
27 .locked (locked)
28 );
29
30 //162M标准,1600*1200*60 75KHz
31 parameter H_DISP = 12'd1600; // 有效行数
32 parameter H_FRONT = 12'd64; // 行消隐前肩
33 parameter H_SYNC = 12'd192; // 行同步
34 parameter H_BACK = 12'd304; // 行消隐后肩
35 parameter H_TOTAL = 12'd2160; // 行总数
36
37 parameter V_DISP = 12'd1200; // 有效列数
38 parameter V_FRONT = 12'd1; // 列消隐前肩
39 parameter V_SYNC = 12'd3; // 列同步
40 parameter V_BACK = 12'd46; // 列消隐后肩
41 parameter V_TOTAL = 12'd1250; // 列总数
42
43
44 //行同步信号发生器
45 always @ (posedge vga_clk or negedge rst_n)
46 begin
47 if (!rst_n) begin
48 hcnt <= 0;
49 vga_hs <= 1;
50 end
51
52 else begin
53 if (hcnt < H_TOTAL-1)
54 hcnt <= hcnt+1'b1;
55 else
56 hcnt <= 0;
57
58 if((hcnt >= H_FRONT) && (hcnt < H_FRONT+H_SYNC))
59 vga_hs <= 0;
60 else
61 vga_hs <= 1;
62 end
63 end
64
65 // 场同步信号发生器
66 always @ (negedge vga_hs or negedge rst_n)
67 begin
68 if (!rst_n) begin
69 vcnt <= 0;
70 vga_vs <= 1;
71 end
72
73 else begin
74 if (vcnt < V_TOTAL-1)
75 vcnt <= vcnt+1'b1;
76 else
77 vcnt <= 0;
78
79 if((vcnt >= V_FRONT) && (vcnt < V_FRONT+V_SYNC))
80 vga_vs <= 0;
81 else
82 vga_vs <= 1;
83 end
84 end
85
86 //消影信号
87 always @(posedge vga_clk or negedge rst_n) begin
88 if (!rst_n)
89 vga_blk <= 1'b0;
90
91 if (vga_clk) begin
92 if (vcnt < V_FRONT + V_SYNC + V_BACK)
93 vga_blk <= 1'b0;
94 else if (hcnt < H_FRONT + H_SYNC + H_BACK)
95 vga_blk <= 1'b0;
96 else
97 vga_blk <= 1'b1;
98 end
99 end
100
101 /*
102 //横条纹
103 always @(posedge vga_clk) begin
104 if (vcnt < (V_DISP >> 3) * 1 + V_FRONT + V_SYNC + V_BACK) begin
105 vga_r <= 8'b1111_1111;
106 vga_g <= 8'b0000_0000;
107 vga_b <= 8'b1000_0000;
108 end
109
110 else if (vcnt < (V_DISP >> 3) * 2 + V_FRONT + V_SYNC + V_BACK) begin
111 vga_r <= 8'b0000_0000;
112 vga_g <= 8'b0000_0000;
113 vga_b <= 8'b1111_1111;
114 end
115
116 else if (vcnt < (V_DISP >> 3) * 3 + V_FRONT + V_SYNC + V_BACK) begin
117 vga_r <= 8'b0000_0000;
118 vga_g <= 8'b1111_1111;
119 vga_b <= 8'b0000_0000;
120 end
121
122 else if (vcnt < (V_DISP >> 3) * 4 + V_FRONT + V_SYNC + V_BACK) begin
123 vga_r <= 8'b0000_0000;
124 vga_g <= 8'b1111_1111;
125 vga_b <= 8'b1111_1111;
126 end
127
128 else if (vcnt < (V_DISP >> 3) * 5 + V_FRONT + V_SYNC + V_BACK) begin
129 vga_r <= 8'b1111_1111;
130 vga_g <= 8'b0000_0000;
131 vga_b <= 8'b0000_0000;
132 end
133
134 else if (vcnt < (V_DISP >> 3) * 6 + V_FRONT + V_SYNC + V_BACK) begin
135 vga_r <= 8'b1111_1111;
136 vga_g <= 8'b0000_0000;
137 vga_b <= 8'b1111_1111;
138 end
139
140 else if (vcnt < (V_DISP >> 3) * 7 + V_FRONT + V_SYNC + V_BACK) begin
141 vga_r <= 8'b1111_1111;
142 vga_g <= 8'b1111_1111;
143 vga_b <= 8'b0000_0000;
144 end
145
146 else if (vcnt < V_TOTAL) begin
147 vga_r <= 8'b1111_1111;
148 vga_g <= 8'b1111_1111;
149 vga_b <= 8'b1111_1111;
150 end
151 end
152 */
153
154
155 //竖条纹
156 always @(posedge vga_clk) begin
157 if (hcnt < H_FRONT + H_SYNC + H_BACK) begin //前消隐+同步时间段+后消隐期无颜色(黑色)
158 vga_r <= 8'b0000_0000;
159 vga_g <= 8'b0000_0000;
160 vga_b <= 8'b0000_0000;
161 end
162
163 else if (hcnt < (H_DISP >> 3) * 1 + H_FRONT + H_SYNC + H_BACK) begin
164 vga_r <= 8'b1111_1111;
165 vga_g <= 8'b0000_0000;
166 vga_b <= 8'b1000_0000;
167 end
168
169 else if (hcnt < (H_DISP >> 3) * 2 + H_FRONT + H_SYNC + H_BACK) begin
170 vga_r <= 8'b0000_0000;
171 vga_g <= 8'b0000_0000;
172 vga_b <= 8'b1111_1111;
173 end
174
175 else if (hcnt < (H_DISP >> 3) * 3 + H_FRONT + H_SYNC + H_BACK) begin
176 vga_r <= 8'b0000_0000;
177 vga_g <= 8'b1111_1111;
178 vga_b <= 8'b0000_0000;
179 end
180
181 else if (hcnt < (H_DISP >> 3) * 4 + H_FRONT + H_SYNC + H_BACK) begin
182 vga_r <= 8'b0000_0000;
183 vga_g <= 8'b1111_1111;
184 vga_b <= 8'b1111_1111;
185 end
186
187 else if (hcnt < (H_DISP >> 3) * 5 + H_FRONT + H_SYNC + H_BACK) begin
188 vga_r <= 8'b1111_1111;
189 vga_g <= 8'b0000_0000;
190 vga_b <= 8'b0000_0000;
191 end
192
193 else if (hcnt < (H_DISP >> 3) * 6 + H_FRONT + H_SYNC + H_BACK) begin
194 vga_r <= 8'b1111_1111;
195 vga_g <= 8'b0000_0000;
196 vga_b <= 8'b1111_1111;
197 end
198
199 else if (hcnt < (H_DISP >> 3) * 7 + H_FRONT + H_SYNC + H_BACK) begin
200 vga_r <= 8'b1111_1111;
201 vga_g <= 8'b1111_1111;
202 vga_b <= 8'b0000_0000;
203 end
204
205 else if (hcnt < H_TOTAL) begin
206 vga_r <= 8'b1111_1111;
207 vga_g <= 8'b1111_1111;
208 vga_b <= 8'b1111_1111;
209 end
210 end
211
212 endmodule
需要注意的是,PLL锁相环产生的时钟要是162MHz。
最新文章
- 【jq】c#零基础学习之路(4)抽象类和密封
- js获取新浪天气接口
- python数学运算的类型转换
- JS读写cookie以及中文乱码解决
- Adding Value To Combo List at Runtime in Oracle Forms
- 【转】Android 实现蘑菇街购物车动画效果
- 10.8 OSInstall破解
- 关闭ES动态创建type
- 关于模板pair的用法
- EXT.NET复杂布局(二)——报表
- 如何优化Cocos2d-X游戏的内存
- SQLAlchemy 教程 —— 基础入门篇
- Python(十) Python 中的 *args 和 **kwargs
- Mybatis进阶学习笔记——关系查询——一对多查询
- 获取MyBatis
- 【C】——使用creat()函数需要注意的事项
- EditText输入属性
- numpy.random.randn()与rand()的区别【转】
- iOS Socket编程-C语言版(UDP)
- 【校招面试 之 C/C++】第31题 C++ 11新特性(二)之nullptr关键字
热门文章
- metinfo小于v6.2.0版本通杀SQL盲注漏洞分析
- android studio 找不到真机设备
- SpringBoot 与 SpringSecurity
- APK 的前世今生:从 Android 源码到 apk 的编译打包流程
- 游标数据练习java
- day114:MoFang:基于支付宝沙箱测试环境完成创建充值订单接口&;服务端处理支付结果的同步通知和异步通知
- [LeetCode]Minimum Moves to Equal Array Elements1,2
- .NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
- 行业动态 | DataStax 2021年新年预测
- 【函数分享】每日PHP函数分享(2021-1-8)