【案例】 LCD显示叠加图片

  发布时间:2023-10-18  |    作者:管理员  |  浏览量:345

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

 

1.1 总体设计

1.1.1 概述

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

1.1.2 设计目标

7寸LCD显示屏上实现图片显示。

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

 

1.1.3 系统结构框图

系统结构框图如下所示:

 image.png


图一

1.1.4模块功能
PLL模块实现功能

1.将输入的50MHz时钟分频输出40MHz时钟。


ROM模块实现功能

1.FPGA_rom存储明德扬LOGO的图像数据;

 

2.e_rom存储字母“E”的图像数据。


LCD驱动模块实现功能

1、产生驱动LCD屏显示的时序

2、读取ROM里存储的数据并输出显示


1.1.5顶层信号

  

信号名

  

I/O

位宽

定义

clk

I

1

系统工作时钟 50M

rst_n

I

1

系统复位信号,低电平有效

hys

O

1

LCD 行时序信号

vys

O

1

LCD 场时序信号

lcd_de

O

1

LCD 数据输入使能信号

lcd_rgb

O

24

LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。

lcd_dclk

O

1

LCD 数据采样时钟




1.1.6参考代码

a. 

module top_mdyLcdPicOverlay(

b. 

c. 

    clk       ,

d. 

e. 

    rst_n     ,

f. 

g. 

    hys       ,

h. 

i. 

    vys       ,

j. 

k. 

    lcd_de    ,

l. 

m. 

    lcd_rgb   ,

n. 

o. 

    lcd_dclk

p. 

q. 

    );

r. 

s. 

 

t. 

u. 

    parameter   PICTURE_W = 24  ;

v. 

w. 

 

x. 

y. 

    input                   clk         ;

z. 

aa. 

    input                   rst_n       ;

ab. 

ac. 

    output                  hys         ;

ad. 

ae. 

    output                  vys         ;

af. 

ag. 

    output                  lcd_de      ;

ah. 

ai. 

    output  [PICTURE_W-1:0] lcd_rgb     ;

aj. 

ak. 

    output                  lcd_dclk    ;

al. 

am. 

   

an. 

ao. 

 

ap. 

aq. 

    wire                     clk_0      ;

ar. 

as. 

   

at. 

au. 

    wire                     hys        ;

av. 

aw. 

    wire                     vys        ;

ax. 

ay. 

    wire                     lcd_de     ;

az. 

ba. 

    wire   [PICTURE_W-1:0]   lcd_rgb    ;

bb. 

bc. 

    wire                     lcd_dclk   ;

bd. 

be. 

 

bf. 

bg. 

 

bh. 

bi. 

//40MHz

bj. 

bk. 

pll_40m u_pll_40m(

bl. 

bm. 

            .areset     (~rst_n ),

bn. 

bo. 

        .inclk0     (clk    ),

bp. 

bq. 

            .c0         (clk_0  )

br. 

bs. 

    );

bt. 

bu. 

 

bv. 

bw. 

 

bx. 

by. 

lcd_driver  u2(

bz. 

ca. 

   .clk          (clk_0       ),//40MHz

cb. 

cc. 

   .rst_n        (rst_n       ),

cd. 

ce. 

                          

cf. 

cg. 

   .hys          (hys         ),  

ch. 

ci. 

   .vys          (vys         ),  

cj. 

ck. 

   .lcd_de       (lcd_de      ),                  

cl. 

cm. 

   .lcd_rgb      (lcd_rgb     ),

cn. 

co. 

   .lcd_dclk     (lcd_dclk    )

cp. 

cq. 

    );

cr. 

cs. 

 

ct. 

cu. 

endmodule

cv. 

复制代码


1.2 PLL模块设计

1.2.1接口信号

下面为PLL的接口信号:

 

  

信号名

  

I/O

位宽

定义

areset

I

1

PLL复位信号,高电平有效

inclk0

I

1

PLL输入时钟 50MHz

c0

O

1

PLL输出时钟 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

位宽

定义

address

I

16

ROM数据存放地址

clock

I

1

ROM工作时钟40MHz

q

O

8

ROM输出数据


1.3.2设计思路

本模块主要用于存储需要显示的图像数据,关于ROM的使用详细介绍请查看IP核右上角数据手册“Documentation”。


1.4 LCD驱动模块设计
1.4.1接口信号

  

信号名

  

I/O

位宽

定义

clk

