基于FPGA的VGA时序控制器
程序员文章站
2024-02-22 21:26:10
...
VGA时序
VGA 显示器扫描方式从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间, CRT 对电子束进行消隐,每行结束时,用行同步信号进行同步; 当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐, 开始下一帧。完成一行扫描的时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描的时间称为垂直扫描时间,其倒数称为场频率,即刷新一屏的频率,常见的有 60Hz, 75Hz 等等。标准的 VGA 显示的场频 60Hz。时钟频率:以640aaa@qq.com为例,每场对应 525 个行周期,其中 480 为显示行。每显示行包括 800 点时钟,其中 640 点为有效显示区。由此可知:需要点时钟频率: 525800*60= 25.2MHz,约25MHz。
扫描方式
常见VGA时序表
其中:
a:行同步时间,
b:行消隐后沿,
c:行显示有效区域
d:行消隐前沿,
e:行扫描总时间,
o:场同步时间,
p:场消隐后沿,
q:场显示有效区域
r:场消隐前沿,
s:场扫描总时间,
本设计以640*aaa@qq.com为例,因此需要的时钟频率为25MHz,因此需要引入PLL生产25MHz的信号。
VGA时序控制器的Verilog代码
//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
//
// Create Date: 2020/01/20 20:01:50
// Design Name: vga_640_480
// Module Name: vga_640_480
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module vga_640_480(
input clk,//25M
input rst,
output hs,
output vs,
output reg[9:0] h_cnt,//行计数器
output reg[9:0] v_cnt //场计数器
);
//*************************
//行时序(像素数)
localparam a=96;
localparam b=48;
localparam c=640;
localparam d=16;
localparam e=800;
//*************************
//帧时序(行数)
localparam o=2;
localparam p=33;
localparam q=480;
localparam r=10;
localparam s=525;
aaa@qq.com(posedge clk or negedge rst)begin
if(!rst)
h_cnt <= 10'd0;
else
if(h_cnt==e-1)
h_cnt <= 10'd0;
else
h_cnt <= h_cnt + 1'b1;
end
assign hs=(h_cnt<a-1)?1'b0:1'b1;
aaa@qq.com(posedge clk or negedge rst)begin
if(!rst)
v_cnt <= 10'd0;
else
if(v_cnt==s-1)
v_cnt <= 10'd0;
else
if(h_cnt==e-1)
v_cnt <= v_cnt + 1'b1;
else
v_cnt <= v_cnt;
end
assign vs=(v_cnt<o-1)?1'b0:1'b1;
endmodule
仿真文件Verilog代码
由于跑完一帧显示需要约18,000,000ns,因此只做部分过程的仿真
`timescale 1ns/1ps
`define clock_period 40
module vga_640_480_tb;
reg clk_25m;
reg rst;
wire hs;
wire vs;
wire[9:0] h_cnt;
wire[9:0] v_cnt;
vga_640_480 vga(
.clk (clk_25m),//25M
.rst (rst),
.hs (hs),
.vs (vs),
.h_cnt(h_cnt),//行计数器
.v_cnt(v_cnt) //场计数器
);
initial clk_25m=1;
always#(`clock_period/2)clk_25m=~clk_25m;
initial begin
rst=0;
#200;
rst=1;
#(300000);
$stop;
end
endmodule