特权同学

基于verilog的VGA简单接口驱动

0
阅读(3876)

断断续续的利用业余的 时间终于搞定了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

Baidu
map