FPGA学习笔记03——RGB LCD显示屏

FPGA驱动RGB LCD显示屏

  • RGB LCD显示原理
  • 系统框图
  • LCD屏显示彩条
  • LCD屏显示字符和图片

RGB LCD显示原理

LCD屏与FPGA芯片接口如下,其中LCD_R0—R7,G0—G7,B0—B7为RGB888信号,
LCD_BL:背光板使能,为高时背光板才亮
LCD_DE:RGB数据使能,为高时RGB数据有效
LCD_VSYNC:竖直(列)扫描有效
LCD_HSYNC:水平(行)扫描有效
LCD_CLK:显示器时钟
//在控制RGB LCD屏时,即可使用DE使能,也能用VSYNC和HSYNC使能。

以1024600分辨率显示器为例,图中灰色部分为显示器黑框部分,白色区域才是有效显示区域,在进行行列扫描时可以用计数器控制DE信号,使其仅仅在有效显示区域内为高电平。

对于每一行的扫描,需要先经过行同步时间(HSPW)、显示后延时间(HBP)才能到达有效显示时间(HOZVAL),在此之后还有一段时间的显示前沿(HFP)。列扫描同理。


不同显示器的时序参数如图,这里使用1024
600屏。

系统框图

系统分为LCD显示模块和LCD驱动模块。
LCD显示模块定义显示的区域和对应颜色,
LCD驱动模块定义行扫描、列扫描、DE等信号,使LCD屏工作

LCD屏显示彩条

对不同的显示区域赋给对应的颜色值

//屏幕分辨率为1024*600,显示彩条
module LCD_colorbar_top(
	input 			clk,
	input 			rst_n,
	
	output        	lcd_de,
	output        	lcd_hs,
	output        	lcd_vs,
	output        	lcd_bl,
	output        	lcd_clk,
	inout  [23:0]   lcd_rgb
);

wire		pixel_xpos    ;
wire		pixel_ypos	  ;
wire 		h_disp		  ;
wire 		v_disp		  ;
wire		pixel_data	  ;	

wire 		pixel_xpos	  ;
wire  		pixel_ypos    ;
wire    	h_disp        ;
wire        v_disp		  ;


LCD_display  u_LCD_display(
	.clk     		(clk		),
	.rst_n        	(rst_n		),
	.pixel_xpos  	(pixel_xpos ),
	.pixel_ypos		(pixel_ypos	),
	.h_disp			(h_disp		),
	.v_disp			(v_disp		),
					
	.pixel_data		(pixel_data )
);

LCD_driver  u_LCD_driver(
	.clk			(clk			),
	.rst_n			(rst_n			),
	.pixel_data		(pixel_data		),
				
	.pixel_xpos		(pixel_xpos		),
	.pixel_ypos		(pixel_ypos		),
	.h_disp			(h_disp			),
	.v_disp			(v_disp			),
		
	.lcd_de			(lcd_de			),
	.lcd_hs			(lcd_hs			),
	.lcd_vs			(lcd_vs			),
	.lcd_bl			(lcd_bl			),
	.lcd_clk		(lcd_clk		),
	.lcd_rgb		(lcd_rgb		)
);
endmodule

//显示模块
module LCD_display(
	input 				clk,
	input 				rst_n,
	input      [10:0] 	pixel_xpos,
	input      [10:0] 	pixel_ypos,
	input        		h_disp,
	input		  		v_disp,
	
	output reg [23:0]	pixel_data
);

parameter WHITE = 24'hffffff;
parameter BLACK = 24'h000000;
parameter RED = 24'hff0000;
parameter GREEN = 24'h00ff00;
parameter BLUE = 24'h0000ff;

//不同区域显示不同颜色
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		pixel_data <= BLACK;
	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
endmodule

//驱动模块
module LCD_driver(
	input 			clk,
	input 			rst_n,
	input  [23:0]	pixel_data,
	//像素位置
	output [10:0] 	pixel_xpos,
	output [10:0] 	pixel_ypos,
	output        	h_disp,
	output		  	v_disp,
	//RGB LCD control
	output        	lcd_de,
	output        	lcd_hs,
	output        	lcd_vs,
	output        	lcd_bl,
	output        	lcd_clk,
	output [23:0]   lcd_rgb
);