I

1

模块工作时钟 40MHz

rst_n

I

1

系统复位信号,低电平有效

hys

O

1

LCD 行时序信号

vys

O

1

LCD 场时序信号

lcd_de

O

1

LCD 数据输入使能信号

lcd_rgb

O

24

LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。

lcd_dclk

O

1

LCD 数据采样时钟


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参考代码

a. 

module lcd_driver(

b. 

c. 

    clk          ,//40MHz

d. 

e. 

    rst_n        ,

f. 

g. 

 

h. 

i. 

    hys          ,

j. 

k. 

    vys          ,

l. 

m. 

    lcd_de       ,  

n. 

o. 

    lcd_rgb      ,

p. 

q. 

    lcd_dclk   

r. 

s. 

);

t. 

u. 

 

v. 

w. 

   input                    clk             ;

x. 

y. 

   input                    rst_n           ;

z. 

aa. 

 

ab. 

ac. 

   output                   hys             ;

ad. 

ae. 

   output                   vys             ;

af. 

ag. 

   output                   lcd_de          ;

ah. 

ai. 

   output [23:0]            lcd_rgb         ;

aj. 

ak. 

   output                   lcd_dclk        ;

al. 

am. 

 

an. 

ao. 

   reg                      hys             ;

ap. 

aq. 

   reg                      vys             ;

ar. 

as. 

   reg                      lcd_de          ;

at. 

au. 

   reg    [23:0]            lcd_rgb         ;

av. 

aw. 

   wire                     lcd_dclk        ;

ax. 

ay. 

 

az. 

ba. 

   //1056

bb. 

bc. 

   parameter         THPW      = 20         ;   

bd. 

be. 

   parameter         THB       = 46         ;   

bf. 

bg. 

   parameter         THD       = 800        ;   

bh. 

bi. 

   parameter         THFP      = 210        ;   

bj. 

bk. 

   

bl. 

bm. 

   //525

bn. 

bo. 

   parameter         TVPW      = 10         ;   

bp. 

bq. 

   parameter         TVB       = 23         ;   

br. 

bs. 

   parameter         TVD       = 480        ;   

bt. 

bu. 

   parameter         TVFP      = 22         ;   

bv. 

bw. 

 

bx. 

by. 

   parameter       HDE_CENTRE  = THD/2      ;//400

bz. 

ca. 

   parameter       VDE_CENTRE  = TVD/2      ;//240

cb. 

cc. 

 

cd. 

ce. 

   parameter       LOGO_X0     = (0   + (THB-1))         ;   

cf. 

cg. 

   parameter       LOGO_X1     = (120 + (THB-1))         ;   

ch. 

ci. 

   parameter       LOGO_Y0     = (0   + (TVB-1))         ;   

cj. 

ck. 

   parameter       LOGO_Y1     = (55  + (TVB-1))         ;  

cl. 

cm. 

 

cn. 

co. 

   parameter         E_X0      = ((HDE_CENTRE-200) + (THB-1))        ;   

cp. 

cq. 

   parameter         E_X1      = ((HDE_CENTRE+200) + (THB-1))        ;   

cr. 

cs. 

   parameter         E_Y0      = ((VDE_CENTRE-150) + (TVB-1))        ;   

ct. 

cu. 

   parameter         E_Y1      = ((VDE_CENTRE+150) + (TVB-1))        ;   

cv. 

cw. 

 

cx. 

cy. 

   reg   [ 10:0]            h_cnt           ;

cz. 

da. 

   wire                     add_h_cnt       ;

db. 

dc. 

   wire                     end_h_cnt       ;

dd. 

de. 

   reg   [ 9:0]             v_cnt           ;

df. 

dg. 

   wire                     add_v_cnt       ;

dh. 

di. 

   wire                     end_v_cnt       ;

dj. 

dk. 

 

dl. 

dm. 

 

dn. 

do. 

   wire                     active_area     ;

dp. 

dq. 

   reg                      logo_rom_area        ;

dr. 

ds. 

   reg      [15:0]          logo_rom_addr        ;

dt. 

du. 

   wire     [7:0]           logo_rom_data        ;

dv. 

dw. 

   reg                      e_rom_area        ;

dx. 

dy. 

   reg      [17:0]          e_rom_addr        ;

dz. 

ea. 

   wire     [7:0]           e_rom_data        ;

eb. 

ec. 

   reg      [2:0]           e_rom_addr_low    ;

