Verilog的VGA显示控制

from : 好友博客:http://www.edabc.net/blog/?uid-20-action-viewspace-itemid-591

一、VGA时序

下面的图是本人画了一个晚上的结果,个人认为能够比较详细的阐述VGA的信号时序


VGA的时序根据不同的显示分辨率和刷新频率会有变化,具体各种类型的时序信息可以参考下面的网站
这里非常详细的说明的每一种显示模式的VGA时序信息
http://www.epanorama.net/documents/pc/vga_timing.html

二、VGA电平

VSYNC,HSYNC为标准TTL电平,0V~3.3V
RGB的电平在0V~0.7V之间(0V为黑色,0.7V为全色)

三、程序顶层框图

VGA产生行同步(HSYNC),场同步信号(VSYNC),并产生每个像素的地址输入单口ROM(显存)中,ROM输出该点需要显示的颜色值

四、单口ROM(显存)设计

程序的显示模式为800*600,72Hz刷新频率,像素频率为50MHz
每个像素需要显示的颜色存储在单口RAM中,每种颜色用8个字节表示
则如果要显示800*600分辨率,则需要800*600字节(480KB)的单口ROM
由于FPGA内部没有这么大的RAM,因此我把屏幕上100*100个像素组成的矩形作为一个逻辑像素(即显示同一种颜色)
这样只要8*6字节(48字节),用FPGA自带的RAM是很容易实现的

ROM中颜色存储地址表:

将全屏划分成8*6的方格,每个方格的颜色存储在ROM中,VGA控制器不断产生行坐标(ROM水平地址)和场坐标(ROM垂直地址)
最后组合成ROM实际地址输入ROM中,ROM输出该地址的颜色值,显示在LCD中

五、程序设计


