今天花了半天的时间把VGA做出来了,800*600液晶显示器,非常的完美。
先跟大家分享一个网站,这个网站上列举了基本上所有VGA显示器的时序。个人觉得做的非常好,有兴趣的同学可以挑一个自己仔细研究下,做好了一个,其他的应该问题不好。
附件是整个工程代码,我用的工具是Quartus 9.1版本
网站 : http://www.tinyvga.com/vga-timing
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
我把我的代码也贴出来和大家分享,嘿嘿,直接上……
顶层模块 vga800_600.v
`timescale 1ns / 1ps
module vga800_600 (
clk,rst_n,
hsync,vsync,
vga_r,vga_g,vga_b
);
input clk; //FPAG输入时钟信号20MHz
input rst_n; //FPGA输入复位信号,低电平有效
// FPGA与VGA接口信号
output hsync; //行同步信号
output vsync; //场同步信号
output vga_r;
output vga_g;
output vga_b;
wire clk_<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />40M; //pll倍频产生的40Mhz的时钟
wire sys_rst_n; //和pll同步后的系统复位,低电平有效
// 坐标计数
reg[10:0] x_cnt; //行坐标
reg[10:0] y_cnt; //列坐标
/*
VGA Signal 800 x 600 @ 60 Hz timing
General timing
Screen refresh rate 60 Hz
Vertical refresh 37.878787878788 kHz
Pixel freq. 40.0 MHz
Horizontal :
______________ _____________
| | |
_______________| VIDEO |_______________| VIDEO
___________ _____________________ ______________________ --hsync_r
|_| |_|
B C <------D------> <-E-->
<----------A--------------->
Horizontal timing (line)
Polarity of horizontal sync pulse is positive.
Scanline part Pixels Time [μs]
Sync pulse 128 3.2 ----B 同步脉冲
Back porch 88 2.2 ----C 后沿
Visible area 800 20 ----D 显示区域
Front porch 40 1 ----E 前沿
Whole line 1056 26.4 ----A 一行
x_cnt 0~127 hsync_r = 1'b0;
x_cnt 128~1055 hsync_r = 1'b1;
Vertical :
______________ _____________
| | |
_______________| VIDEO |_______________| VIDEO
___________ _____________________ ______________________ --vsync_r
|_| |_|
P Q <--------R-----><-S->
<-------------O------------>
Vertical timing (frame)
Polarity of vertical sync pulse is positive.
Scanline part Pixels Time [ms]
Sync pulse 4 0.1056 ----P 同步脉冲
Back porch 23 0.6072 ----Q 后沿
Visible area 600 15.84 ----R 显示区域
Front porch 1 0.0264 ----S 前沿
Whole frame 628 16.5792 ----O 一场
y_cnt 0~3 vsync_r = 1'b0;
y_cnt 4~627 vsync_r = 1'b1;
*/
always @ (posedge clk_40M or negedge sys_rst_n)
if(!sys_rst_n)
x_cnt <= 11'd0;
else if(x_cnt >= 11'd1055) //Whole line 1056 26.4us
x_cnt <= 11'd0;
else
x_cnt <= x_cnt + 1'b1;
always @ (posedge clk_40M or negedge sys_rst_n)
if(!sys_rst_n)
y_cnt <= 11'd0;
else if(y_cnt >= 11'd627) //Whole frame 628 16.5792ms
y_cnt <= 11'd0;
else if(x_cnt == 11'd1055)
y_cnt <= y_cnt + 1'b1;
reg hsync_r; //行同步信号寄存器
reg vsync_r; //场同步信号寄存器
always @ (posedge clk_40M or negedge sys_rst_n)
if(!sys_rst_n)
hsync_r <= 1'b1;
else if(x_cnt == 11'd0 || x_cnt <= 11'd127)
hsync_r <= 1'b0;
else if(x_cnt >= 11'd128)
hsync_r <= 1'b1;
always @ (posedge clk_40M or negedge sys_rst_n)
if(!sys_rst_n)
vsync_r <= 1'b1;
else if(y_cnt == 11'd0 || y_cnt <= 11'd3)
vsync_r <= 1'b0;
else if(y_cnt >= 11'd4)
vsync_r <= 1'b1;
assign hsync = hsync_r;
assign vsync = vsync_r;
wire valid; //800*600的有效显示区域
assign valid = (x_cnt >11'd215) && (x_cnt <= 11'd1015)
&& (y_cnt > 11'd26) && (y_cnt <= 11'd626);
/*
// VGA色彩信号产生
RGB = 000 黑色 RGB = 100 红色
= 001 蓝色 = 101 紫色
= 010 绿色 = 110 黄色
= 011 青色 = 111 白色
*/
//我显示的是全黄色
assign vga_r = valid ? 1'b1 : 1'b0;
assign vga_g = valid ? 1'b1 : 1'b0;
assign vga_b = valid ? 1'b0 : 1'b0;
sys_ctrl U1(
.clk(clk),
.rst_n(rst_n),
.sys_rst_n(sys_rst_n),
.clk_40M(clk_40M)
);
endmodule
系统复位处理和pll实例化模块 sys_rst.v(学习特权同学的复位处理)
`timescale 1ns / 1ps
module sys_ctrl(
clk,rst_n,
sys_rst_n,clk_40M
);
input clk; //FPAG输入时钟信号20MHz
input rst_n; //FPGA输入复位信号
output sys_rst_n; //系统复位信号,低有效
output clk_40M; //PLL输出40MHz时钟
wire locked; //PLL输出有效标志位,高表示PLL输出有效
//----------------------------------------------
//PLL复位信号产生,高有效
//异步复位,同步释放
wire pll_rst; //PLL复位信号,高有效
reg rst_reg1,rst_reg2;
always @(posedge clk or negedge rst_n)
if(!rst_n)
rst_reg1 <= 1'b1;
else
rst_reg1 <= 1'b0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
rst_reg2 <= 1'b1;
else
rst_reg2 <= rst_reg1;
assign pll_rst = rst_reg2;
//----------------------------------------------
//系统复位信号产生,低有效
//异步复位,同步释放
wire sys_rst_n; //系统复位信号,低有效
wire sysrst_nr0;
reg sysrst_nr1,sysrst_nr2;
assign sysrst_nr0 = rst_n & locked; //系统复位直到PLL有效输出
always @(posedge clk_40M or negedge sysrst_nr0)
if(!sysrst_nr0) sysrst_nr1 <= 1'b0;
else sysrst_nr1 <= 1'b1;
always @(posedge clk_40M or negedge sysrst_nr0)
if(!sysrst_nr0) sysrst_nr2 <= 1'b0;
else sysrst_nr2 <= sysrst_nr1;
assign sys_rst_n = sysrst_nr2;
//例化PLL产生模块
pll_ctrl U2(
.areset(pll_rst), //PLL复位信号,高电平复位
.inclk0(clk), //PLL输入时钟,20MHz
.c0(clk_40M), //PLL输出60MHz时钟
.locked(locked) //PLL输出有效标志位,高表示PLL输出有效
);
endmodule
还有一个模块就是 调用PLL ip核。 中间的很多注释实际上就是从我前面提到的网站上面cope下来的,然后加了个图,希望能更加直观的给大家信息。有什么地方错了,请大家指教,一起学习,嘿嘿
用户1722030 2013-11-19 22:58
用户383871 2011-9-14 10:24
用户1632924 2010-6-11 13:45
用户1526653 2010-5-29 22:34
用户276169 2010-5-29 15:20