ed. 

ee. 

   reg                      e_sel             ;

ef. 

eg. 

   

eh. 

ei. 

 

ej. 

ek. 

 

el. 

em. 

always @(posedge clk or negedge rst_n) begin

en. 

eo. 

    if (rst_n==0) begin

ep. 

eq. 

        h_cnt <= 0;

er. 

es. 

    end

et. 

eu. 

    else if(add_h_cnt) begin

ev. 

ew. 

        if(end_h_cnt)

ex. 

ey. 

            h_cnt <= 0;

ez. 

fa. 

        else

fb. 

fc. 

            h_cnt <= h_cnt+1 ;

fd. 

fe. 

   end

ff. 

fg. 

end

fh. 

fi. 

assign add_h_cnt = 1;

fj. 

fk. 

assign end_h_cnt = add_h_cnt  && h_cnt == (THB + THD + THFP)-1 ;

fl. 

fm. 

 

fn. 

fo. 

 

fp. 

fq. 

 

fr. 

fs. 

always @(posedge clk or negedge rst_n) begin

ft. 

fu. 

    if (rst_n==0) begin

fv. 

fw. 

        v_cnt <= 0;

fx. 

fy. 

    end

fz. 

ga. 

    else if(add_v_cnt) begin

gb. 

gc. 

        if(end_v_cnt)

gd. 

ge. 

            v_cnt <= 0;

gf. 

gg. 

        else

gh. 

gi. 

            v_cnt <= v_cnt+1 ;

gj. 

gk. 

   end

gl. 

gm. 

end

gn. 

go. 

assign add_v_cnt = end_h_cnt;

gp. 

gq. 

assign end_v_cnt = add_v_cnt  && v_cnt == (TVB + TVD + TVFP)-1 ;

gr. 

gs. 

 

gt. 

gu. 

/*******************************************************/

gv. 

gw. 

    //dclk

gx. 

gy. 

    assign lcd_dclk = clk;

gz. 

ha. 

 

hb. 

hc. 

    //hsync

hd. 

he. 

    always  @(posedge clk or negedge rst_n)begin

hf. 

