FPGA学习系列:27. VGA驱动设计

设计背景: 
    vga (video graphics array) 即视频图形阵列,是ibm于1987年随ps/2机(personalsystem 2)一起推出的使用模拟信号的一种视频传输标准。这个标准对于现今的个人电脑市场已经十分过时。但在当时具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域取得了广泛的应用,是众多制造商所共同支持的一个低标准。
设计原理: 
    vga的实体图与接口示意图,如下图所示,它有15个针孔:
在开发板(zx_1)中,vga的电路原理图如下图所示:
通过原理图,我们不难发现,vga需要我们控制的接口只有5个:
显示器的扫描规律是什么?本设计采用逐行扫描,逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,crt对电子束进行消隐,每行结束时,用行同步信号进行行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。通过这种扫描规律,很容易看出,在设计两个有效范围计数器时,场同步信号计数器是以行同步信号计数器为周期的。
    vga的显示标准如下表所示:
对于普通的vga显示器都要严格遵循“vga工业标准”,否则可能会损害vga显示器,因此我们在设计时vga控制器时,都需要参考显示器的显示标准,下面是vga的行扫描时序与场扫描时序:
    行扫描时序:
场扫描时序:
根据上述显示器的扫描参数以及扫描时序,例如800*600@60的显示模式,60指得是显示器图像的刷新频率,时钟40mhz指得是一个像素输出的频率。800*600为vga的分辨率,指有效显示区域为时序中的c段只有800*600,也就是行计数在[216,1016],列计数在[27,627],在这个范围内,给rgb色值才会有效。
    在vga 工业标准显示模式要求:行同步、场同步都为负极性,即同步脉冲要求是负脉冲。行同步信号上电拉高,在行同步计数为0时拉低a个时钟周期,即128,之后拉高,在行同步计数到1055时,行同步计数器清零,场同步计数器加1。在行扫描时序中,扫描计数时,周期就是一个像素点的时间。
    场同步信号上电拉高,在场同步计数为0时拉低场同步a个时钟周期,即4,之后拉高,在场同步计数到627时,场同步计数器清零。
    在vga控制器中,还需要控制三个接口,即三种基色(r、g、b),它们共专用8位,分别是red为3位,green为3位,blue为3位,所以可以显示256种颜色,rgb数据的格式如下表所示:
设计架构图: 
    本设计选择的vga显示标准为800*600@60,实现点亮整个屏幕,并显示为全红。通过分析设计的功能,可以得到如下的顶层架构:
顶层模块端口列表如下:
vga_pll模块是为了满足分辨率800*600@60的时钟为40mhz,而zx_1开发板的系统时钟为50mhz,通过锁相环,将50mhz转化为40mhz。vga_control模块是为了设定行场同步信号,并标定出有效显示区域,并输出控制颜色的po_rgb信号。为了便于移植,根据800*600@60分辨率下的参数,对其进行参数化定义。
设计代码: 
    vga控制器代码:
