Fpga的vga显示设计
1.VGA原理
Vga端口一个有15根线,可以百度查看一下VGA端口的定义,这里就不多说了,现在能用到只有5根线,分别是行同步信号输入(h_sync),场同步信号输入(v_sync),红色信号输入(R)、绿色信号输入(G)、蓝色信号输入(B) 。本次实验主要用640x480的分辨率在友晶开发板de2-115上进行开发,所以需要了解VGA有关的时序。
一般VGA扫描的顺序是从左到右,从上到下的方式,理论上一帧要扫640*480的像素点,但实际上还需要考虑同步脉冲(Sync a)、显示后沿(Back porch b)、显示时序段(Display interval c)和显示前沿(Front porch d)四部分。另外VGA工业标准显示模式要求:行同步,场同步都为负极性,即同步脉冲要求是负脉冲。
行扫描图
场扫描图
各个值的对照表。
这次实验采用的是640x480@60hz,计算其他像素就是800x524,需要的频率为800*524*60大约为25M,开发板提供的只有50M,所以可以利用分频为25M。如果设置其他分辨率可以用FPGA内部的PLL来获得所需频率。
由于采用DE2-115开发板作为vga输出实验,接口是需要进行DA转换的,芯片为ADV7123,需要注意的是VGA_CLK,VGA_BLANK_N和VGA_SYNC_N;VGA_CLK为上面分频时钟输送给DA转换芯片,而VGA_BLANK_N为无效时间,(低电平有效),VGA_SYNC_N暂时用不到sopc所以设置为低电平也是(低电平有效)。
2.程序代如下(彩条显示):
module vga(
clk,rst_n,
vga_r,vga_g,vga_b,clk_vga,
hsync,vsync,VGA_BLANK_N,VGA_SYNC_N,
);
input clk; //时钟信号
input rst_n; //复位信号
output [7:0] vga_r ;
output [7:0] vga_g ;
output [7:0] vga_b ;
output clk_vga; //VGA工作时钟
output hsync;
output vsync;
output VGA_BLANK_N;
output VGA_SYNC_N;
reg [7:0]vga_r,vga_g,vga_b;
//------------------------------------ 640*480,刷新频率60Hz,时钟频率25Mhz
parameterH_FRONT=16;
parameterH_SYNC=96;
parameterH_BACK=48;
parameterH_ACT=640;
parameterH_BLANK=H_FRONT+H_SYNC+H_BACK;
parameterH_TOTAL=H_FRONT+H_SYNC+H_BACK+H_ACT;
//Vertical Parameter 11+2+32+480=525
parameterV_FRONT=10;
parameterV_SYNC=2;
parameterV_BACK=33;
parameterV_ACT=480;
parameterV_BLANK=V_FRONT+V_SYNC+V_BACK;
parameterV_TOTAL=V_FRONT+V_SYNC+V_BACK+V_ACT;
assignVGA_SYNC_N=1'b0; //Ifnot SOG, Sync input should be tied to 0;
assignVGA_BLANK_N=~((x_cnt
//------------------------------------
// 分频
reg clk_vga;
always @(posedge clk or negedge rst_n)
if (!rst_n)
clk_vga<=1'b0;
else clk_vga<=~clk_vga;
//------------------------------------
//行列坐标的计算
reg [9:0] x_cnt;
reg [9:0] y_cnt;
always @(posedgeclk_vga or negedge rst_n)
if (!rst_n) begin
x_cnt<=10'd0; //行计数开始
end
else if (x_cnt==800) x_cnt<=0;
else x_cnt<=x_cnt+1;
always @(posedge clk_vga or negedge rst_n)
if (!rst_n) begin
y_cnt<=10'd0; //行计数开始
end
else if (y_cnt==525) y_cnt<=0;
else if (x_cnt==800) y_cnt<=y_cnt+1;
//----------------------------------
//同步信号的产生
reg hsync_r,vsync_r;
always @(posedge clk_vgaor negedge rst_n)
if (!rst_n) hsync_r<=1'b1; //同步信号拉高
else if(x_cnt==0)
hsync_r<=1'b0; //行计数开始,行同步信号拉低
else if(x_cnt==96)
hsync_r<=1'b1; //行计数开始,行同步信号拉高
always @(posedge clk_vga or negedge rst_n)
if (!rst_n) vsync_r<=1'b1; //同步信号拉高
else if(y_cnt==0)
vsync_r<=1'b0; //行计数开始,行同步信号拉低
else if(y_cnt==2)
vsync_r<=1'b1; //行计数开始,行同步信号拉高
assign hsync=hsync_r;
assign vsync=vsync_r;
always @(posedge clk_vga or negedge rst_n)
if (!rst_n)
begin
vga_r=8'b00000000;
vga_g=8'b00000000;
vga_b=8'b00000000;
end
else if(144<=x_cnt&&x_cnt<=223)
begin
vga_r=8'b11111111;
vga_g=8'b00000000;
vga_b=8'b00000000;
end
else if(224<=x_cnt&&x_cnt<=303)
begin
vga_r=8'b11111111;
vga_g=8'b11111111;
vga_b=8'b00000000;
end
else if(304<=x_cnt&&x_cnt<=383)
begin
vga_r=8'b00000000;
vga_g=8'b11111111;
vga_b=8'b00000000;
end
else if(384<=x_cnt&&x_cnt<=463)
begin
vga_r=8'b00000000;
vga_g=8'b11111111;
vga_b=8'b11111111;
end
else if(464<=x_cnt&&x_cnt<=543)
begin
vga_r=8'b11111111;
vga_g=8'b00000000;
vga_b=8'b11111111;
end
else if(544<=x_cnt&&x_cnt<=623)
begin
vga_r=8'b00000000;
vga_g=8'b00000000;
vga_b=8'b11111111;
end
else if(624<=x_cnt&&x_cnt<=703)
begin
vga_r=8'b00000000;
vga_g=8'b00000000;
vga_b=8'b00000000;
end
else if(704<=x_cnt&&x_cnt<=783)
begin
vga_r=8'b11111111;
vga_g=8'b11111111;
vga_b=8'b11111111;
end
else
begin
vga_r=8'b11111111;
vga_g=8'b11111111;
vga_b=8'b11111111;
end
endmodule