使用的TFT为群创7寸液晶屏AT070TN83,分辨率为800*480FPGA为ep1c6q240c8,晶振为50M
首先介绍一下TFT接口
1和2脚VLED,4和5脚GLED,3脚为ADJ。VLED和GLED为背光电源和地,ADJ为用PWM调整背光亮度脚,频率应在100-300HZ,占空比越高越亮。本人背光电源用的+5v
6和7脚为数字电路部分电源。本人用的是3.3v
12,16,20,24,28,32,36,38为地
8脚为MODE,9脚为DE,10脚VS,11脚HS。当选用DE模式时HS和VS应浮空,当选用HV模式时,DE脚应浮空。本人使用的是HV模式。
13,14,15,17,18,19分别为b5,b4,b3,b3,b1,b0。本人b0脚未用,直接接地
21,22,23,25,26,27分别为g5,g4,g3,g2,g1,g0
29,30,31,33,34,35分别为 r5,r4,r3,r2,r1,r0。本人r0脚未用 ,直接接地
37脚为DCLK
39脚为L/R,40脚为U/D。本人40脚接地,39脚接高电平,为从左到右,从上到下扫描
这样我总共用了16根颜色信号线分别为5根R,6根G,5根B线。还需要fpga控制的是DCLK,HS,VS,和ADJ脚。
下面附上HV模式下hs和vs的脉冲数的说明
本人使用汉字取模软件得到“液晶测试”4个汉字的字模,如下
/////////////////////////////////////////////////////////////////////////
// 汉字字模表 //
// 汉字库: 宋体16.dot,横向取模左高位,数据排列:从左到右从上到下 //
/////////////////////////////////////////////////////////////////////////
struct typFNT_GB16 code GB_16[] = // 数据表
{
"液", 0x00,0x80,0x40,0x44,0x37,0xFE,0x10,0x20,
0x81,0x20,0x61,0x3C,0x22,0x44,0x0A,0x64,
0x16,0x98,0x2B,0x48,0xE2,0x50,0x22,0x20,
0x22,0x50,0x22,0x8E,0x23,0x04,0x22,0x00,
"晶", 0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,
0x08,0x20,0x08,0x20,0x0F,0xE0,0x08,0x24,
0x7E,0xFE,0x42,0x84,0x42,0x84,0x7E,0xFC,
0x42,0x84,0x42,0x84,0x7E,0xFC,0x42,0x84,
"测", 0x00,0x00,0x40,0x44,0x27,0xE4,0x24,0x54,
0x85,0x54,0x65,0x54,0x25,0x54,0x0D,0x54,
0x15,0x54,0x25,0x54,0xE5,0x54,0x21,0x04,
0x22,0x84,0x24,0x44,0x28,0x54,0x20,0x08,
"试", 0x00,0x20,0x40,0x28,0x20,0x24,0x20,0x20,
0x0F,0xFE,0x00,0x20,0xE0,0x20,0x27,0xE0,
0x21,0x20,0x21,0x10,0x21,0x10,0x21,0x10,
0x29,0xD2,0x37,0x12,0x22,0x0A,0x00,0x04
};
将这些字模数据放在fpga的256*8的mif文件里面(其实128*8就够用了),如下
然后用Tools->MegaWizard Plug-in Manager建立一个tft_rom.v,保存这些数据。
Tft显示程序如下。最终显示结果为屏幕底色为蓝色,中间有个绿色的方框,“液晶测试”字为白色,底色为红色。这4个字沿着方框内部,每隔3s顺指针换一个位置。
程序中计数器没有优化。
/**********************************************************************
*project name :tft
*module name :tft
*designer :kang
*version :1.00
*date :2010-11-27
**********************************************************************/
module tft (
//input signals
input clk,
input rst,
//output signals
output vs,
output hs,
output dclk,
output reg adj,
output [4:0] r,
output [5:0] g,
output [4:0] b
);
//counter_x and counter_y
reg [9:0] counter_x;
reg [9:0] counter_y;
always @(posedge clk or negedge rst)
begin
if(!rst) counter_x<=0;
else if(counter_x>=10'd928) counter_x<=0;
else counter_x<=counter_x+1'b1;
end
always @(posedge clk or negedge rst)
begin
if(!rst) counter_y<=0;
else if(counter_y>=10'd525) counter_y<=0;
else if(counter_x>=10'd928) counter_y<=counter_y+1'b1;
end
//adj
reg [31:0] counter_pwm;
always @(posedge clk or negedge rst)
begin
if(!rst) counter_pwm<=0;
else if(counter_pwm>=32'd125000) counter_pwm<=0;
else counter_pwm<=counter_pwm+1'b1;
end
always @(posedge clk or negedge rst)
begin
if(!rst) adj<=0;
else if(counter_pwm==32'd125000) adj<=~adj;
end
//hs and vs
assign hs=(counter_x<=10'd48);
assign vs=(counter_y<=3);
//dclk
assign dclk=clk;
//pos_x and pos_y
wire [9:0] pos_x;
wire [9:0] pos_y;
assign pos_x=(counter_x-10'd88);
assign pos_y=(counter_y-10'd32);
//valid
wire valid;
assign valid=(pos_x<=10'd800)&&(pos_y<=640);
//word
wire word_valid;
reg [9:0] word_origin_x;
reg [9:0] word_origin_y;
reg [31:0] count_word;
always @(posedge clk or negedge rst)
begin
if(!rst) count_word<=0;
else if(count_word==100000000) count_word<=0;
else count_word<=count_word+1'b1;
end
reg dir_word_x;
reg dir_word_y;
reg dir_word_x_en;
reg dir_word_y_en;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
dir_word_x<=0;
dir_word_y<=0;
dir_word_x_en<=1'b1;
dir_word_y_en<=0;
end
else if(dir_word_x_en&!dir_word_x&(word_origin_x==10'd640))
begin
dir_word_x<=1'b1;
dir_word_y<=1'b0;
dir_word_x_en<=1'b0;
dir_word_y_en<=1'b1;
end
else if(dir_word_x_en&dir_word_x&(word_origin_x==10'd128))
begin
dir_word_x<=1'b0;
dir_word_y<=1'b1;
dir_word_x_en<=0;
dir_word_y_en<=1'b1;
end
else if(dir_word_y_en&!dir_word_y&(word_origin_y==10'd416))
begin
dir_word_x<=1'b1;
dir_word_y<=1'b1;
dir_word_x_en<=1'b1;
dir_word_y_en<=1'b0;
end
else if(dir_word_y_en&dir_word_y&(word_origin_y==10'd32))
begin
dir_word_x<=1'b0;
dir_word_y<=1'b0;
dir_word_x_en<=1'b1;
dir_word_y_en<=1'b0;
end
end
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
word_origin_x<=0;
word_origin_y<=0;
end
else if((word_origin_x<128)||(word_origin_x>640)||(word_origin_y<32)||(word_origin_y>416))
begin
word_origin_x<=10'd128;
word_origin_y<=10'd32;
end
else if(count_word==100000000)
begin
if(dir_word_x_en)
begin
if(dir_word_x) word_origin_x<=word_origin_x-10'd128;
else word_origin_x<=word_origin_x+10'd128;
end
else if(dir_word_y_en)
begin
if(dir_word_y) word_origin_y<=word_origin_y-10'd32;
else word_origin_y<=word_origin_y+10'd32;
end
end
end
assign word_valid=(pos_x>=word_origin_x)&(pos_x<=(word_origin_x+10'd128))&
(pos_y>=word_origin_y)&(pos_y<=(word_origin_y+10'd32));
//assign word_valid=1'b1;
wire line_valid;
assign line_valid=((pos_x>=10'd110)&(pos_x<=10'd790)&(pos_y>=10'd10)&(pos_y<=10'd470))&
((pos_x>=10'd780)||(pos_x<=10'd120)||(pos_y>=10'd460)||(pos_y<=10'd20));
//assign r,g and b
wire [2:0] bitx;
assign bitx=3'd7-pos_x[3:1];
assign r=(!valid)?5'h0line_valid)?5'h00!word_valid)?5'h00:dat[bitx]?5'h1f:5'h1f;
assign g=(!valid)?6'h0line_valid)?6'h3f!word_valid)?6'h00:dat[bitx]?6'h3f:6'h0;
assign b=(!valid)?5'h0line_valid)?5'h00!word_valid)?5'h1f:dat[bitx]?5'h1f:5'h0;
//dat
wire [7:0] dat;
tft_rom U1(
.address({1'b0,pos_x[6:5],pos_y[4:1],pos_x[4]}),
.clock(clk),
.q(dat)
);
endmodule
用户377235 2016-4-21 21:07
用户377235 2014-4-23 15:24
用户372420 2011-6-1 16:55