第1节 LCD显示叠加图片

本文介绍了一种在7寸LCD显示屏上实现图片显示的方法,包括显示明德扬LOGO图标及字母“E”,涉及PLL模块、ROM模块及LCD驱动模块的设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第1节 LCD显示叠加图片

–作者:肖肖肖

本文为明德扬原创及录用文章,转载请注明出处!

1.1 总体设计

1.1.1 概述

液晶显示器是一-种通过液晶和色彩过滤器过滤光源,在平面面板上产生图像的数字显示器。LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置薄膜晶体管,.上基板玻璃上设置彩色滤光片,通过薄膜晶体管上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。与传统的阴极射线管相比,LCD具有占用空间小,低功耗,低辐射,无闪烁,降低视觉疲劳等优点。现在LCD已渐替代CRT成为主流,价格也已经下降了很多,并已充分的普及。

1.1.2 设计目标

在7寸LCD显示屏上实现图片显示。
其中,在显示屏左上角显示明德扬的LOGO图标,在显示屏的中间居中显示字母“E”。

1.1.3 系统结构框图

系统结构框图如下所示:
在这里插入图片描述

图一

1.1.4 模块功能

 PLL模块实现功能

  1. 将输入的50MHz时钟分频输出40MHz时钟。
     ROM模块实现功能
  2. fpga_rom存储明德扬LOGO的图像数据;
  3. e_rom存储字母“E”的图像数据。
     LCD驱动模块实现功能
    1、 产生驱动LCD屏显示的时序
    2、 读取ROM里存储的数据并输出显示

1.1.5 顶层信号

信号名I/O位宽定义
clkI1系统工作时钟 50M
rst_nI1系统复位信号,低电平有效
hysO1LCD 行时序信号
vysO1LCD 场时序信号
lcd_deO1LCD 数据输入使能信号
lcd_rgbO24LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
lcd_dclkO1LCD 数据采样时钟

1.1.6 参考代码

1.	module top_mdyLcdPic(
2.	    clk       ,
3.	    rst_n     ,
4.	    hys       ,
5.	    vys       ,
6.	    lcd_de    , 
7.	    lcd_rgb   ,
8.	    lcd_dclk
9.	    );
10.	
11.	    parameter   PICTURE_W = 24  ;
12.	
13.	    input                   clk         ;
14.	    input                   rst_n       ;
15.	    output                  hys         ;
16.	    output                  vys         ;
17.	    output                  lcd_de      ;
18.	    output  [PICTURE_W-1:0] lcd_rgb     ;
19.	    output                  lcd_dclk    ;
20.	   
21.	
22.	    wire                     clk_0      ;
23.	    
24.	    wire                     hys        ;
25.	    wire                     vys        ;
26.	    wire                     lcd_de     ;
27.	    wire   [PICTURE_W-1:0]   lcd_rgb    ;
28.	    wire                     lcd_dclk   ;
29.	
30.	
31.	//40MHz
32.	pll_40m u_pll_40m(
33.		    .areset     (~rst_n ),
34.	        .inclk0     (clk    ),
35.		    .c0         (clk_0  )
36.	    );
37.	
38.	
39.	lcd_driver  u2(
40.	   .clk          (clk_0       ),//40MHz
41.	   .rst_n        (rst_n       ),
42.	                          
43.	   .hys          (hys         ),  
44.	   .vys          (vys         ),  
45.	   .lcd_de       (lcd_de      ),                   
46.	   .lcd_rgb      (lcd_rgb     ), 
47.	   .lcd_dclk     (lcd_dclk    ) 
48.	    );
49.	
50.	endmodule

1.2 PLL模块设计

1.2.1 接口信号

下面为PLL的接口信号:

信号名I/O位宽定义
aresetI1PLL复位信号,高电平有效
inclk0I1PLL输入时钟 50MHz
c0O1PLL输出时钟 40MHz

1.2.2 设计思路

本模块主要用于产生LCD驱动时序所需要的时钟,关于PLL的使用详细介绍请看下方链接:
http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=322&fromuid=100105

1.3 ROM模块设计

1.3.1 接口信号

信号名I/O位宽定义
addressI16ROM数据存放地址
clockI1ROM工作时钟40MHz
qO8ROM输出数据

1.3.2 设计思路

本模块主要用于存储需要显示的图像数据,关于ROM的使用详细介绍请查看IP核右上角数据手册“Documentation”。
也可以参考以下链接链接额的ROM IP核配置介绍:
http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=1026&fromuid=9437

1.4 LCD驱动模块设计

1.4.1 接口信号

