基于verilog的VGA简单接口驱动
0赞断断续续的利用业余的 时间终于搞定了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