TFT_LCD 字符显示
第43章、TFT_LCD 字符显示
【实战】
实验目标:在TFT显示屏中心位置显示金色“野火科技”四个汉字,字符外的背景颜色为黑色。每个汉字大小为56*56,字模点阵为64*64(4个汉字大小 256*64),TFT显示屏显示模式为480*270@60。
【图像数据生成模块(tft_pic)】
本模块的目的是,以TFT时序控制模块传入的图像有效显示区域像素点坐标(pix_x,pix_y)为约束条件,产生图像像素点色彩信息pix_data并回传给TFT时序控制模块。在字符显示区域pi_data赋值为金色,其他区域均为黑色。
第一部分:字符点阵显示区域坐标信号
利用 取模软件 生成了要显示字符的 字模,字模点阵的大小为 256*64 :
(1)确定字符有效显示区域,区域大小与字符点阵大小相同,显示区域的像素点与字模点阵中数据项一一对应,当字模点阵中的数据项数值为“1”时,赋值字符颜色给对应像素点;当字模点阵中的数据项数值为“0”时,赋值点阵背景颜色给对应像素
(2)声明char_x、char_y,两变量组成字符点阵显示区域坐标,在字符点阵有效显示区域内,char_x信号0-255循环计数,char_y信号0-63循环计数 ,根据坐标(char_x,char_y)寻找字符点阵对应的数据项,根据数据项的数值,赋予对应坐标像素点颜色信息。
第二部分:输出图像数据信号
本模块的目的是生成图像像素点色彩信息回传给TFT_LCD时序控制模块,声明像素点色彩信息pix_data信号。在字符点阵显示区域内、字符点阵数据项数值为“1”时, pix_data赋值为字符颜色;其他区域均赋值为背景色。因为pix_data的赋值条件超前图像显示区域一个时钟周期、且采用时序逻辑的赋值方式,pix_data与字符显示有效区域保持同步。
module tft_pic( input tft_clk_9m , input tft_rst_n , input [9:0] pix_x ,//表示坐标位置,0-640,需要10位 input [9:0] pix_y ,
output reg [15:0] pix_data //rgb565 共10位
);
//----------------参数定义------------//
//1.定义字符显示区域的顶点坐标
parameter CHAR_VALID_LEFT = 10'd112 ,
CHAR_VALID_RIGHT = 10'd368 ,
CHAR_VALID_TOP = 10'd81 ,
CHAR_VALID_BUTTOM = 10'd145 ;//2.定义显示颜色
parameter BLACK = 16'h0000 ,
GOLDRN = 16'hFEC0 ;//----------------字符显示区域坐标 char_x、char_y------------//
//确定char_x、char_y:pix_x、pix_y在vga_ctrl模块由h_cnt、v_cnt确定,表示了 640 范围内的坐标
wire [9:0] char_x ;
wire [9:0] char_y ;
assign char_x = ( ((pix_x >= CHAR_VALID_LEFT) && ( pix_x < CHAR_VALID_RIGHT ))
&& ((pix_y >= CHAR_VALID_TOP) && ( pix_y < CHAR_VALID_BUTTOM )) )? (pix_x - CHAR_VALID_LEFT) : 10'h3ff ,
char_y = ( ((pix_x >= CHAR_VALID_LEFT) && ( pix_x < CHAR_VALID_RIGHT ))
&& ((pix_y >= CHAR_VALID_TOP) && ( pix_y < CHAR_VALID_BUTTOM )) ) ? (pix_y - CHAR_VALID_TOP) : 10'h3ff ;//----------------加载字符数据------------//
//加载字符数据流:字符分辨率为 64*256,则字符取模软件生成的数据流共 64行256列,相应位置为0则表示无颜色表示,不为零则为金色,需要定义多维变量存储
reg [255:0] char [63:0] ;//char变量,数据深度 64个,每个数据位宽 256位
always@(posedge tft_clk_9m or negedge tft_rst_n)begin
char[0] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[1] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[2] <= 256'h0000000000000000000000200000000000000020000000000000000000000000;
char[3] <= 256'h0000000000000000000000380000000000000038000000000000000000000000;
char[4] <= 256'h00000000000000000000007E000000000000003E000000000000000000080000;
char[5] <= 256'h00000000000000000000007C000000000000003C0000000000000000001C0000;
char[6] <= 256'h0000000000000000000000F800000000000000380000000000000000003E0000;
char[7] <= 256'h0000000000000000000000FC000000000000003800018000003FFFFFFFFF0000;
char[8] <= 256'h0000000000000000000001E600000000000000380003C00000100000007F0000;
char[9] <= 256'h0000000000000000000001E200000000000000380007E0000000000000F80000;
char[10] <= 256'h0000000000000000000003C30000000007FFFFFFFFFFF0000000000003E00000;
char[11] <= 256'h0000000000000000000003C180000000000003F9000000000000000007800000;
char[12] <= 256'h000000000000000000000781C0000000000007F900000000000000000E000000;
char[13] <= 256'h000000000000000000000F00E0000000000007B9800000000000000018000000;
char[14] <= 256'h000000000000000000000E007000000000000F38C00000000000000070000000;
char[15] <= 256'h000000000000000000001E003800000000001E386000000000000000C0000000;
char[16] <= 256'h000000000000000000003C003C00000000003C38700000000000001180000000;
char[17] <= 256'h0000000000000000000078001E00000000007838380000000000001A00000000;
char[18] <= 256'h0000000000000000000070200F000000000070381E0000000000001E00000000;
char[19] <= 256'h00000000000000000000E038078000000000E0380F0000000000001F00000000;
char[20] <= 256'h00000000000000000001C03E03E000000003C03807C000000000001C00000000;
char[21] <= 256'h00000000000080000003803C01F800000007803803F000000000001C00008000;
char[22] <= 256'h000000000003C0000007003C00FE0000000F003801FE00000000001C0001C000;
char[23] <= 256'h000000000007E000000E003C007F8000001E003800FFE0000000001C0003E000;
char[24] <= 256'h00000000000FE0000038003C003FF00000380020043FF8000000001C0007F000;
char[25] <= 256'h0FFFFFFFFFFFF0000070003C000FFC0000E000000E0FC0001FFFFFFFFFFFF800;
char[26] <= 256'h040000000000000000C0003C0007C00001C1FFFFFF0780000800001C00000000;
char[27] <= 256'h00000000000000000380003C00018000070000001F8000000000001C00000000;
char[28] <= 256'h00000000000000000E00003C000000001C0000003C0000000000001C00000000;
char[29] <= 256'h00000000000000003800003C0000000000000000700000000000001C00000000;
char[30] <= 256'h00000000000000000000003C0000000000000001C00000000000001C00000000;
char[31] <= 256'h00000000000000000000003C000000000000001B000000000000001C00000000;
char[32] <= 256'h00000000000000000000003C000000000000001E000000000000001C00000000;
char[33] <= 256'h00000000000000000000003C000000000000001F800000000000001C00000000;
char[34] <= 256'h00000000000000000000003C000000000000001E000180000000001C00000000;
char[35] <= 256'h00000000000000000000003C000000000000001C0003C0000000001C00000000;
char[36] <= 256'h00000000000000000000003C000000000000001C0007E0000000001C00000000;
char[37] <= 256'h00000000000000000000003C000000000FFFFFFFFFFFF0000000001C00000000;
char[38] <= 256'h00000000000000000000003C000000000400001C000000000000001C00000000;
char[39] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[40] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[41] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[42] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[43] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[44] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[45] <= 256'h00000000000000000000003C000000000000001C000000000000001C00000000;
char[46] <= 256'h00000000000000000000003C000000000000001C000000000000003C00000000;
char[47] <= 256'h00000000000000000000003C0000000000001E3C0000000000007FFC00000000;
char[48] <= 256'h00000000000000000000003C0000000000000FFC0000000000001FFC00000000;
char[49] <= 256'h00000000000000000000003C00000000000001FC00000000000003F800000000;
char[50] <= 256'h00000000000000000000003C00000000000000F800000000000001F800000000;
char[51] <= 256'h00000000000000000000003C000000000000007000000000000000E000000000;
char[52] <= 256'h000000000000000000000038000000000000002000000000000000C000000000;
char[53] <= 256'h0000000000000000000000200000000000000000000000000000000000000000;
char[54] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[55] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[56] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[57] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[58] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[59] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[60] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[61] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[62] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
char[63] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
end//----------------图形样式输出 pix_data------------//
//pix_data:根据char_x、char_y确定图像显示的样式
// reg [15:0] pix_data ;
always@(posedge tft_clk_9m or negedge tft_rst_n)begin
if(!tft_rst_n)
pix_data <= BLACK ;
else if( ((pix_x >= CHAR_VALID_LEFT) && ( pix_x < CHAR_VALID_RIGHT ))
&& ((pix_y >= CHAR_VALID_TOP) && ( pix_y < CHAR_VALID_BUTTOM )) //表明在图片显示区域内
&& (char[char_y][10'd255 - char_x]) ) //char_x范围为[0-255] ,[char_y][10'd255 - char_x]:表示了字符坐标位置,
pix_data <= GOLDRN ; //char[char_y][10'd255 - char_x]:表明像素点上是否为0 , 不为0则赋值金色
else
pix_data <= BLACK ;
end
endmodule
【时钟生成模块】
module clk_gen( input sys_clk , input sys_rst_n , output tft_clk_9m , output locked );
clk_9 clk_9_inst01 (
.inclk0 ( sys_clk ),
.areset ( sys_rst_n ),
.c0 ( tft_clk_9m ),
.locked ( locked )
);
endmodule
【时序控制模块】
module tft_ctrl( input tft_clk_9m , input tft_rst_n , input [15:0] pix_data ,//pix_data即显示图像的信息,rgb565模式共16位
output hsync , output vsync , output [8:0] pix_x ,//480*272,9位足够 output [8:0] pix_y , output [15:0] rgb_tft ,//rgb565模式,共16位 output tft_bl , output tft_de , output tft_clk
);
/----------------------------tft扫描参数定义----------------------------------/
//定义行、场信号节点参数:同步、后沿、有效数据、前沿、总周期 (相较于vga、hdmi无边框)
parameter H_SYNC = 10'd41 , //行同步
H_BACK = 10'd2 , //行时序后沿
H_VALID = 10'd480 , //行有效数据
H_FRONT = 10'd2 , //行时序前沿
H_TOTAL = 10'd525 ; //行扫描周期,一个周期525个像素点
parameter V_SYNC = 10'd10 , //场同步
V_BACK = 10'd2 , //场时序后沿
V_VALID = 10'd272 , //场有效数据
V_FRONT = 10'd2 , //场时序前沿
V_TOTAL = 10'd286 ; //场扫描周期,一个周期286/----------------------------行场计数器:h_cnt、v_cnt----------------------------------/
//行、场计数器(h_cnt、v_cnt):用来生成行、场扫描信号,行计数器h_cnt,计数(0-799),共10位
reg [9:0] h_cnt ;
always@(posedge tft_clk_9m or negedge tft_rst_n)begin
if(!tft_rst_n)
h_cnt <= 10'b0 ;
else if(h_cnt == H_TOTAL-1'b1)
h_cnt <= 10'b0 ;
else
h_cnt <= h_cnt + 10'b1 ;
end
reg [9:0] v_cnt ;
always@(posedge tft_clk_9m or negedge tft_rst_n)begin
if(!tft_rst_n)
v_cnt <= 10'b0 ;
else if((v_cnt == V_TOTAL-1'b1) && (h_cnt == H_TOTAL - 1'b1))//计数到整幅图片的最后一个像素
v_cnt <= 10'b0 ;
else if(h_cnt==H_TOTAL - 1'b1)//每当行计数满则向下一行
v_cnt <= v_cnt + 10'b1 ;
else
v_cnt <= v_cnt ;
end/----------------------------1、行场同步信号(hsync、vsync):由计数器确定行、场同步信号hsync、vsync----------------------/
//行、场同步信号(hsync、vsync):只有行、场同步信号为高,其余皆为低 ,表明行场扫描信号的过程/进程
wire hysnc ;
wire vysnc ;
//assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
assign hsync = (h_cnt >= 0) && (h_cnt < 41) ;
assign vsync = (v_cnt >= 0) && (v_cnt < 10) ;/----------------------------2、区域有效标志信号(rgb_valid):计数器确定,680480,底边的大小----------------------------------*/
wire rgb_valid ;
assign rgb_valid = (((h_cnt >= H_SYNC + H_BACK )&&(h_cnt < H_SYNC + H_BACK + H_VALID)) //43-523
&&((v_cnt >= V_SYNC + V_BACK )&&(v_cnt < V_SYNC + V_BACK + V_VALID)));//12-284/---------------------------3、色彩请求信号(pix_data_req):计数器确定,在行扫描信号上超前pic_valid信号一个时钟---------------/
wire pix_data_req ;
assign pix_data_req = (((h_cnt >= H_SYNC + H_BACK - 1'b1 )&&(h_cnt < H_SYNC + H_BACK + H_VALID - 1'b1))
&&((v_cnt >= V_SYNC + V_BACK )&&(v_cnt < V_SYNC + V_BACK + V_VALID)));/-----------------------------4、像素点坐标:请求信号和计数器确定,坐标即距有效显示区域边界的值-----------------------------/
assign pix_x = (pix_data_req == 1'b1)?(h_cnt - H_SYNC - H_BACK -1'b1):9'd511 ;//行场计数器的值计算出相应像素点的坐标位置
assign pix_y = (pix_data_req == 1'b1)?(v_cnt - V_SYNC - V_BACK ) :9'd511 ;//最大值511/-----------------------------5、输出pic_rgb:将vga_pic模块生成的图形样式(pix_data)赋值给pic_rgb,并显示-----------------------------/
assign rgb_tft = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;//tft_clk,tft_de,tft_bl:TFT像素时钟、数据使能、背光信号
assign tft_clk = tft_clk_9m ;
assign tft_de = rgb_valid ;
assign tft_bl = tft_rst_n ;
endmodule
【顶层模块】
module top_tft_colorbar( input sys_clk , input sys_rst_n ,
output hsync , output vsync , output [15:0] rgb , output tft_bl , output tft_clk , output tft_de
);
// wire tft_clk ; wire locked ; wire [8:0] pix_x ; wire [8:0] pix_y ; wire [15:0] pix_data ; wire tft_rst_n ;
assign tft_rst_n = (sys_rst_n && locked);
//25MHZ时钟生成模块
clk_gen clk_gen_inst01(
. sys_clk (sys_clk ) ,
. sys_rst_n (~sys_rst_n ) ,. c0 (tft_clk_9m ) , . locked (locked )
);
//图像样式确定模块
tft_pic tft_pic_inst01(
. tft_clk_9m (tft_clk_9m ) ,
. tft_rst_n (tft_rst_n ) ,
. pix_x (pix_x ) ,
. pix_y (pix_y ) ,. pix_data (pix_data )
);
//vga时序控制模块,输出像素点坐标,并根据图像样式输出行场信号
tft_ctrl tft_ctrl_inst01(
. tft_clk_9m ( tft_clk_9m) ,
. tft_rst_n ( tft_rst_n ) ,
. pix_data ( pix_data ) ,//pix_data即显示图像的信息,rgb565模式共16位. hsync ( hsync ) , . vsync ( vsync ) , . pix_x ( pix_x ) ,//480*272,9位足够 . pix_y ( pix_y ) , . rgb_tft ( rgb ) ,//rgb565模式,共16位 . tft_bl ( tft_bl ) , . tft_de ( tft_de ) , . tft_clk ( tft_clk )
);
endmodule
`timescale 1ns/1ns module tb_top_tft_char(); reg sys_clk ; reg sys_rst_n ;
wire hsync ; wire vsync ; wire [15:0] rgb ; wire tft_bl ; wire tft_clk ; wire tft_de ;
top_tft_char top_tft_char_inst01(
. sys_clk ( sys_clk ) ,
. sys_rst_n ( sys_rst_n) ,. hsync ( hsync ) , . vsync ( vsync ) , . rgb ( rgb ) , . tft_bl ( tft_bl ) , . tft_clk ( tft_clk ) , . tft_de ( tft_de )
);
initial begin
sys_clk = 1'b1 ;
sys_rst_n = 1'b0 ;
#200
sys_rst_n = 1'b1 ;
endalways #10 sys_clk = ~sys_clk ;
endmodule