源文件
`timescale 1ns / 1ps
module VGA_CTRL(
Clk, //时钟
Reset_n, //复位
Data, //存储三原色的数据,由用户输入
Data_Req, //数据请求,解决RGB滞后Data的问题
X, //像素点的横坐标,范围0~640
Y, //像素点的纵坐标,范围0~480
VGA_HS, //行同步
VGA_VS, //场同步
VGA_BLK, //数据有效控制位,高电平有效
VGA_RGB //三原色
);
input Clk;
input Reset_n;
input[23:0] Data;
output reg Data_Req;
output reg [9:0] X;
output reg [8:0] Y;
output reg VGA_HS;
output reg VGA_VS;
output reg VGA_BLK;
output reg [23:0] VGA_RGB;
//各个信号和数据的变化时间节点,640*480
localparam HS_Begin = 0; //行同步脉冲的开始位置
localparam HS_End = 96; //行同步脉冲的结束位置
localparam Hdat_Begin = 96 + 40 + 8; //行数据开始输出的位置
localparam Hdat_End = 96 + 40 + 8 + 640; //行数据停止输出的位置
localparam Hsync_End = 96 + 40 + 8 + 640 + 8 + 8; //行同步信号的结束位置
localparam VS_Begin = 0; //场同步脉冲的开始位置
localparam VS_End = 2; //场同步脉冲的结束位置
localparam Vdat_Begin = 2 + 25 + 8; //场数据开始输出的位置
localparam Vdat_End = 2 + 25 + 8 + 480; //场数据停止输出的位置
localparam Vsync_End = 2 + 25 + 8 + 480 + 2 + 8; //场同步信号的结束位置
//定义颜色编码
localparam Black = 24'h00_00_00, //黑色
Blue = 24'h00_00_FF, //蓝色
Green = 24'h00_FF_00, //绿色
Cyan = 24'h00_FF_FF, //青色
Red = 24'hFF_00_00, //红色
Purpple = 24'hFF_00_FF, //紫色
Yellow = 24'hFF_FF_00, //黄色
White = 24'hFF_FF_FF; //白色
reg [9:0] HS_Cnt; //行时钟计数器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
HS_Cnt <= 0;
else if(HS_Cnt == Hsync_End - 1)
HS_Cnt <= 0;
else
HS_Cnt <= HS_Cnt + 1'b1;
reg [9:0] VS_Cnt; //场时钟计数器
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
VS_Cnt <= 0;
else if(HS_Cnt == Hsync_End - 1) //如果行扫描完成
begin
if(VS_Cnt >= Vsync_End - 1) //如果场扫描完成
VS_Cnt <= 0;
else
VS_Cnt <= VS_Cnt + 1'b1;
end
else
VS_Cnt <= VS_Cnt;
// 组合逻辑
// assign VGA_HS = (HS_Cnt < HS_End - 1'b1)?0:1; //模仿时序
// assign VGA_VS <= (VS_Cnt < Vsync_End - 1'b1)?0:1; //模仿时序
// assign VGA_BLK <= ((HS_Cnt >= Hdat_Begin) && (HS_Cnt <= Hdat_End) && (VS_Cnt >= Vdat_Begin) && (VS_Cnt <= Vdat_End))?1:0; //就是图像的矩形区域
// assign VGA_RGB <= VGA_BLK? Data:0; //如果在图像矩形区域,就将用户的三原色数据给到 VGA_RGB;
// 时序逻辑
always@(posedge Clk)
VGA_HS = (HS_Cnt <= HS_End - 1'b1)?0:1;
always@(posedge Clk)
VGA_VS <= (VS_Cnt <= VS_End - 1'b1)?0:1;
//BLK表示的就是输出 输出(三原色)的时间段 ,高电平有效
always@(posedge Clk)
Data_Req <= ((HS_Cnt >= Hdat_Begin) && (HS_Cnt < Hdat_End) && (VS_Cnt >= Vdat_Begin) && (VS_Cnt < Vdat_End))?1:0; //解决RGB滞后Data的问题
always@(posedge Clk)
VGA_BLK <= Data_Req;
//RGB值由外界输入,且整个屏幕显示
// always@(posedge Clk)
// VGA_RGB <= Data_Req? Data:0;
//计算像素点的坐标
always@(posedge Clk)
X <= Data_Req? (HS_Cnt - Hdat_Begin - 1) : 0;
always@(posedge Clk)
Y <= Data_Req? (VS_Cnt - Vdat_Begin) : 0;
// 划分矩形区域,并在想要的区域填充想要的RGB值
always@(posedge Clk)
if((X >= 0) && (X < 320) && (Y >= 0) && (Y < 120))
VGA_RGB <= Black;
else if((X >= 0) && (X < 320) && (Y >= 120) && (Y < 240))
VGA_RGB <= Blue;
else if((X >= 0) && (X < 320) && (Y >= 240) && (Y < 360))
VGA_RGB <= Green;
else if((X >= 0) && (X < 320) && (Y >= 360) && (Y < 480))
VGA_RGB <= Cyan;
else if((X >= 320) && (X < 320) && (Y >= 0) && (Y < 120))
VGA_RGB <= Red;
else if((X >= 320) && (X < 320) && (Y >= 120) && (Y < 240))
VGA_RGB <= Purpple;
else if((X >= 320) && (X < 320) && (Y >= 240) && (Y < 360))
VGA_RGB <= Yellow;
else if((X >= 320) && (X < 320) && (Y >= 360) && (Y < 480))
VGA_RGB <= White;
endmodule
仿真文件
`timescale 1ns / 1ps
module VGA_CTRL_tb;
reg Clk;
reg Reset_n;
reg[23:0] Data;
wire Data_Req;
wire [9:0] X;
wire [8:0] Y;
wire VGA_HS;
wire VGA_VS;
wire VGA_BLK;
wire [23:0] VGA_RGB;
VGA_CTRL VGA_CTRL_inst(
.Clk(Clk), //时钟
.Reset_n(Reset_n), //复位
.Data(Data), //存储三原色的数据,由用户输入
.Data_Req(Data_Req),
.X(X),
.Y(Y),
.VGA_HS(VGA_HS), //行同步
.VGA_VS(VGA_VS), //场同步
.VGA_BLK(VGA_BLK), //数据有效控制位,高电平有效
.VGA_RGB(VGA_RGB) //三原色
);
initial Clk = 1;
always #20 Clk = ~Clk;
initial
begin
Reset_n = 0;
#201;
Reset_n = 1;
#2000000;
$stop;
end
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Data <= 0;
else if(!Data_Req)
Data <= Data;
else
Data <= Data + 1'd1;
endmodule