大家好,这里是程序员杰克。一名平平无奇的嵌入式软件工程师。
上两篇已经总结和分享了RGB接口TFT-LCD触摸屏的相关内容。 本篇使用Verilog语言实现RGB的驱动时序。
前面描述了很多关于时序的内容,但其实在FPGA中实现RGB接口的LCD屏驱动时序还是很简单的。 只需要实现行扫描、列扫描的时钟周期控制,并且在有效区域输出对应像素点的RGB数据便可。 实现控制时序和测试验证难度不大,主要还是要在实际的项目中应用,例如:实时显示摄像头的图像信息等。 由于文字篇幅原因, 本篇仅对RGB接口驱动时序的实现思想以及Verilog语言代码进行说明。
下面正式进入本章推送的内容。
01 时序参数
常用的TFT-LCD屏(帧率为60Hz)时序参数如下图所示,其中,行同步信号时序的单位是时钟脉冲,而场同步信号时序的单位是行周期。
对于驱动时序而言,最重要的是确定帧率和像素时钟,其他参数由厂商提供。本示例使用的是分辨率为800*480 的4.3寸TFT-LCD屏,使用的帧率为60Hz(每秒60帧图像),时序参参数以及相关计算公式如下表所示:
02 时序实现
对于帧率和分辨率固定的LCD屏幕驱动时序(RGB接口),有以下特点:
设计思路
FPGA设计周期性的时序,可以通过计数器来控制,在计数器的对应count数执行相对应的逻辑; 对于逻辑而言,需要考虑的是同步信号、数据有效信号的范围脉冲数、以及扫描周期; 行扫描、列扫描对应的设计思路如下(800*480 @60 TFT-LCD屏示例):
时序 | 设计思路描述 |
---|---|
行扫描 | 设计场扫描脉冲计数器,对PCLK脉冲计数; 计数的最大值 = 行扫描周期; 计数自增条件为时钟脉冲高电平(PCLK); 当cnt>H Pulse width时, HSYNC=1,否则为HSYNC=0; |
场扫描 | 设计场扫描脉冲计数器,对行扫描周期计数; 场扫描计数最大值 = 场扫描周期; 计数自增条件为行扫描周期; 当cnt>V Pulsewidth时,VSYNC=1,否则为VSYNC=0; |
行扫描时序实现
由于FPGA设计计数器时,一般从0开始计数,因此行扫描逻辑控制参数需要减去1,如下表所示:
逻辑控制参数 | 说明 | 数值(单位:PCLK) |
---|---|---|
H_SYNC | 行同步持续时间 | 128-1 |
H_DATA_START | 行数据开始 | 216-1 |
H_DATA_END | 行数据结束 | 1016-1 |
H_PERIOD | 行扫描周期 | 1055-1 |
Verilog实现代码如下:
parameter H_SYNC = 11'd127 ;
parameter H_DATA_START = 11'd215 ;
parameter H_DATA_END = 11'd1015 ;
parameter H_PERIOD = 11'd1055 ;
//行扫描控制时序
reg [10:0] h_cnt;
always @(posedge pclk) begin
if(rst_n == 1'b0) begin
h_cnt <= 11'd0;
end
else if(h_cnt == H_PERIOD) begin
h_cnt <= 11'd0;
end
else begin
h_cnt <= h_cnt + 1'b1;
end
end
assign hsync = (h_cnt > H_SYNC) ? 1'b1 : 1'b0;
assign h_index = (h_cnt > H_DATA_START) ? (h_cnt - H_DATA_START) : 11'd0;
场扫描时序实现
由于FPGA设计计数器时,一般从0开始计数,因此行扫描逻辑控制参数需要减去1,如下表所示:
参数 | 说明 | 数值(单位:PCLK) |
---|---|---|
V_SYNC | 行同步持续时间 | 2-1 |
V_DATA_START | 行数据开始 | 216-1 |
V_DATA_END | 行数据结束 | 1016-1 |
V_PERIOD | 行扫描周期 | 1055-1 |
Verilog实现代码如下:
parameter v_SYNC = 11'd1 ;
parameter v_DATA_START = 11'd34 ;
parameter v_DATA_END = 11'd514 ;
parameter v_PERIOD = 11'd524 ;
//场扫描控制时序
reg [10:0] v_cnt;
always @(posedge pclk) begin
if(rst_n == 1'b0) begin
v_cnt <= 11'd0;
end
else if(v_cnt == v_PERIOD) begin
v_cnt <= 11'd0;
end
else if(h_cnt == H_PERIOD) begin
v_cnt <= v_cnt + 1'b1;
end
else begin
v_cnt <= v_cnt;
end
end
assign vsync = (v_cnt > v_SYNC) ? 1'b1 : 1'b0;
assign v_index = (v_cnt > v_DATA_START) ? (v_cnt - v_DATA_START) : 11'd0;
完整Verilog代码如下:
module parallel_rgb_control
#
(
parameter H_SYNC = 11'd127 ,
parameter H_DATA_START = 11'd215 ,
parameter H_DATA_END = 11'd1015 ,
parameter H_PERIOD = 11'd1055 ,
parameter v_SYNC = 11'd1 ,
parameter v_DATA_START = 11'd34 ,
parameter v_DATA_END = 11'd514 ,
parameter v_PERIOD = 11'd524
)
(
input wire pclk ,
input wire rst_n ,
output wire hsync ,
output wire [10:0] h_index ,
output wire vsync ,
output wire [10:0] v_index ,
output wire de
);
//行扫描控制时序
reg [10:0] h_cnt;
always @(posedge pclk) begin
if(rst_n == 1'b0) begin
h_cnt <= 11'd0;
end
else if(h_cnt == H_PERIOD) begin
h_cnt <= 11'd0;
end
else begin
h_cnt <= h_cnt + 1'b1;
end
end
assign hsync = (h_cnt > H_SYNC) ? 1'b1 : 1'b0;
assign h_index = (h_cnt > H_DATA_START) ? (h_cnt - H_DATA_START) : 11'd0;
//场扫描控制时序
reg [10:0] v_cnt;
always @(posedge pclk) begin
if(rst_n == 1'b0) begin
v_cnt <= 11'd0;
end
else if(v_cnt == v_PERIOD) begin
v_cnt <= 11'd0;
end
else if(h_cnt == H_PERIOD) begin
v_cnt <= v_cnt + 1'b1;
end
else begin
v_cnt <= v_cnt;
end
end
assign vsync = (v_cnt > v_SYNC) ? 1'b1 : 1'b0;
assign v_index = (v_cnt > v_DATA_START) ? (v_cnt - v_DATA_START) : 11'd0;
assign de = ( (h_cnt >= H_DATA_START) && (h_cnt < H_DATA_END) ) && ( (v_cnt >= v_DATA_START) && (v_cnt < v_DATA_END) );
endmodule
05 文章总结
对于RGB接口的TFT-LCD屏的时序驱动代码还是较为简单的。 使用文字描述实际的应用并且让人容易理解,还是很困难的。 基于此,本篇仅仅只是分享了RGB接口周期时序的实现,对于具体的数据输出显示的应用并未说明。 倘若有兄弟想了解实际应用,可以添加杰克的微信号来交流。
全部0条评论
快来发表一下你的评论吧 !