hg. 

        if(rst_n==1'b0)begin

hh. 

hi. 

            hys <= 0;

hj. 

hk. 

        end

hl. 

hm. 

        else if(add_h_cnt && h_cnt==THPW-1)begin

hn. 

ho. 

            hys <= 1;

hp. 

hq. 

        end

hr. 

hs. 

        else if(end_h_cnt)begin

ht. 

hu. 

            hys <= 0;

hv. 

hw. 

        end

hx. 

hy. 

    end

hz. 

ia. 

 

ib. 

ic. 

 

id. 

ie. 

    //vsync

if. 

ig. 

    always  @(posedge clk or negedge rst_n)begin

ih. 

ii. 

        if(rst_n==1'b0)begin

ij. 

ik. 

            vys <= 0;

il. 

im. 

        end

in. 

io. 

        else if(add_v_cnt && v_cnt==TVPW-1)begin

ip. 

iq. 

            vys <= 1;

ir. 

is. 

        end

it. 

iu. 

        else if(end_v_cnt)begin

iv. 

iw. 

            vys <= 0;

ix. 

iy. 

        end

iz. 

ja. 

    end

jb. 

jc. 

   

jd. 

je. 

 

jf. 

jg. 

    //lcd_de

jh. 

ji. 

    always  @(posedge clk or negedge rst_n)begin

jj. 

jk. 

        if(rst_n==1'b0)begin

jl. 

jm. 

            lcd_de <= 0;

jn. 

jo. 

        end

jp. 

jq. 

        else if(active_area)begin

jr. 

js. 

            lcd_de <= 1;

jt. 

ju. 

        end

jv. 

jw. 

        else begin

jx. 

jy. 

            lcd_de <= 0;

jz. 

ka. 

        end

kb. 

kc. 

    end

kd. 

ke. 

   

kf. 

kg. 

 

kh. 

ki. 

/********************************************************************/   

kj. 

kk. 

 

kl. 

km. 

 

kn. 

ko. 

 

kp. 

kq. 

assign active_area = h_cnt>=(THB-1) && h_cnt<(THB+THD-1) && v_cnt>=(TVB-1) && v_cnt<(TVB+TVD-1);

kr. 

ks. 

 

kt. 

ku. 

 

kv. 

kw. 

always  @(*)begin

kx. 

ky. 

    logo_rom_area = h_cnt >=LOGO_X0 && h_cnt < LOGO_X1 && v_cnt >= LOGO_Y0 && v_cnt < LOGO_Y1;

kz. 

la. 

end

lb. 

lc. 

 

ld. 

le. 

always  @(*)begin

lf. 

lg. 

    e_rom_area = h_cnt >=E_X0 && h_cnt < E_X1 && v_cnt >= E_Y0 && v_cnt < E_Y1;

lh. 

li. 

end

lj. 

lk. 

 

ll. 

lm. 

 

ln. 

lo. 

 

lp. 

lq. 

always  @(posedge clk or negedge rst_n)begin

lr. 

ls. 

    if(rst_n==1'b0)begin

lt. 

lu. 

        lcd_rgb <= 0;

lv. 

lw. 

    end

lx. 

ly. 

    else if(active_area)begin

lz. 

ma. 

        if(logo_rom_area)

mb. 

mc. 

            lcd_rgb <= {logo_rom_data[7:5],5'b11111,logo_rom_data[4:2],5'b11111,logo_rom_data[1:0],6'b111111};

md. 

me. 

        else if(e_rom_area)

mf. 

mg. 

            lcd_rgb <= {24{e_sel}};

mh. 

mi. 

        else

mj. 

mk. 

            lcd_rgb <= {24{1'b1}};

ml. 

mm. 

    end

mn. 

mo. 

    else begin

mp. 

mq. 

        lcd_rgb <=0;

mr. 

ms. 

    end

mt. 

mu. 

end

mv. 

mw. 

 

mx. 

my. 

 

mz. 

na. 

 

nb. 

nc. 

 

nd. 

ne. 

always  @(*)begin

nf. 

ng. 

    logo_rom_addr = (h_cnt-LOGO_X0) + 120*(v_cnt-LOGO_Y0);

nh. 

ni. 

end

nj. 

nk. 

 

nl. 

nm. 

always  @(*)begin

nn. 

no. 

    e_rom_addr = (h_cnt-E_X0) + 400*(v_cnt-E_Y0);

np. 

nq. 

end

nr. 

ns. 

 

nt. 

nu. 

 

nv. 

nw. 

 

nx. 

ny. 

always  @(posedge clk or negedge rst_n)begin

nz. 

oa. 

    if(rst_n==1'b0)begin

ob. 

oc. 

        e_rom_addr_low <= 0;

od. 

oe. 

    end

of. 

og. 

    else begin

oh. 

oi. 

        e_rom_addr_low <= e_rom_addr[2:0];

oj. 

ok. 

    end

ol. 

om. 

end

on. 

oo. 

 

op. 

oq. 

 

or. 

os. 

always  @(*)begin

ot. 

ou. 

    e_sel = ~e_rom_data[7-e_rom_addr_low];

ov. 

ow. 

end

ox. 

oy. 

 

oz. 

pa. 

 

pb. 

pc. 

fpga_rom u_fpga_rom(

pd. 

pe. 

                   .address (logo_rom_addr),

pf. 

pg. 

                   .clock   (clk     ),

ph. 

pi. 

                   .q       (logo_rom_data));

pj. 

pk. 

 

pl. 

pm. 

e_rom u_e_rom(

pn. 

po. 

    .address   (e_rom_addr[16:3]  ),

pp. 

pq. 

    .clock     (clk  ),

pr. 

ps. 

    .q         (e_rom_data  ));

pt. 

pu. 

 

pv. 

pw. 

 

px. 

py. 

    endmodule

pz. 

复制代码


1.5 效果和总结

以下为工程上板后的现象效果图:


mp801开发板

image.png

ms980试验箱

image.png

设计视频和源工程代码请到论坛下载学习:http://www.fpgabbs.cn/thread-1162-1-1.html

访问明德扬论坛(http://www.fpgabbs.cn/)进行更多FPGA相关工程设计学习。



温馨提示:明德扬2023推出了全新课程——逻辑设计基本功修炼课,降低学习FPGA门槛的同时,增加了学习的趣味性,并组织了考试赢积分活动

http://www.mdy-edu.com/ffkc/415.html

(点击→了解课程详情☝)感兴趣请联系易老师:13112063618(微信同步)



本文TAG:

Copyright © 2012-2023 版权所有:深圳明德扬科技教育有限公司