首页 > 技术文章 > VGA显示

aikimi7 2014-08-15 16:55 原文

VGA控制器的编写主要是了解VGA的显示标准和时序,如1024X768@60Hz,确定时钟频率(65MHz=1344X806X60),列像素时间等于时钟周期,扫描从左到右、从上到下(类似于电视扫描PAL)。除有效时间外,一行还有同步脉冲时间、后肩和前肩。(http://tinyvga.com/vgatiminghttp://wenku.baidu.com/view/13b3140102020740be1e9b94.html,

http://www.cnblogs.com/qiweiwang/archive/2011/01/17/1937688.html

image image

 

然后根据时序实现显示标准的功能模块,完成同步信号的输出、有效区域标志和当前坐标。一行列像素计数完成后,行计数器加1,列像素计数器清零后继续计数,知道最后一行计数完成后,行计数器清零,重复上述过程。

 1 `timescale 1 ps/1 ps
 2 module sync_module(
 3      output VSYNC_Sig,HSYNC_Sig,Ready_Sig,Frame_Sig,
 4      output [10:0]Column_Addr_Sig,Row_Addr_Sig,    
 5     input CLK,RSTn     
 6 );
 7 //VGA format: 640 X 480 @ 60Hz,pix width:0.039683us≈40ns,25MHz
 8 //场扫描时序: 2--30--484-- 9,    525
 9 //一般:      2--33--480-- 10
10 //行扫描时序:96--45--646--13,    800
11 //一般:      96--48--640--16
12 
13 //VGA format: 1024 X 768 @ 60Hz,pix width:1/65MHz
14 //场扫描时序: 6--  29-- 768-- 3,     806
15 //行扫描时序:136--160--1024--24,    1344
16      /********************************/
17      
18      reg [10:0]Count_H;
19 
20      always @ ( posedge CLK or negedge RSTn )
21          if( !RSTn )
22                  Count_H <= 11'd0;
23             else if( Count_H == 11'd1343 )
24                 Count_H <= 11'd0;
25             else 
26                 Count_H <= Count_H + 1'b1;
27     
28      /********************************/
29      
30      reg [10:0]Count_V;
31          
32      always @ ( posedge CLK or negedge RSTn )
33          if( !RSTn )
34               Count_V <= 11'd0;
35           else if( Count_V == 11'd805 )
36               Count_V <= 11'd0;
37           else if( Count_H == 11'd1343 )
38               Count_V <= Count_V + 1'b1;
39     
40      /********************************/
41      wire isReady;
42 
43     assign isReady = ( ( Count_H >= 11'd296 && Count_H <= 11'd1319 ) &&    //有效时间1024
44                     ( Count_V >= 11'd35 && Count_V <= 11'd802 ) ) ? 1'b1 : 1'b0;      //768
45             
46      /*********************************/
47      
48      assign VSYNC_Sig = ( Count_V < 11'd6 ) ? 1'b0 : 1'b1;  //场同步信号
49      assign HSYNC_Sig = ( Count_H < 11'd136 ) ? 1'b0 : 1'b1; //行同步信号
50      assign Ready_Sig = isReady; 
51      assign Frame_Sig = ( Count_V == 11'd805 ) ? 1'b1 : 1'b0; //帧结束标志                       
52      
53      /********************************/
54      
55      assign Column_Addr_Sig = isReady ? Count_H - 11'd296 : 11'd0;    // Count from 0; 列地址
56      assign Row_Addr_Sig = isReady ? Count_V - 11'd35 : 11'd0; // Count from 0; 行地址
57     
58      /********************************/
59      
60 endmodule
sync_module.v

第二个模块根据有效区域标志和当前坐标完成图像的显示,输出需要的RGB值,相对简单。

  1 `timescale 1 ps/1 ps
  2 module vga_control_module(
  3      output Red_Sig,Green_Sig,Blue_Sig,
  4      output[6:0]Rom_Addr,
  5      input[15:0]Rom_Data,
  6      input [10:0]Column_Addr_Sig,Row_Addr_Sig,
  7     input Ready_Sig,Frame_Sig,CLK,RSTn 
  8 );
  9 
 10 /**********************************/
 11 //greenman 16X16,6pics
 12 //16X96,reg [15:0] mem [6:0],帧偏移量16
 13      
 14      reg [3:0]m;
 15      wire[10:0]row_addr;
 16      wire row_valid;
 17      assign row_addr = Row_Addr_Sig - 11'd300; //图片显示起始位置y坐标:300
 18      assign row_valid = row_addr < 16 && row_addr >= 0; //图片行有效0-15
 19      
 20      always @ ( posedge CLK or negedge RSTn )
 21          if( !RSTn )
 22               m <= 4'd0; 
 23           else if( Ready_Sig && row_valid )
 24               m <= row_addr[3:0];
 25           else 
 26                 m <= 4'd0; 
 27                 
 28     /************************************/
 29     
 30     reg [3:0]n;
 31     wire[10:0]col_addr;
 32     wire col_valid;
 33     assign col_addr = Column_Addr_Sig - 11'd500; //图片显示起始位置x坐标:500
 34     assign col_valid = col_addr < 16 && col_addr >= 0; //图片列有效0-15
 35     
 36     always @ ( posedge CLK or negedge RSTn )
 37         if( !RSTn )
 38              n <= 4'd0;
 39          else if( Ready_Sig && col_valid )
 40              n <= col_addr[3:0];
 41          else 
 42               n <= 4'd0; 
 43                 
 44      /**********************************/
 45      
 46      parameter FRAME = 10'd10;  //每幅图像显示10帧 X 6 = 60Hz
 47      
 48      /**********************************/
 49      
 50      reg [9:0]Count_Frame;
 51 
 52      always @ ( posedge CLK or negedge RSTn )
 53          if( !RSTn )
 54             Count_Frame <= 10'd0;
 55           else if( Count_Frame == FRAME )
 56               Count_Frame <= 10'd0;
 57           else if( Frame_Sig )
 58               Count_Frame <= Count_Frame + 1'b1;  //帧计数
 59     
 60     /************************************/    
 61      ///// 帧偏移地址16,状态机控制,跳转条件计数到10帧切换下一幅图像
 62      
 63      reg [6:0]rAddr;
 64      reg [3:0]state;
 65      
 66      always @ ( posedge CLK or negedge RSTn )
 67          if( !RSTn )
 68               begin
 69                   rAddr <= 7'd0;
 70                      state <= 4'd0;
 71                end
 72           else
 73               case ( state )
 74                 
 75                     4'd0 : 
 76                      if( Count_Frame == FRAME ) state <= 4'd1; 
 77                      else rAddr <= 7'd0;
 78                      
 79                      4'd1 :
 80                      if( Count_Frame == FRAME ) state <= 4'd2;
 81                      else rAddr <= 7'd16;
 82                      
 83                      4'd2 :
 84                      if( Count_Frame == FRAME ) state <= 4'd3;
 85                      else rAddr <= 7'd32;
 86                      
 87                      4'd3 :
 88                      if( Count_Frame == FRAME ) state <= 4'd4;
 89                      else rAddr <= 7'd48;
 90                     
 91                      4'd4 :
 92                      if( Count_Frame == FRAME ) state <= 4'd5;
 93                      else rAddr <= 7'd48;
 94                      
 95                      4'd5 :
 96                      if( Count_Frame == FRAME ) state <= 4'd6;
 97                      else rAddr <= 7'd64;
 98                      
 99                      4'd6 :
100                      if( Count_Frame == FRAME ) state <= 4'd0;
101                      else rAddr <= 7'd80;
102                      
103                 endcase
104                 
105      /************************************/
106     
107     assign Rom_Addr = rAddr + m; //图像起始地址 + 行寻址
108     
109      assign Red_Sig = Ready_Sig ? Rom_Data[ 5'd15 - n ] : 1'b0;   //扫描到图片大小区域时获取ROM数据,
110      assign Green_Sig = Ready_Sig  ? Rom_Data[ 5'd15 - n ] : 1'b0; //row_valid && col_valid 
111      assign Blue_Sig = Ready_Sig ? ~Rom_Data[ 5'd15 - n ] : 1'b0; //不在图片区域内时显示底色:蓝色
112      
113     /***********************************/
114      
115 //     /**********************************/
116 //     
117 //     reg [5:0]m;
118 //     wire[10:0]row_add;
119 //     assign row_add = Row_Addr_Sig - 11'd300;
120 //     
121 //     always @ ( posedge CLK or negedge RSTn )
122 //         if( !RSTn )
123 //              m <= 6'd0; 
124 //          else if( Ready_Sig && row_add < 64 && row_add >= 0 )
125 //              m <= row_add[5:0];
126 //      else    
127 //            m <= 6'd0;
128 //                
129 //    /************************************/
130 //    
131 //    reg [5:0]n;
132 //    wire[10:0]col_add;
133 //    assign col_add = Column_Addr_Sig - 11'd500;
134 //    
135 //    always @ ( posedge CLK or negedge RSTn )
136 //        if( !RSTn )
137 //             n <= 6'd0;
138 //         else if( Ready_Sig && col_add < 64 && col_add >= 0 )
139 //             n <= col_add[5:0];    
140 //     else    
141 //           n <= 6'd0;
142 //                
143 //    /************************************/
144 //    
145 //    assign Rom_Addr = m;
146 //    
147 //     assign Red_Sig =  Ready_Sig ? Red_Rom_Data[ 6'd63 - n ] : 1'b0; //3个ROM读取不同的RGB值
148 //     assign Green_Sig = Ready_Sig ? Green_Rom_Data[ 6'd63 - n ] : 1'b0;
149 //     assign Blue_Sig = Ready_Sig ? Blue_Rom_Data[ 6'd63 - n ] : 1'b0;
150 
151 
152 ////---------显示一个圆--------------------
153 //parameter radius  = 11'd100; //半径
154 //parameter radius2 = radius * radius; //半径的平方
155 //parameter x_pos = 11'd400; //圆心x坐标
156 //parameter y_pos = 11'd500; //圆心y坐标
157 //
158 //reg[10:0] x_temp,y_temp; 
159 //reg[21:0] x_temp_2,y_temp_2;
160 //wire is_flag;
161 //
162 //always@*
163 //    if(Column_Addr_Sig >= x_pos)
164 //        x_temp = Column_Addr_Sig - x_pos;
165 //    else 
166 //        x_temp = x_pos - Column_Addr_Sig;
167 //
168 //always@*
169 //    if(Row_Addr_Sig >= y_pos)
170 //        y_temp = Row_Addr_Sig - y_pos;
171 //    else 
172 //        y_temp = y_pos - Row_Addr_Sig;
173 //        
174 //always@*
175 //    x_temp_2 = x_temp * x_temp;
176 //    
177 //always@*
178 //    y_temp_2 = y_temp * y_temp;
179 //    
180 //assign is_flag = (x_temp_2 + y_temp_2) <= 10000;
181 //
182 //assign Red_Sig = Ready_Sig ? is_flag : 1'b0;
183 //assign Green_Sig = Ready_Sig ?  ~is_flag : 1'b0;
184 //assign Blue_Sig = Ready_Sig ? ~is_flag : 1'b0;
185 
186 //--------------------------------------------------
187     //显示一个矩形框
188 //wire a_dis,b_dis,c_dis,d_dis;    //矩形框显示区域定位
189 //
190 //assign a_dis = ( (Column_Addr_Sig>=200) && (Column_Addr_Sig<220) ) 
191 //                &&    ( (Row_Addr_Sig>=140) && (Row_Addr_Sig<460) );
192 //                
193 //assign b_dis = ( (Column_Addr_Sig>=580) && (Column_Addr_Sig<600) )
194 //                && ( (Row_Addr_Sig>=140) && (Row_Addr_Sig<460) );
195 //
196 //assign c_dis = ( (Column_Addr_Sig>=220) && (Column_Addr_Sig<580) ) 
197 //                &&    ( (Row_Addr_Sig>=140)  && (Row_Addr_Sig<160) );
198 //                
199 //assign d_dis = ( (Column_Addr_Sig>=220) && (Column_Addr_Sig<580) )
200 //                && ( (Row_Addr_Sig>=440) && (Row_Addr_Sig<460) );
201 //
202 //    //显示一个小矩形
203 //wire e_rdy;    //矩形的显示有效矩形区域
204 //
205 //assign e_rdy = ( (Column_Addr_Sig>=385) && (Column_Addr_Sig<=415) )
206 //                &&    ( (Row_Addr_Sig>=285) && (Row_Addr_Sig<=315) );
207 //
208 ////-------------------------------------------------- 
209 //    //r,g,b控制液晶屏颜色显示,背景显示蓝色,矩形框显示红蓝色
210 //assign Red_Sig = Ready_Sig ? e_rdy : 1'b0;
211 //assign Green_Sig = Ready_Sig ?  (a_dis | b_dis | c_dis | d_dis) : 1'b0;
212 //assign Blue_Sig = Ready_Sig ? ~(a_dis | b_dis | c_dis | d_dis) : 1'b0;     
213     
214 //wire a_pos;
215 //assign a_pos = Column_Addr_Sig > 11'd0 && Row_Addr_Sig < 11'd100 ;        
216 ////    /************************************/
217 ////                
218 //     assign Red_Sig = Ready_Sig ? a_pos: 1'b0;
219 //     assign Green_Sig = Ready_Sig ? a_pos : 1'b0;
220 //     assign Blue_Sig = Ready_Sig ? ~a_pos : 1'b0;             
221      
222      endmodule
vga_control_module.v

image

推荐阅读