代码
  1 module VGA(clk,rst_n,hsync,vsync,vga_r,vga_g,vga_b);
  2
  3  
  4
  5 input clk;       // 50MHz
  6
  7 input rst_n;    // 复位信号
  8
  9 output hsync;  // 行同步信号
 10
 11 output vsync;  // 场同步信号
 12
 13 //  R、G、B信号输出
 14
 15 output[ 1 : 0 ] vga_r;
 16
 17 output[ 2 : 0 ] vga_g;
 18
 19 output[ 2 : 0 ] vga_b;
 20
 21 // --------------------------------------------------
 22
 23 reg[ 10 : 0 ] x_cnt;      // 行坐标(这里包括了行同步、后沿、有效数据区、前沿)
 24
 25 reg[ 9 : 0 ] y_cnt;      // 列坐标(这里包括了场同步、后沿、有效数据区、前沿)
 26
 27 reg[ 5 : 0 ] Xcoloradd;
 28
 29 reg[ 2 : 0 ] Ycoloradd;
 30
 31  
 32
 33 parameter
 34
 35      Left  =   184 ,
 36
 37      PixelWidth  =   100 ,
 38
 39      Top  =   29 ;
 40
 41      
 42
 43 always @ (posedge clk or negedge rst_n)
 44
 45        if ( ! rst_n) x_cnt  <=   10 ' d0;
 46
 47        else   if (x_cnt  ==   11 ' d1040) x_cnt <= 10 ' d0;           // 行计数记到1040
 48
 49        else  x_cnt  <=  x_cnt + 1 ' b1;
 50
 51  
 52
 53 always @ (posedge clk or negedge rst_n) // 产生行地址(ROM水平地址)
 54
 55        if ( ! rst_n) Xcoloradd  <=   6 ' b000000;
 56
 57        else   if (x_cnt  >=  Left  &&  x_cnt  < Left  +  PixelWidth) Xcoloradd  <=   6 ' b000000;
 58
 59        else   if (x_cnt  >=  Left  +  PixelWidth  &&  x_cnt  < Left  +   2 * PixelWidth) Xcoloradd  <=   6 ' b000001;
 60
 61        else   if (x_cnt  >=  Left  +   2 * PixelWidth  &&  x_cnt  < Left  +   3 * PixelWidth) Xcoloradd  <=   6 ' b000010;
 62
 63        else   if (x_cnt  >=  Left  +   3 * PixelWidth  &&  x_cnt  < Left  +   4 * PixelWidth) Xcoloradd  <=   6 ' b000011;
 64
 65        else   if (x_cnt  >=  Left  +   4 * PixelWidth  &&  x_cnt  < Left  +   5 * PixelWidth) Xcoloradd  <=   6 ' b000100;
 66
 67        else   if (x_cnt  >=  Left  +   5 * PixelWidth  &&  x_cnt  < Left  +   6 * PixelWidth) Xcoloradd  <=   6 ' b000101;
 68
 69        else   if (x_cnt  >=  Left  +   6 * PixelWidth  &&  x_cnt  < Left  +   7 * PixelWidth) Xcoloradd  <=   6 ' b000110;
 70
 71        else   if (x_cnt  >=  Left  +   7 * PixelWidth  &&  x_cnt  < Left  +   8 * PixelWidth) Xcoloradd  <=   6 ' b000111;
 72
 73        else  Xcoloradd  <=   6 ' b110000;//背景颜色地址
 74
 75  
 76
 77 always @ (posedge clk or negedge rst_n)
 78
 79        if ( ! rst_n) y_cnt  <=   10 ' d0;
 80
 81        else   if (y_cnt  ==   10 ' d666) y_cnt <= 10 ' d0;             // 场同步记到666
 82
 83        else   if (x_cnt  ==   11 ' d1040) y_cnt <= y_cnt+1 ' b1; // 每计数完一行,场同步就加一
 84
 85      
 86
 87 always @ (posedge clk or negedge rst_n) // 产生列地址(ROM垂直地址)
 88
 89        if ( ! rst_n) Ycoloradd  <=   3 ' b000;
 90
 91        else   if (y_cnt  >=  Top  &&  y_cnt  <  Top  +  PixelWidth) Ycoloradd  <=   3 ' b000;
 92
 93        else   if (y_cnt  >=  Top  +  PixelWidth  &&  y_cnt  <  Top  +   2 * PixelWidth) Ycoloradd  <=   3 ' b001;
 94
 95        else   if (y_cnt  >=  Top  +   2 * PixelWidth  &&  y_cnt  <  Top  +   3 * PixelWidth) Ycoloradd  <=   3 ' b010;
 96
 97        else   if (y_cnt  >=  Top  +   3 * PixelWidth  &&  y_cnt  <  Top  +   4 * PixelWidth) Ycoloradd  <=   3 ' b011;
 98
 99        else   if (y_cnt  >=  Top  +   4 * PixelWidth  &&  y_cnt  <  Top  +   5 * PixelWidth) Ycoloradd  <=   3 ' b100;
100
101        else   if (y_cnt  >=  Top  +   5 * PixelWidth  &&  y_cnt  <  Top  +   6 * PixelWidth) Ycoloradd  <=   3 ' b101;
102
103        else  Ycoloradd  <=   3 ' b110;//背景颜色地址
104
105 // --------------------------------------------------
106
107 //  signal port ROM
108
109  
110
111 wire[ 7 : 0 ] color;
112
113 wire[ 5 : 0 ] coloradd;
114
115  
116
117 ExpandedBlockStart.gifContractedBlock.gifassign coloradd  =   {Ycoloradd,3'b000}|Xcoloradd;//将水平地址和垂直地址合成ROM实际地址
118
119sprom u1(coloradd,clk,color);
120
121 
122
123//---------------------------------------------------
124
125 
126
127wire valid;     //有效数据显示区标志,就是你在液晶屏幕上可以看到的区域
128
129 
130
131assign valid = (x_cnt > 10'd184) && (x_cnt < 10'd984)
132
133 
134
135          && (y_cnt > 10'd29) && (y_cnt < 10'd629);
136
137//--------------------------------------------------
138
139reg hsync_r,vsync_r;
140
141 
142
143always @ (posedge clk or negedge rst_n)
144
145  if (!rst_n) begin
146
147             hsync_r <= 1'b0;
148
149     vsync_r <= 1'b0;
150
151     end
152
153  else begin
154
155     hsync_r <= x_cnt >= 10'd120; //产生hsync信号(行同步)when x_cnt>=50,then hsync_r=1,else 0;低电平同步
156
157     vsync_r <= y_cnt >= 10'd6;  //产生vsync信号(场同步)my LCD is low sync
158
159     end
160
161assign hsync = hsync_r;
162
163assign vsync = vsync_r;
164
165 
166
167//--------------------------------------------------
168
169//颜色输出
170
171assign vga_r[1= valid ? color[7] : 1'b0;
172
173assign vga_r[0= valid ? color[6] : 1'b0;
174
175 
176
177assign vga_g[2= valid ? color[5] : 1'b0;
178
179assign vga_g[1= valid ? color[4] : 1'b0;
180
181assign vga_g[0= valid ? color[3] : 1'b0;
182
183 
184
185assign vga_b[2= valid ? color[2] : 1'b0;  
186
187assign vga_b[1= valid ? color[1] : 1'b0;
188
189assign vga_b[0= valid ? color[0] : 1'b0;
190
191 
192
193endmodule

194

六、后记

在这次程序中只在ROM中存储了一些随机的数,因此显示出来是一些小方格
如果ROM做的更大,完全可以存储一幅图像,显示在LCD中
不过由于由于用ROM做为显存,每次只能显示一幅静态的图像,而且没有加入字符库,不能显示字符
在下次的文章中,我将使用双口RAM,加上Nios II处理器,这样可以方便的显示各种字符

转载于:https://www.cnblogs.com/zhangzhi/archive/2009/11/29/1612912.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值