特权同学

基于verilog的VGA简单接口驱动

0
阅读(4069)

断断续续的利用业余的 时间终于搞定了VGA的驱动,从VGA的显像原理到接口的定义再到编程驱动。其实现在想想还是蛮简单的,显像的原 理就不废话了,前面的日志里有详细的说明,今天就主要谈一下用verilog对VGA编程驱动。

       FPGA芯片用的还是Spartan3系列的xc3s400。即使是编程,也还是 不得不先看看它的接口连接电路:

 


标准VGA一共15个接口(拔下你家的液晶或是CRT显示器看看就知道 了),真正用到的信号接口不多,就五个,HSYNC是行同步信号,VSYNC是场同步信号,VGA_R、VGA_G、VGA_B是三原色信号,这三个 信号接口都是输入模拟信号的,所以它们都有相应的地线需要连接。我的这块FPGA开发板上面做的比较简单,直接用IO口去连接VGA的五个信号接口了,并 且三原色信号接口输入的只可能是数字信号(0或1),因此驱动液晶屏上显示的颜色最多也就8种,一般来说,可以在FPGA和VGA接口间加一个DA模块的设计,这样就可 能实现65536或者更多种可能的配色 效果。

       看完接口电路,就看程序吧,这个程序要实现的显示效果很简单,屏幕是800*600(15寸液晶)的,如图:

Verilog代码以及详细注释如 下:

module vga_rgb8(clk,rst_n,hsync,vsync,vga_r,vga_g,vga_b);

 

input clk;       //50MHz

input rst_n;    //低电平复位

output hsync;//行同步信号

output vsync;//场同步信号

       //三原色信号接口R、G、B

output vga_r;

output vga_g;

output vga_b;

 

//--------------------------------------------------

reg[9:0] x_cnt;      //行坐标(这里包括了行同步、后沿、有效数据区、前沿)

reg[9:0] y_cnt;      //列坐标(这里包括了场同步、后沿、有效数据区、前沿)

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) x_cnt <= 10'd0;

       else if(x_cnt == 10'd1000) x_cnt <= 10'd0;           //行计数只记到1000

       else x_cnt <= x_cnt+1'b1;

 

always @ (posedge clk or negedge rst_n)

       if(!rst_n) y_cnt <= 10'd0;

       else if(y_cnt == 10'd665) y_cnt <= 10'd0;             //场同步只记到665

       else if(x_cnt == 10'd1000) y_cnt <= y_cnt+1'b1;//每计数完一行,场同步 就加一

 

//--------------------------------------------------

wire valid;      //有效数据显示区标志,就是你在液晶屏幕上可以看到的区域

/*要说明的一点是,当坐标不处于有效显示区时,R、G、B三原色信号接的电平都必 须拉底(0)*/

 

assign valid = (x_cnt > 10'd180) && (x_cnt < 10'd980)

                                   && (y_cnt > 10'd35) && (y_cnt < 10'd635);

 

wire[9:0] xpos,ypos;    //有效显示区坐标

 

assign xpos = x_cnt-10'd180;

assign ypos = y_cnt-10'd35;

 

//--------------------------------------------------

reg hsync_r,vsync_r;

 

always @ (posedge clk or negedge rst_n)

   if (!rst_n) begin

              hsync_r <= 1'b0;

      vsync_r <= 1'b0;

      end

   else begin

      hsync_r <= x_cnt <= 10'd50;  //产生hsync信号(行同步)

      vsync_r <= y_cnt <= 10'd6;   //产生vsync信号(场同步)

      end

 

assign hsync = hsync_r;

assign vsync = vsync_r;

 

//--------------------------------------------------

       //显示一个矩形框

wire a_dis,b_dis,c_dis,d_dis;     //矩形框显示区域定位

 

assign a_dis = ( (xpos>=200) && (xpos<=220) )

                            &&( (ypos>=140) && (ypos<=460) );

                           

assign b_dis = ( (xpos>=580) && (xpos<=600) )

                            && ( (ypos>=140) && (ypos<=460) );

 

assign c_dis = ( (xpos>=220) && (xpos<=580) )

                            &&( (ypos>140)  && (ypos<=160) );

                           

assign d_dis = ( (xpos>=220) && (xpos<=580) )

                            && ( (ypos>=440) && (ypos<=460) );

 

       //显示一个小矩形

wire e_rdy;    //矩形的显示有效矩形区域

 

assign e_rdy = ( (xpos>=385) && (xpos<=415) )

                            &&( (ypos>=285) && (ypos<=315) );

 

//--------------------------------------------------

       //r,g,b控制液晶屏颜色显示,背景显示蓝色,矩形框显示红蓝色

assign vga_r = valid ? e_rdy : 1'b0;

assign vga_g = valid ?  (a_dis | b_dis | c_dis | d_dis) : 1'b0;

assign vga_b = valid ? ~(a_dis | b_dis | c_dis | d_dis) : 1'b0; 

 

endmodule