信号名I/O位宽定义
clkI1模块工作时钟 40MHz
rst_nI1系统复位信号,低电平有效
hysO1LCD 行时序信号
vysO1LCD 场时序信号
lcd_deO1LCD 数据输入使能信号
lcd_rgbO24LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
lcd_dclkO1LCD 数据采样时钟

1.4.2 设计思路

产生驱动LCD显示的行场时序信号,其计数器架构如下图所示:
在这里插入图片描述

行计数器h_cnt:该计数器用来计算行同步信号的帧长。加一条件为1,表示一直在计数。结束条件为数1056个,也就是一行有1056个像素。
场计数器v_cnt:该计数器用来计算场同步信号的帧长。加一条件为end_h_cnt,即行计数器的计数器的结束条件,表示每计数完一行像素就加一。结束条件为数525个,也就是一共有525行像素。
其中,在从存储图像“E”的ROM里读取数据的时候,有一个操作就是读取的地址从第8位开始,也就是说18位数据地址,低三位不读,读取的是e_rom_addr[16:3]。有这样一个操作的话就能实现对存储的图像进行8倍的放大显示。

1.4.3 参考代码

1.	module lcd_driver(
2.	    clk          ,//40MHz
3.	    rst_n        ,
4.	
5.	    hys          , 
6.	    vys          , 
7.	    lcd_de       ,  
8.	    lcd_rgb      , 
9.	    lcd_dclk   
10.	);
11.	
12.	   input                    clk             ;
13.	   input                    rst_n           ;
14.	
15.	   output                   hys             ;
16.	   output                   vys             ;
17.	   output                   lcd_de          ;
18.	   output [23:0]            lcd_rgb         ;
19.	   output                   lcd_dclk        ;
20.	
21.	   reg                      hys             ;
22.	   reg                      vys             ;
23.	   reg                      lcd_de          ;
24.	   reg    [23:0]            lcd_rgb         ;
25.	   wire                     lcd_dclk        ;
26.	
27.	   //1056
28.	   parameter         THPW      = 20         ;   
29.	   parameter         THB       = 46         ;   
30.	   parameter         THD       = 800        ;   
31.	   parameter         THFP      = 210        ;   
32.	   
33.	   //525
34.	   parameter         TVPW      = 10         ;   
35.	   parameter         TVB       = 23         ;   
36.	   parameter         TVD       = 480        ;   
37.	   parameter         TVFP      = 22         ;   
38.	
39.	   parameter       HDE_CENTRE  = THD/2      ;//400
40.	   parameter       VDE_CENTRE  = TVD/2      ;//240
41.	
42.	   parameter       LOGO_X0     = (0   + (THB-1))         ;   
43.	   parameter       LOGO_X1     = (120 + (THB-1))         ;   
44.	   parameter       LOGO_Y0     = (0   + (TVB-1))         ;   
45.	   parameter       LOGO_Y1     = (55  + (TVB-1))         ;  
46.	
47.	   parameter         E_X0      = ((HDE_CENTRE-200) + (THB-1))        ;   
48.	   parameter         E_X1      = ((HDE_CENTRE+200) + (THB-1))        ;   
49.	   parameter         E_Y0      = ((VDE_CENTRE-150) + (TVB-1))        ;   
50.	   parameter         E_Y1      = ((VDE_CENTRE+150) + (TVB-1))        ;   
51.	
52.	   reg   [ 10:0]            h_cnt           ;
53.	   wire                     add_h_cnt       ;
54.	   wire                     end_h_cnt       ;
55.	   reg   [ 9:0]             v_cnt           ;
56.	   wire                     add_v_cnt       ;
57.	   wire                     end_v_cnt       ;
58.	
59.	
60.	   wire                     active_area     ;
61.	   reg                      logo_rom_area        ;
62.	   reg      [15:0]          logo_rom_addr        ;
63.	   wire     [7:0]           logo_rom_data        ;
64.	   reg                      e_rom_area        ;
65.	   reg      [17:0]          e_rom_addr        ;
66.	   wire     [7:0]           e_rom_data        ;
67.	   reg      [2:0]           e_rom_addr_low    ;
68.	   reg                      e_sel             ;
69.	   
70.	
71.	
72.	always @(posedge clk or negedge rst_n) begin 
73.	    if (rst_n==0) begin
74.	        h_cnt <= 0; 
75.	    end
76.	    else if(add_h_cnt) begin
77.	        if(end_h_cnt)
78.	            h_cnt <= 0; 
79.	        else
80.	            h_cnt <= h_cnt+1 ;
81.	   end
82.	end
83.	assign add_h_cnt = 1;
84.	assign end_h_cnt = add_h_cnt  && h_cnt == (THB + THD + THFP)-1 ;
85.	
86.	
87.	always @(posedge clk or negedge rst_n) begin 
88.	    if (rst_n==0) begin
89.	        v_cnt <= 0; 
90.	    end
91.	    else if(add_v_cnt) begin
92.	        if(end_v_cnt)
93.	            v_cnt <= 0; 
94.	        else
95.	            v_cnt <= v_cnt+1 ;
96.	   end
97.	end
98.	assign add_v_cnt = end_h_cnt;
99.	assign end_v_cnt = add_v_cnt  && v_cnt == (TVB + TVD + TVFP)-1 ;
100.	
101.	/*******************************************************/
102.	    //dclk
103.	    assign lcd_dclk = clk;
104.	
105.	    //hsync
106.	    always  @(posedge clk or negedge rst_n)begin
107.	        if(rst_n==1'b0)begin
108.	            hys <= 0;
109.	        end
110.	        else if(add_h_cnt && h_cnt==THPW-1)begin
111.	            hys <= 1;
112.	        end
113.	        else if(end_h_cnt)begin
114.	            hys <= 0;
115.	        end
116.	    end
117.	
118.	
119.	    //vsync
120.	    always  @(posedge clk or negedge rst_n)begin
121.	        if(rst_n==1'b0)begin
122.	            vys <= 0;
123.	        end
124.	        else if(add_v_cnt && v_cnt==TVPW-1)begin
125.	            vys <= 1;
126.	        end
127.	        else if(end_v_cnt)begin
128.	            vys <= 0;
129.	        end
130.	    end
131.	   
132.	
133.	    //lcd_de
134.	    always  @(posedge clk or negedge rst_n)begin
135.	        if(rst_n==1'b0)begin
136.	            lcd_de <= 0;
137.	        end
138.	        else if(active_area)begin
139.	            lcd_de <= 1;
140.	        end
141.	        else begin
142.	            lcd_de <= 0;
143.	        end
144.	    end
145.	    
146.	/********************************************************************/    
147.	
148.	assign active_area = h_cnt>=(THB-1) && h_cnt<(THB+THD-1) && v_cnt>=(TVB-1) && v_cnt<(TVB+TVD-1);
149.	
150.	
151.	always  @(*)begin
152.	    logo_rom_area = h_cnt >=LOGO_X0 && h_cnt < LOGO_X1 && v_cnt >= LOGO_Y0 && v_cnt < LOGO_Y1;
153.	end
154.	
155.	always  @(*)begin
156.	    e_rom_area = h_cnt >=E_X0 && h_cnt < E_X1 && v_cnt >= E_Y0 && v_cnt < E_Y1;
157.	end
158.	
159.	
160.	always  @(posedge clk or negedge rst_n)begin
161.	    if(rst_n==1'b0)begin
162.	        lcd_rgb <= 0;
163.	    end
164.	    else if(active_area)begin
165.	        if(logo_rom_area)
166.	            lcd_rgb <= {logo_rom_data[7:5],5'b11111,logo_rom_data[4:2],5'b11111,logo_rom_data[1:0],6'b111111};
167.	        else if(e_rom_area)
168.	            lcd_rgb <= {24{e_sel}};
169.	        else 
170.	            lcd_rgb <= {24{1'b1}};
171.	    end
172.	    else begin
173.	        lcd_rgb <=0;
174.	    end
175.	end
176.	
177.	
178.	always  @(*)begin
179.	    logo_rom_addr = (h_cnt-LOGO_X0) + 120*(v_cnt-LOGO_Y0);
180.	end
181.	
182.	always  @(*)begin
183.	    e_rom_addr = (h_cnt-E_X0) + 400*(v_cnt-E_Y0);
184.	end
185.	
186.	
187.	
188.	always  @(posedge clk or negedge rst_n)begin
189.	    if(rst_n==1'b0)begin
190.	        e_rom_addr_low <= 0;
191.	    end
192.	    else begin
193.	        e_rom_addr_low <= e_rom_addr[2:0];
194.	    end
195.	end
196.	
197.	always  @(*)begin
198.	    e_sel = ~e_rom_data[7-e_rom_addr_low];
199.	end
200.	
201.	
202.	fpga_rom u_fpga_rom(
203.		           .address (logo_rom_addr),
204.		           .clock   (clk     ),
205.		           .q       (logo_rom_data));
206.	
207.	e_rom u_e_rom(
208.	    .address   (e_rom_addr[16:3]  ),
209.	    .clock     (clk  ),
210.	    .q         (e_rom_data  ));
211.	
212.	
213.	    endmodule

1.5 效果和总结

以下为工程上板后的现象效果图:
 mp801开发板
在这里插入图片描述

 ms980试验箱
在这里插入图片描述

感兴趣的朋友也可以访问mdy论坛进行FPGA相关工程设计学习,也可以看一下我们往期的文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值