parameter H_SYNC_7016 = 11'd20;
parameter H_BACK_7016 = 11'd140;
parameter H_DISP_7016 = 11'd1024;
parameter H_FRONT_7016 = 11'd160;
parameter H_TOTAL_7016 = 11'd1344;

parameter V_SYNC_7016 = 11'd3;
parameter V_BACK_7016 = 11'd20;
parameter V_DISP_7016 = 11'd600;
parameter V_FRONT_7016 = 11'd120;
parameter V_TOTAL_7016 = 11'd635;

wire lcd_en;

reg  [10:0] h_cnt;
reg  [10:0] v_cnt;

assign lcd_bl = 1;
assign lcd_hs = 1;
assign lcd_vs = 1;
assign lcd_clk = clk;
assign h_disp = H_DISP_7016;
assign v_disp = V_DISP_7016;

assign lcd_de = lcd_en;

assign lcd_en = (h_cnt >= H_SYNC_7016 + H_BACK_7016) && (h_cnt <= H_SYNC_7016 + H_BACK_7016 + H_DISP_7016)
				&& (v_cnt >= V_SYNC_7016 + V_BACK_7016) && (v_cnt <= V_SYNC_7016 + V_BACK_7016 + V_DISP_7016)
				? 1 : 0;
				
assign data_reg = (h_cnt >= H_SYNC_7016 + H_BACK_7016 - 1) && (h_cnt <= H_SYNC_7016 + H_BACK_7016 + H_DISP_7016 - 1)
				&& (v_cnt >= V_SYNC_7016 + V_BACK_7016) && (v_cnt <= V_SYNC_7016 + V_BACK_7016 + V_DISP_7016)
				? 1 : 0;
				
assign lcd_rgb = lcd_en ? pixel_data : 24'd0;

assign pixel_xpos = data_reg ? (h_cnt - (H_SYNC_7016 + H_BACK_7016 - 1)) : 11'd0;
assign pixel_ypos = data_reg ? (v_cnt - (V_SYNC_7016 + V_BACK_7016 - 1)) : 11'd0;

//水平扫描计数器和竖直扫描计数器				
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		h_cnt <= 0;
	else begin
		if(h_cnt == H_BACK_7016 - 1)
			h_cnt <= 0;
		else
			h_cnt <= h_cnt + 1;
	
	end
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		v_cnt <= 0;
	else if(h_cnt == H_BACK_7016 - 1) begin
		if(v_cnt == V_BACK_7016 - 1)
			v_cnt <= 0;
		else 
			v_cnt <= v_cnt + 1;
	end
end
endmodule

LCD屏显示字符和图片

显示字符和图片时LCD_driver不变,通过改变pixel_data的值来显示不同的内容。
文字的显示是通过特定像素的高亮来实现的,用PCtoLCD2002软件可实现字符到字模的转换。
使用PicToLCD软件可将图片转换为coe文件并存储到ROM IP内。

//显示字符和图片
module LCD_display(
	input 				clk,
	input 				rst_n,
	input      [10:0] 	pixel_xpos,
	input      [10:0] 	pixel_ypos,
	input        		h_disp,
	input		  		v_disp,
	
	output reg [23:0]	pixel_data
);

//背景和字符的颜色
parameter BACK_COLOR = 24'hffffff;
parameter CHAR_COLOR = 24'h000000;

//字符起始位置和尺寸
parameter CHAR_X_START	= 11'd1;
parameter CHAR_Y_START 	= 11'd110;
parameter CHAR_WITH 	= 11'd96;
parameter CHAR_HEIGHT 	= 11'd32;
//图片起始位置和尺寸
parameter PIC_X_START	= 11'd1;
parameter PIC_Y_START 	= 11'd1;
parameter PIC_WITH 		= 11'd100;
parameter PIC_HEIGHT 	= 11'd100;

wire [10:0] x_cnt;
wire [10:0] y_cnt;
wire 		rom_rd_en;

reg [95:0] char [31:0];

assign rom_rd_en = 1;
assign x_cnt = pixel_xpos - CHAR_X_START;
assign y_cnt = pixel_ypos - CHAR_Y_START;

