主要是复习一下TFT显示,学的三个星期了,都忘了差不多了,再次复习一下
TFT有两种显示模式
1.HV同步模式
2.DE同步模式
上述两种模式很相似,先以HV同步模式讲解
这里的H是指行,V是指场从竖直方向上看。因为屏幕是二维的就是长和宽,在显示一副图片时,屏幕上的二维矩阵像素点被一行一行的点亮,最后完成整幅图片的显示,最小单元是组成行扫描周期的最小周期,像素周期,其可以使得一个像素点点亮与否。在一个完整的行扫描周期中有四部分组成同步,后沿,有效图像,前沿。行就这些东西,下来就是场扫描,一个完整的场扫描周期同样也包含上面四个部分,但是场扫描周期的最小组成单元是行扫描周期。图像的帧率就是指一秒内多少个场扫描周期。
下面就开始进入愉快的写代码时间了。
TFT字符显示分为3个模块,1.tft控制模块2.字符数据生成模块3.总模块
1.tft控制模块
1.tft_clk_9m是工作时钟,如果用系统时钟,不太合适,经计算9m合适,我的屏幕是绿色这款
525*286*60约等于9000_000,九兆(9M)有ip核PLL生成
2.系统复位
3.16位像素点数据
4.像素点横坐标
5.像素点纵坐标
6.行同步信号
7.场同步信号
8.tft背光板
9.tft输入的时钟
10.DE同步信号
要想按照时序输出行同步信号,则需要行同步信号计数器,hsync_cnt进行计数,在0-40,hsync为1;在41-524,hsync为0;
同样也需要场计数器vsync_cnt进行计数,在行同步计数器完成一个周期的计数时,场计数器加一,在0-11,vsync为1;在12-285,vsync为0;
rgb_valid这个信号表明此时数据有效,而在考虑到将横纵坐标点传递给字符生成模块会产生一个延迟,则提前一个周期产生pix_data_req用于提取数据,接下来就是rgb_tft的赋值,当rgb_valid为高电平就将输入的色彩信号输出。
`timescale 1ns/1ns
module tft_ctrl(
input tft_clk_9m ,
input sys_rst_n ,
input [15:0] pix_data ,
output wire [9:0] pix_x ,
output wire [9:0] pix_y ,
output wire [15:0] rgb_tft ,
output wire hsync ,
output wire vsync ,
output wire tft_bl ,
output wire tft_clk ,
output wire tft_de
);
reg [9:0]hsync_cnt;
reg [9:0]vsync_cnt;
wire rgb_valid ;
wire pix_data_req ;
//为了便于复用,定义一些参数
parameter H_TB = 'd41;
parameter H_HY = 'd2 ;
parameter H_YX = 'd480;
parameter H_QY = 'd2;
parameter V_TB = 'd10;
parameter V_HY = 'd2 ;
parameter V_YX = 'd272;
parameter V_QY = 'd2;
//tft_bl ,tft_clk_9m, tft_de
assign tft_bl = sys_rst_n;
assign tft_clk = tft_clk_9m;
assign tft_de = rgb_valid;
//行计数
always@(posedge tft_clk_9m or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
hsync_cnt <= 10'd0;
else if (hsync_cnt == H_TB + H_HY + H_YX + H_QY -1'b1)
hsync_cnt <= 10'd0;
else
hsync_cnt <= hsync_cnt + 1'b1;
assign hsync = (hsync_cnt < H_TB) ? 1'b1 :1'b0;
//场计数
always@(posedge tft_clk_9m or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
vsync_cnt <= 10'd0;
else if (vsync_cnt == V_TB + V_HY + V_YX + V_QY -1'b1)
vsync_cnt <= 10'd0;
else if (hsync_cnt == H_TB + H_HY + H_YX + H_QY -1'b1)
vsync_cnt <= vsync_cnt + 1'b1;
assign vsync = (vsync_cnt < V_TB) ? 1'b1 :1'b0;
//rgb_valid ,这个用来确保图像有效显示,同时和de信号一样
assign rgb_valid = ((hsync_cnt >= H_TB + H_HY ) && (hsync_cnt < H_TB + H_HY + H_YX)
&& (vsync_cnt >= V_TB + V_HY ) && (vsync_cnt < V_TB + V_HY + V_YX))
? 1'b1 : 1'b0;
//像素点信息请求信号,这个需要超前rgb一个时钟周期
assign pix_data_req = ((hsync_cnt >= H_TB + H_HY - 1'b1) && (hsync_cnt < H_TB + H_HY + H_YX - 1'b1)
&& (vsync_cnt >= V_TB + V_HY) && (vsync_cnt < V_TB + V_HY + V_YX))
? 1'b1 : 1'b0;
//pix_x
assign pix_x = (pix_data_req == 1'b1) ? (hsync_cnt - (H_TB + H_HY - 1'b1)) : 10'h3ff;
//pix_y
assign pix_y = (pix_data_req == 1'b1) ? (vsync_cnt - (V_TB + V_HY - 1'b1)) : 10'h3ff;
//rgb_tft 色彩点输出。
assign rgb_tft = (rgb_valid == 1'b1) ? pix_data : 16'b0;
endmodule
2.字符数据生成模块
1
这一部分就是存放字符的数据,其实想要显示的字符并不是480*272,可以随意设置,但是必须小于这个范围。这里我打算存放三个字符:刺激战场,和平精英,野火牛逼
所设计的字符范围为256*64,比480*272小。
在有字符的区域显示金色,没有字符的区域显示绿色。
1.工作时钟
2.复位
3.横坐标
4.纵坐标
5.色彩信息
根据横纵坐标确定输出信号色彩信息的值。
输入行坐标的范围时0-479,输入纵坐标的范围时0-271
在0.5*480-0.5*256<x<0.5*480+0.5*256,0.5*272-0.5*64<y<0.5*272+0.5*64,字符才有可能是金色的。
如果判断是1则输出金色对应的色彩信息,反之输出绿色对应的色彩信息。