1.了解VGA的大致时序
2.Verilog设计模块
3.时钟产生--使用Clocking IP核
根据不同的屏幕、刷新速率,产生对应所需的时钟
4.TFT显示时序控制模块
A.行和场计数器
B.rgb_valid(有效请求信号)
`timescale 1ns / 1ps
module tft_ctrl(
Clk33_3M,//输入时钟,频率
Reset_n,
pix_data,
pix_x,
pix_y,
rgb_tft,
hsync,
vsync,
tft_clk,
tft_de,
tft_bl
);
input Clk33_3M;//输入时钟,频率
input Reset_n;//复位信号
input [15:0] pix_data;//待显示数据
output [9:0] pix_x; //有效显示区像素点x轴坐标
output [9:0] pix_y; //有效显示区像素点y轴坐标
output [15:0] rgb_tft;//TFT显示数据
output hsync; //行同步信号
output vsync; //场同步信号
output tft_clk; //像素时钟
output tft_de; //数据使能信号
output tft_bl; //TFT背光信号
//行扫描——参数定义 parameter define
parameter H_SYNC = 10'd128,//行同步信号
H_BACK = 10'd88,//行时序后沿
H_VALID = 10'd800,//行有效
H_FRONT = 10'd40,//行前沿
H_TOTAL = 11'd1056;//行扫描周期
//场扫描——参数定义 parameter define
parameter V_SYNC = 10'd2, //场同步信号
V_BACK = 10'd33, //场时序后沿
V_VALID = 10'd480, //场有效
V_FRONT = 10'd10, //场前沿
V_TOTAL = 11'd525;//场扫描周期
//wire define
wire rgb_valid;//VGA有效显示区域
wire pix_data_req;//像素点色彩信息请求信号
//tft_clk,tft_de,tft_bl:TFT像素时钟、数据使能、背光信号
assign tft_clk = Clk33_3M ;
assign tft_de = rgb_valid ;
assign tft_bl = Reset_n ;
//reg define
reg [12:0]cnt_h; //行扫描计数器
reg [12:0]cnt_v; //场扫描计数器
//cnt_h:行同步信号计数器
always@(posedge Clk33_3M or negedge Reset_n)
if(!Reset_n)
cnt_h <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_h <= 10'd0 ;
else
cnt_h <= cnt_h + 1'd1 ;
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//cnt_v:场同步信号计数器
always@(posedge Clk33_3M or negedge Reset_n)
if(!Reset_n)
cnt_v <= 10'd0 ;
else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
cnt_v <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_v <= cnt_v + 1'd1 ;
else
cnt_v <= cnt_v ;
//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//rgb_valid:VGA有效显示区域
assign rgb_valid = (((cnt_h >= H_SYNC + H_BACK)
&& (cnt_h < H_SYNC + H_BACK + H_VALID))
&&((cnt_v >= V_SYNC + V_BACK)
&& (cnt_v < V_SYNC + V_BACK + V_VALID)))
? 1'b1 : 1'b0;
//pix_data_req:像素点色彩信息请求信号,超前rgb_valid信号一个时钟周期
assign pix_data_req = (((cnt_h >= H_SYNC + H_BACK - 1'b1)
&& (cnt_h < H_SYNC + H_BACK + H_VALID - 1'b1))
&&((cnt_v >= V_SYNC + V_BACK)
&& (cnt_v < V_SYNC + V_BACK + V_VALID)))
? 1'b1 : 1'b0;
//pix_x,pix_y:VGA有效显示区域像素点坐标
assign pix_x = (pix_data_req == 1'b1)
? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 10'h3ff;
assign pix_y = (pix_data_req == 1'b1)
? (cnt_v - (V_SYNC + V_BACK )) : 10'h3ff;
//rgb_tft:输出像素点色彩信息
assign rgb_tft = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;
endmodule
`timescale 1ns / 1ps
module tft_ctrl_tb();
reg Clk; //系统时钟
wire Clk33_3M;//输入时钟,频率
reg Reset_n;//复位信号
wire tft_reset_n;
reg [15:0] pix_data;//待显示数据
wire [9:0] pix_x; //有效显示区像素点x轴坐标
wire [9:0] pix_y; //有效显示区像素点y轴坐标
wire [15:0] rgb_tft;//TFT显示数据
wire hsync; //行同步信号
wire vsync; //场同步信号
wire tft_clk; //像素时钟
wire tft_de; //数据使能信号
wire tft_bl; //TFT背光信号
wire locked ;
clk_gen_0 clk_gen_0_inst0
(
.clk_in1(Clk),
.reset(!Reset_n),
.tft_clock(Clk33_3M),
.locked(locked)
);
tft_ctrl tft_ctrl_inst0(
.Clk33_3M(Clk33_3M),//输入时钟,频率
.Reset_n(Reset_n),
.pix_data(pix_data),
.pix_x(pix_x),
.pix_y(pix_y),
.rgb_tft(rgb_tft),
.hsync(hsync),
.vsync(vsync),
.tft_clk(tft_clk),
.tft_de(tft_de),
.tft_bl(tft_bl)
);
//rst_n:VGA模块复位信号
assign tft_reset_n = (Reset_n & locked);
//产生时钟
initial Clk = 1;
always #10 Clk = ~Clk;
//pix_data:输入像素点色彩信息
always@(posedge Clk33_3M or negedge Reset_n)
if(!Reset_n)
pix_data <= 16'h0;
else
pix_data <= 16'hffff;
initial begin
Reset_n = 0;
#300;
Reset_n = 1;
#2000_000;
end
endmodule
5.图像数据生成模块
`timescale 1ns / 1ps
module tft_pic(
Clk33_3M,//输入时钟,频率
Reset_n,
pix_x,
pix_y,
pix_data
);
input Clk33_3M;//输入时钟,频率
input Reset_n;
input [9:0]pix_x;
input [9:0]pix_y;
output reg[15:0]pix_data;
parameter H_VALID = 10'd800;//行有效数据
parameter V_VALID = 10'd480;//场有效数据
parameter RED = 16'hF800, //红色
ORANGE = 16'hFC00, //橙色
YELLOW = 16'hFFE0, //黄色
GREEN = 16'h07E0, //绿色
CYAN = 16'h07FF, //青色
BLUE = 16'h001F, //蓝色
PURPPLE = 16'hF81F, //紫色
BLACK = 16'h0000, //黑色
WHITE = 16'hFFFF, //白色
GRAY = 16'hD69A; //灰色
//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge Clk33_3M or negedge Reset_n)
if(!Reset_n)
pix_data <= 16'd0;
else if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
pix_data <= RED;
else if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
pix_data <= ORANGE;
else if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
pix_data <= YELLOW;
else if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
pix_data <= GREEN;
else if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
pix_data <= CYAN;
else if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
pix_data <= BLUE;
else if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
pix_data <= PURPPLE;
else if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
pix_data <= BLACK;
else if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
pix_data <= WHITE;
else if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
pix_data <= GRAY;
else
pix_data <= BLACK;
endmodule
6.顶层模块
`timescale 1ns / 1ps
module TFT800x480_ctrl(
Clk , //输入工作时钟,频率50MHz
Reset_n , //输入复位信号,低电平有效
rgb_tft , //输出像素信息
hsync , //输出行同步信号
vsync , //输出场同步信号
tft_clk , //输出TFT时钟信号
tft_de , //输出TFT使能信号
tft_bl //输出背光信号
);
input Clk;
input Reset_n;
output [15:0]rgb_tft; //输出像素信息
output hsync ;//输出行同步信号
output vsync ;//输出场同步信号
output tft_clk; //输出TFT时钟信号
output tft_de ;//输出TFT使能信号
output tft_bl ;//输出背光信号
//wire define
wire Clk33_3M ; //TFT工作时钟,频率33.3MHz
wire locked ; //PLL locked信号
wire rst_n ; //TFT模块复位信号
wire [9:0] pix_x ; //TFT有效显示区域X轴坐标
wire [9:0] pix_y ; //TFT有效显示区域Y轴坐标
wire [15:0] pix_data ; //TFT像素点色彩信息
//rst_n:TFT模块复位信号
assign rst_n = (Reset_n & locked);
//------------- clk_gen_inst -------------
clk_gen_0 clk_gen_0_inst0
(
.clk_in1(Clk),
.reset(!Reset_n),
.tft_clock(Clk33_3M),
.locked(locked)
);
//------------- tft_ctrl_inst -------------
tft_ctrl tft_ctrl_inst0(
.Clk33_3M(Clk33_3M),//输入时钟,频率
.Reset_n(Reset_n),
.pix_data(pix_data),
.pix_x(pix_x),
.pix_y(pix_y),
.rgb_tft(rgb_tft),
.hsync(hsync),
.vsync(vsync),
.tft_clk(tft_clk),
.tft_de(tft_de),
.tft_bl(tft_bl)
);
//------------- tft_pic_inst -------------
tft_pic tft_pic_inst0(
.Clk33_3M(Clk33_3M),//输入时钟,频率
.Reset_n(Reset_n),
.pix_x(pix_x),
.pix_y(pix_y),
.pix_data(pix_data)
);
endmodule
仿真tb
`timescale 1ns / 1ps
module TFT800x480_ctrl_tb();
reg Clk; //输入工作时钟,频率50MHz
reg Reset_n; //输入复位信号,低电平有效
wire [15:0]rgb_tft; //输出像素信息
wire hsync; //输出行同步信号
wire vsync; //输出场同步信号
wire tft_clk; //输出TFT时钟信号
wire tft_de; //输出TFT使能信号
wire tft_bl; //输出背光信号
TFT800x480_ctrl TFT800x480_ctrl_inst0(
.Clk(Clk), //输入工作时钟,频率50MHz
.Reset_n(Reset_n), //输入复位信号,低电平有效
.rgb_tft(rgb_tft), //输出像素信息
.hsync(hsync), //输出行同步信号
.vsync(vsync), //输出场同步信号
.tft_clk(tft_clk), //输出TFT时钟信号
.tft_de(tft_de), //输出TFT使能信号
.tft_bl(tft_bl) //输出背光信号
);
initial Clk=1;
always#10 Clk = ~Clk;
initial begin
Reset_n = 0;
#210;
Reset_n = 1;
#3000_000_000;
#3000_000_000;
$stop;
end
endmodule