//字模数据,3个字,每个字尺寸32*32,总共96*32
always @(*) begin

		char[0] <=	96'h000000000000000000000000;
		char[1] <=	96'h000000000000000000000000;
		char[2] <=	96'h003C1C000000000000001000;
		char[3] <=	96'h003C1E300000004010441980;
		char[4] <=	96'h003C1C7803FFFFE00FE231C0;
		char[5] <=	96'h3FFFFFFC000001F008633100;
		char[6] <=	96'h183C1C000000038008613200;
		char[7] <=	96'h003C1C000000060008612220;
		char[8] <=	96'h01FC1C0000000C00086FFFF0;
		char[9] <=	96'h01E0C0000000300008606000;
		char[10] <=	96'h03C3C060000160000FE06000;
		char[11] <=	96'h03FFFFF00001C00008604018;
		char[12] <=	96'h0387E0F00001C000087FFFFC;
		char[13] <=	96'h07C731E00001801008608200;
		char[14] <=	96'h0EEE39C00001803808618300;
		char[15] <=	96'h0E7E1F803FFFFFFC08630380;
		char[16] <=	96'h1F7C1F00000180000866FEE0;
		char[17] <=	96'h3BBC3F00000180000FED823E;
		char[18] <=	96'h33FFFF800001800008718618;
		char[19] <=	96'h03FC03E00001800008618600;
		char[20] <=	96'h01E007FC0001800008618620;
		char[21] <=	96'h03FFFFFE000180001863FFF0;
		char[22] <=	96'h07E1C0380001800018610060;
		char[23] <=	96'h1E31C0000001800018600060;
		char[24] <=	96'h3879DE000001800010600460;
		char[25] <=	96'h00F9C78000018000107FFE60;
		char[26] <=	96'h01E1C3E00001800010600060;
		char[27] <=	96'h03C1C0F00021800020600060;
		char[28] <=	96'h071FC070001F800023C00FC0;
		char[29] <=	96'h1E07C0700007000040C003C0;
		char[30] <=	96'h000380000002000040000180;
		char[31] <=	96'h000000000000000000000000;
end


always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		pixel_data <= BACK_COLOR;
	//显示图片
	else if((pixel_xpos >= PIC_X_START) && (pixel_xpos <= PIC_X_START + PIC_WITH) && (pixel_ypos >= PIC_Y_START) && (pixel_ypos <= PIC_Y_START + PIC_HEIGHT))
		//从ROM中读取图片数据
		pixel_data <= rom_rd_data;
	//显示字符
	else if((pixel_xpos >= CHAR_X_START) && (pixel_xpos <= CHAR_X_START + CHAR_WITH) && (pixel_ypos >= CHAR_Y_START) && (pixel_ypos <= CHAR_Y_START + CHAR_HEIGHT))
		//当char的数据为1时,像素高亮
		if(char[y_cnt][CHAR_WITH - 1 - x_cnt])
			pixel_data <= CHAR_COLOR;
		else
			pixel_data <= BACK_COLOR;
end


always @(posedge lcd_pclk or negedge rst_n) begin
    if(!rst_n)
        rom_addr <= 14'd0;
    //当横纵坐标位于图片显示区域时,累加ROM地址    
    else if((pixel_xpos >= PIC_X_START) && (pixel_xpos <= PIC_X_START + PIC_WITH) && (pixel_ypos >= PIC_Y_START) && (pixel_ypos <= PIC_Y_START + PIC_HEIGHT))
        rom_addr <= rom_addr + 1'b1;
    //当横纵坐标位于图片区域最后一个像素点时,ROM地址清零    
    else if((pixel_ypos >= PIC_Y_START + PIC_HEIGHT))
        rom_addr <= 14'd0;
end

//ROM_IP:存储图片
blk_mem_gen_0  blk_mem_gen_0 (
  .clka  (clk),    // input wire clka
  .ena   (rom_rd_en),   // input wire ena
  .addra (rom_addr),    // input wire [13 : 0] addra
  .douta (rom_rd_data)  // output wire [23 : 0] douta
);
endmodule

版权声明:本文为博主作者:Avava_wan原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/weixin_44128315/article/details/131675938

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2024年1月11日
下一篇 2024年1月11日

相关推荐