(1)RGB-TFT-LCD简介
TFT-LCD的全称是Thin Film Transistor-Liquid Crystal Display,即薄膜晶体管液晶显示屏,它显示的每个像素点都是由集成在液晶后面的薄膜晶体管独立驱动的,因此TFT-LCD具有较高的响应速度以及较好的图像质量。
与VGA不同,TFT-LCD直接接收数字信号,并能够支持不同的接口类型,如RGB接口、Intel8080接口等。本章我们将使ALIENTEK推出的一款7寸RGB接口TFT液晶显示屏模块(以下简介ATK-7’RGBLCD模块)为例,介绍RGB LCD的使用方法。
ATK-7’RGBLCD模块采用群创光电的7寸LCD液晶屏AT070TN92,分辨率为800*480,采用RGB888格式的数据接口(也可使用RGB565格式)。下面是AT070TN92输入数据的时序图:
AT070TN92液晶屏的输入数据有两种同步方式,分别为行场同步模式(HV Mode)和数据使能同步模式(DE Mode),可通过MODE引脚进行选择。AT070TN92的数据手册指出,当MODE引脚拉高时,选择DE同步模式,此时行场同步信号VS和HS必须为高电平;当MODE引脚拉低时,选择HV同步模式,此时数据使能信号DE必须为低电平。
(2)实验任务
本节任务是使用开发板上的RGB TFT-LCD接口在7寸RGB LCD液晶屏模块(分辨率为800*480)上显示彩条。其它尺寸和分辨率的RGB LCD模块,只需要在此基础上稍作修改。
(3)硬件设计
FPGA管脚输出的颜色数据位宽为16bit,数据格式为RGB565,即数据高5位表示红色,中间6位表示绿色,低5位表示蓝色。另外,RGBLCD模块支持触摸功能,图中以字母T开头的5个信号(T_PEN、T_SCK等)与模块上的触摸芯片相连接。由于本次实验不涉及触摸功能的实现,因此这些信号并未用到。
(4)程序设计
RGB TFT-LCD输入时序包含三个要素:像素时钟、同步信号、以及图像数据,其中,时钟分频模块负责产生像素时钟,LCD驱动模块产生同步信号,LCD显示模块输出图像数据。
FPGA需要四个模块。顶层模块(lcd_rgb_colorbar)、时钟分频模块(lcd_pll)、LCD显示模块(lcd_display)以及LCD驱动模块(lcd_driver)。其中在顶层模块中完成对另外三个模块的例化。
代码:
module vga_driver(
input lcd_clk, //lcd模块驱动时钟
input sys_rst_n, //复位信号
//RGB LCD接口
output lcd_hs, //LCD 行同步信号
output lcd_vs, //LCD 场同步信号
output lcd_de, //LCD 数据使能
output [15:0] lcd_rgb, //LCD RGB565颜色数据
output lcd_bl, //LCD 背光控制信号
output lcd_rst, //LCD 复位信号
output lcd_pclk, //LCD 采样时钟
input [15:0] pixel_data, //像素点数据
output [10:0] pixel_xpos, //像素点横坐标
output [10:0] pixel_ypos //像素点纵坐标
);
//parameter define
parameter H_SYNC = 11'd128; //行同步
parameter H_BACK = 11'd88; //行显示后沿
parameter H_DISP = 11'd800; //行有效数据
parameter H_FRONT = 11'd40; //行显示前沿
parameter H_TOTAL = 11'd1056; //行扫描周期
parameter V_SYNC = 11'd2; //场同步
parameter V_BACK = 11'd33; //场显示后沿
parameter V_DISP = 11'd480; //场有效数据
parameter V_FRONT = 11'd10; //场显示前沿
parameter V_TOTAL = 11'd525; //场扫描周期
//reg define
reg [10:0] cnt_h;
reg [10:0] cnt_v;
//wire define
wire lcd_en;
wire data_req;
//*****************************************************
//** main code
//*****************************************************
assign lcd_bl = 1'b1; //RGB LCD显示模块背光控制信号
assign lcd_rst = 1'b1; //RGB LCD显示模块系统复位信号
assign lcd_pclk = lcd_clk; //RGB LCD显示模块采样时钟
assign lcd_de = lcd_en; //LCD输入的颜色数据采用数据输入使能信号同步
assign lcd_hs = 1'b1; //RGB LCD 采用数据输入使能信号同步时,
assign lcd_vs = 1'b1; //行场同步信号需要拉高
//使能RGB565数据输出
assign lcd_en = (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))
&&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
? 1'b1 : 1'b0;
//RGB565数据输出
assign lcd_rgb = lcd_en ? pixel_data : 16'd0;
//请求像素点颜色数据输入
assign data_req = (((cnt_h >= H_SYNC+H_BACK-1'b1) && (cnt_h < H_SYNC+H_BACK+H_DISP-1'b1))
&& ((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
? 1'b1 : 1'b0;
//像素点坐标
assign pixel_xpos = data_req ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 11'd0;
assign pixel_ypos = data_req ? (cnt_v - (V_SYNC + V_BACK - 1'b1)) : 11'd0;
//行计数器对像素时钟计数
always @(posedge lcd_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
cnt_h <= 11'd0;
else begin
if(cnt_h < H_TOTAL - 1'b1)
cnt_h <= cnt_h + 1'b1;
else
cnt_h <= 11'd0;
end
end
//场计数器对行计数
always @(posedge lcd_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
cnt_v <= 11'd0;
else if(cnt_h == H_TOTAL - 1'b1) begin
if(cnt_v < V_TOTAL - 1'b1)
cnt_v <= cnt_v + 1'b1;
else
cnt_v <= 11'd0;
end
end
endmodule
module vga_display(
input vga_clk, //VGA驱动时钟
input sys_rst_n, //复位信号
input [10:0] pixel_xpos, //像素点横坐标
input [10:0] pixel_ypos, //像素点纵坐标
output reg [15:0] pixel_data //像素点数据
);
parameter H_DISP = 10'd500; //分辨率——行
parameter V_DISP = 10'd480; //分辨率——列
localparam WHITE = 16'b11111_111111_11111; //RGB565 白色
localparam BLACK = 16'b00000_000000_00000; //RGB565 黑色
localparam RED = 16'b11111_000000_00000; //RGB565 红色
localparam GREEN = 16'b00000_111111_00000; //RGB565 绿色
localparam BLUE = 16'b00000_000000_11111; //RGB565 蓝色
//*****************************************************
//** main code
//*****************************************************
//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
always @(posedge vga_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
pixel_data <= 16'd0;
else begin
if((pixel_xpos >= 0) && (pixel_xpos <= (H_DISP/10)*1)
|| (pixel_xpos >= (H_DISP/10)*5) && (pixel_xpos < (H_DISP/10)*6)
)
pixel_data <= WHITE;
else if((pixel_xpos >= (H_DISP/10)*1) && (pixel_xpos < (H_DISP/10)*2)
|| (pixel_xpos >= (H_DISP/10)*6) && (pixel_xpos < (H_DISP/10)*7)
)
pixel_data <= BLACK;
else if((pixel_xpos >= (H_DISP/10)*2) && (pixel_xpos < (H_DISP/10)*3)
|| (pixel_xpos >= (H_DISP/10)*7) && (pixel_xpos < (H_DISP/10)*8)
)
pixel_data <= RED;
else if((pixel_xpos >= (H_DISP/10)*3) && (pixel_xpos < (H_DISP/10)*4)
|| (pixel_xpos >= (H_DISP/10)*8) && (pixel_xpos < (H_DISP/10)*9)
)
pixel_data <= GREEN;
else if((pixel_xpos >= (H_DISP/10)*4) && (pixel_xpos < (H_DISP/10)*5)
|| (pixel_xpos >= (H_DISP/10)*9) && (pixel_xpos < (H_DISP/10)*10)
)
pixel_data <= BLUE;
end
end
////根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
//always @(posedge vga_clk or negedge sys_rst_n) begin
// if (!sys_rst_n)
// pixel_data <= 16'd0;
// else begin
// if((pixel_xpos >= 0) && (pixel_xpos < (H_DISP/5)*1))
// pixel_data <= WHITE;
// else if((pixel_xpos >= (H_DISP/5)*1) && (pixel_xpos < (H_DISP/5)*2))
// pixel_data <= BLACK;
// else if((pixel_xpos >= (H_DISP/5)*2) && (pixel_xpos < (H_DISP/5)*3))
// pixel_data <= RED;
// else if((pixel_xpos >= (H_DISP/5)*3) && (pixel_xpos < (H_DISP/5)*4))
// pixel_data <= GREEN;
// else
// pixel_data <= BLUE;
// end
//end
endmodule
信号连接图:
(5)下载验证: