VGA控制器

这里为640*480分辨率的屏幕设计一个VGA控制器

行扫描过程如下:
在这里插入图片描述
场扫描过程:
在这里插入图片描述

代码如下:

module VGA_TEST (
	input Pclk25M,				//VGA 像素时钟,25MHz
	input Rst_n,		
	input [23:0] data_in,		//待显示数据输入端口
	
	output [9:0] X_addr,		//图像区行扫描地址
	output [9:0] Y_addr,		//图像区场扫描地址
	
	output H_pluse,				//VGA 接口行同步信号
	output V_pluse,				//VGA 接口场同步信号

	output VGA_BLK,				//场消隐信号
	output VGA_CLK,				//VGA 时钟输出
	output [23:0] VGA_RGB		//VGA 三元色数据输出
);

reg [9:0] H_count;
reg [9:0] V_count;

wire data_valid;

//输出数据锁存时钟信号
assign VGA_CLK = ~Pclk25M;	//将VGA控制器时钟信号取反输出,作为DAC数据锁存信号

//行计数器
always @(posedge Pclk25M or negedge Rst_n) begin
	if(!Rst_n)
		H_count <= 0;
	else if(H_count == 10'd799)
		H_count <= 0;
	else
		H_count <= H_count + 1'b1;
end


//场计数器
always @(posedge Pclk25M or negedge Rst_n) begin
	if(!Rst_n)
		V_count <= 0;
	else if(H_count == 10'd799)
		begin
			if(V_count == 10'd524)
				V_count <= 0;
			else
				V_count <= V_count + 1'b1;
		end
	else
		V_count <= V_count;
end


//行使能脉冲结束时间--行同步信号
assign H_pluse = (H_count > 10'd95);


//场使能脉冲结束时间--场同步信号
assign V_pluse = (V_count > 10'd1);


//数据输出有效信号
assign data_valid = 	((H_count > 10'd143) && (H_count < 10'd783)) 
						&& ((V_count > 10'd34) && (V_count > 10'd514));


//场消隐信号
assign VGA_BLK = data_valid;


//信号输出
assign VGA_RGB = data_valid ? data_in : 24'h000000;


//行位置信号
assign X_addr = data_valid ? (H_count - 10'd143) : 10'd0;
//列位置信号
assign Y_addr = data_valid ? (V_count - 10'd34) : 10'd0;

endmodule

接下来对其进行仿真验证,仿真文件如下:

`timescale 1ns/1ns
`define clock_period 40

module VGA_TEST_tb ();

	reg Pclk25M;
	reg Rst_n;		
	reg [23:0] data_in;	
	
	wire [9:0] X_addr;
	wire [9:0] Y_addr
	wire H_pluse;	
	wire V_pluse;	
	wire VGA_BLK;
	wire VGA_CLK;
	wire [23:0] VGA_RGB;

    reg [11:0] V_cnt = 0;


initial Pclk25M = 1;
always #20 Pclk25M = ~Pclk25M;


VGA_TEST VGA_TEST(
	.Pclk25M(Pclk25M),				//VGA 像素时钟,25MHz
	.Rst_n(Rst_n),		
	.data_in(data_in),		        //待显示数据输入端口
	
	.X_addr(X_addr),		        //图像区行扫描地址
	.Y_addr(Y_addr),		        //图像区场扫描地址
	
	.H_pluse(H_pluse),				//VGA 接口行同步信号
	.V_pluse(V_pluse),				//VGA 接口场同步信号

	.VGA_BLK(VGA_BLK),
	.VGA_CLK(VGA_CLK),
	.VGA_RGB(VGA_RGB)		        //VGA 三元色数据输出
);

initial begin
    Rst_n = 0;
    data_in = 0;

    #101;
    Rst_n = 1;
    data_in = 24'hffffff;
end



always @ (posedge V_pluse)
    V_cnt <= V_cnt + 1'b1;
    

initial begin
    wait(V_cnt == 3);
    $stop;
end

endmodule

仿真结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

将代码改写成参数化定义,方便修改分辨率以适配不同尺寸的屏幕

module VGA_TEST (
	input Pclk25M,				//VGA 像素时钟,25MHz
	input Rst_n,		
	input [23:0] data_in,		//待显示数据输入端口
	
	output [9:0] X_addr,		//图像区行扫描地址
	output [9:0] Y_addr,		//图像区场扫描地址
	
	output H_pluse,				//VGA 接口行同步信号
	output V_pluse,				//VGA 接口场同步信号

	output VGA_BLK,
	output VGA_CLK,
	output [23:0] VGA_RGB		//VGA 三元色数据输出
);

reg [9:0] H_count;
reg [9:0] V_count;

wire data_valid;

parameter 	VGA_H_END = 10'd799,	//行分辨率的最大像素值
			VGA_V_END = 10'd524,	//列分辨率的最大像素值

			H_data_start = 10'd143,	//行数据有效开始
			H_data_end = 10'd783,	//行数据有效结束

			V_data_start = 10'd34,	//场数据有效开始
			V_data_end = 10'd514,	//场数据有效结束

			H_pluse_end = 10'd95,	//行同步信号上升沿
			V_pluse_end = 10'd1;	//场同步信号上升沿


//输出数据锁存时钟信号
assign VGA_CLK = ~Pclk25M;	//将VGA控制器时钟信号取反输出,作为DAC数据锁存信号

//行计数器
always @(posedge Pclk25M or negedge Rst_n) begin
	if(!Rst_n)
		H_count <= 0;
	else if(H_count == VGA_H_END)
		H_count <= 0;
	else
		H_count <= H_count + 1'b1;
end


//场计数器
always @(posedge Pclk25M or negedge Rst_n) begin
	if(!Rst_n)
		V_count <= 0;
	else if(H_count == VGA_H_END)
		begin
			if(V_count == VGA_V_END)
				V_count <= 0;
			else
				V_count <= V_count + 1'b1;
		end
	else
		V_count <= V_count;
end


//行使能脉冲结束时间--行同步信号
assign H_pluse = (H_count > H_pluse_end);


//场使能脉冲结束时间--场同步信号
assign V_pluse = (V_count > V_pluse_end);


//数据输出有效信号
assign data_valid = 	((H_count > H_data_start) && (H_count < H_data_end)) 
						&& ((V_count > V_data_start) && (V_count > V_data_end));


//场消隐信号
assign VGA_BLK = data_valid;


//信号输出
assign VGA_RGB = data_valid ? data_in : 24'h000000;


//行位置信号
assign X_addr = data_valid ? (H_count - H_data_start) : 10'd0;
//列位置信号
assign Y_addr = data_valid ? (V_count - V_data_start) : 10'd0;

endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值