0   module vga_control (pi_clk, pi_rst_n, po_hs, po_vs, po_rgb);
1       
2       input pi_clk, pi_rst_n; //系统时钟复位
3       output reg po_vs;  //vga场同步信号
4       output reg po_hs;   //vga行同步信号
5       output [7:0] po_rgb;    //vga场红绿蓝三基色
6       
7       //----------------vga时序-----------------------------------
8       //      显示模式        时钟     
9       //      800*600@60  40mhz   
10      //行/场   同步(a)   消隐后沿(b) 有效显示(c) 消隐前沿(d) 扫描时间(e)
11      //hs        128     88              800         40              1056
12      //vs        4           23              600         1               628
13      
14      //  行(horizontal)扫描   parameter (像素)
15      parameter   h_a =   128;
16      parameter   h_b =   80;
17      parameter   h_c =   800;
18      parameter   h_d =   40;
19      parameter   h_e   = 1056;
20      
21      
22      //  场(vertical)扫描 parameter (行数)
23      parameter   v_a =   4;
24      parameter   v_b =   23;
25      parameter   v_c =   600;
26      parameter   v_d =   1;
27      parameter   v_e =   628;
28      
29      //行扫描计数器,
30      reg [10:0] hcnt;
31      
32      always @ (posedge pi_clk or negedge pi_rst_n)
33      begin
34          if (!pi_rst_n)
35              hcnt <= 11'd0;
36          else
37              begin
38                  if (hcnt == (h_e - 1'b1)) //扫描完一行像素
39                      hcnt <= 11'd0;
40                  else
41                      hcnt <= hcnt + 1'b1;
42              end 
43      end 
44      
45      //场扫描计数器
46      reg [10:0] vcnt;  
47      
48      always @ (posedge pi_clk or negedge pi_rst_n)
49      begin
50          if (!pi_rst_n)
51              vcnt <= 11'd0;
52          else if (vcnt == (v_e - 1'b1)) 
53              vcnt <= 11'd0;
54          else if (hcnt == (h_e - 1'b1))
55              vcnt <= vcnt + 1;
56      end     
57
58      //行同步输出
59      always @ (posedge pi_clk or negedge pi_rst_n)
60      begin
61          if (!pi_rst_n)
62              po_hs <= 1'b1;
63          else if (hcnt < h_a)
64              po_hs <= 1'b0;
65          else
66              po_hs <= 1'b1;
67      end 
68      
69      //assign po_hs = (hcnt <= h_a - 1'b1) ? 1'b0 : 1'b1;
70      
71      //场同步输出
72      always @ (posedge pi_clk or negedge pi_rst_n)
73      begin
74          if (!pi_rst_n)
75              po_vs <= 1'b1;
76          else if (vcnt < v_a)
77              po_vs <= 1'b0;
78          else
79              po_vs <= 1'b1;
80      end 
81      
82      //assign po_vs = (vcnt = h_a + h_b  && hcnt = v_a + v_b  && vcnt < v_a + v_b + v_c) ? 1'b1 : 1'b0;
88      
89      assign po_rgb = rgb_en ? 8'b111_000_00 : 8'b0000_0000;
90      
91  endmodule
顶层文件如下所示:
0   module vga_display_pure (pi_clk, pi_rst_n, po_hs, po_vs, po_rgb);
1       
2       input pi_clk, pi_rst_n; //系统时钟复位
3       output po_vs;  //vga场同步信号
4       output po_hs;   //vga行同步信号
5       output [7:0] po_rgb;    //vga场红绿蓝三基色
6       
7       //----------------vga时序-----------------------------------
8       //      显示模式        时钟     
9       //      800*600@60  40mhz   
10      //行/场   同步(a)   消隐后沿(b) 有效显示(c) 消隐前沿(d) 扫描时间(e)
11      //hs        128     88              800         40              1056
12      //vs        4           23              600         1               628
13      
14      wire vga_clk;
15      
16      vga_pll vga_pll_dut(
17          .areset(~pi_rst_n),
18          .inclk0(pi_clk),
19          .c0(vga_clk)
20      );
21      
22      vga_control vga_control_dut(
23          .pi_clk(vga_clk), 
24          .pi_rst_n(pi_rst_n), 
25          .po_hs(po_hs),
26          .po_vs(po_vs),
27          .po_rgb(po_rgb)
28      );
29      
30  endmodule
通过编译后生成的rtl视图如下:
为了验证本设计的逻辑正确性,我们先对其进行了仿真,在仿真时,为了减少仿真的时间,先将行、场扫描的对应参数,进行了缩放,这样不仅节约了仿真时间,同时由于扫描数据量变少,更加便于分析观察。其仿真代码所示;
0   `timescale 1ns/1ps  //仿真时间精度时间单位

2   module vga_display_pure_tb;
3       
4       reg pi_clk, pi_rst_n; //系统时钟复位
5       wire  po_vs;  //vga场同步信号
6       wire  po_hs;    //vga行同步信号
7       wire  [7:0] po_rgb; //vga场红绿蓝三基色
8       
9       //初始化数据,并附相应初值
10      initial begin
11          pi_clk = 0;
12          pi_rst_n = 0;  
13          #200.1 pi_rst_n = 1;  
14          
15      end 
16
17      vga_display_pure vga_display_pure_inst (
18          .pi_clk(pi_clk), 
19          .pi_rst_n(pi_rst_n), 
20          .po_hs(po_hs), 
21          .po_vs(po_vs),
22          .po_rgb(po_rgb)
23      );
24      
25      always #10 pi_clk = ~pi_clk;  //50mhz时钟描述
26
27  endmodule
仿真图:
rgb_en信号,只有当po_vs和po_hs同时为高电平时,才有效,并且有po_rgb red基色信号输出,时序仿真细节图如下所示:
通过观察和分析时序图,可以发现与设计吻合,接下来则可进行管脚分配,并下板验证,验证结果如下:

oppor11预约正式开启,堪称6月最值得期待手机
电力智能配电系统
89C51单片机中断知识要点
八种硬件设计EDA工具对比分析(价格、难度、功能)
为什么要使用MPU?MPU实现内存保护原理分析
FPGA学习系列:27. VGA驱动设计
防烧电路中的MOS管控制
AMCOMRF晶体管GaAs FET的性能表现非常优异
FPGA学习系列:9.简单状态机设计
单站DMB-T 发射的移动数字电视项目如何实现?
共享单车利用 NB-IoT 现网并支持 2G 转 NB-IoT 全类型业务
绝缘型反激式转换器的性能评估-性能评估事例中所使用电源IC的概述和应掌握的特征
多功能仪表接线说明Acrel Multi-function Meter Wiring Instruction
浅谈电瓶修复技术之蓄电池基础知识的讲解(一)
消防设备电源监控系统在某改造项目中的设计应用案例
汽车开发环境解决方案项目
学习Python的双重选择: 树莓派和行空板
为准备Android 11版本,谷歌继续开发 Android Beta项目
具有柔性自适应导电界面的超稳定可拉伸电极
冗余收发器RS-232链路,提供±40V过压保护