chop147的个人空间 https://blog.eetop.cn/1468735 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

【案例】 LCD显示叠加图片

已有 264 次阅读| 2022-6-30 11:53 |个人分类:书籍文章分享|系统分类:芯片设计| fpga

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


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模块实现功能

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参考代码
  1. module top_mdyLcdPicOverlay(

  2.     clk       ,

  3.     rst_n     ,

  4.     hys       ,

  5.     vys       ,

  6.     lcd_de    ,

  7.     lcd_rgb   ,

  8.     lcd_dclk

  9.     );


  10.     parameter   PICTURE_W = 24  ;


  11.     input                   clk         ;

  12.     input                   rst_n       ;

  13.     output                  hys         ;

  14.     output                  vys         ;

  15.     output                  lcd_de      ;

  16.     output  [PICTURE_W-1:0] lcd_rgb     ;

  17.     output                  lcd_dclk    ;

  18.    


  19.     wire                     clk_0      ;

  20.    

  21.     wire                     hys        ;

  22.     wire                     vys        ;

  23.     wire                     lcd_de     ;

  24.     wire   [PICTURE_W-1:0]   lcd_rgb    ;

  25.     wire                     lcd_dclk   ;



  26. //40MHz

  27. pll_40m u_pll_40m(

  28.             .areset     (~rst_n ),

  29.         .inclk0     (clk    ),

  30.             .c0         (clk_0  )

  31.     );



  32. lcd_driver  u2(

  33.    .clk          (clk_0       ),//40MHz

  34.    .rst_n        (rst_n       ),

  35.                           

  36.    .hys          (hys         ),  

  37.    .vys          (vys         ),  

  38.    .lcd_de       (lcd_de      ),                  

  39.    .lcd_rgb      (lcd_rgb     ),

  40.    .lcd_dclk     (lcd_dclk    )

  41.     );


  42. endmodule

复制代码


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参考代码
  1. module lcd_driver(

  2.     clk          ,//40MHz

  3.     rst_n        ,


  4.     hys          ,

  5.     vys          ,

  6.     lcd_de       ,  

  7.     lcd_rgb      ,

  8.     lcd_dclk   

  9. );


  10.    input                    clk             ;

  11.    input                    rst_n           ;


  12.    output                   hys             ;

  13.    output                   vys             ;

  14.    output                   lcd_de          ;

  15.    output [23:0]            lcd_rgb         ;

  16.    output                   lcd_dclk        ;


  17.    reg                      hys             ;

  18.    reg                      vys             ;

  19.    reg                      lcd_de          ;

  20.    reg    [23:0]            lcd_rgb         ;

  21.    wire                     lcd_dclk        ;


  22.    //1056

  23.    parameter         THPW      = 20         ;   

  24.    parameter         THB       = 46         ;   

  25.    parameter         THD       = 800        ;   

  26.    parameter         THFP      = 210        ;   

  27.    

  28.    //525

  29.    parameter         TVPW      = 10         ;   

  30.    parameter         TVB       = 23         ;   

  31.    parameter         TVD       = 480        ;   

  32.    parameter         TVFP      = 22         ;   


  33.    parameter       HDE_CENTRE  = THD/2      ;//400

  34.    parameter       VDE_CENTRE  = TVD/2      ;//240


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

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

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

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


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

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

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

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


  43.    reg   [ 10:0]            h_cnt           ;

  44.    wire                     add_h_cnt       ;

  45.    wire                     end_h_cnt       ;

  46.    reg   [ 9:0]             v_cnt           ;

  47.    wire                     add_v_cnt       ;

  48.    wire                     end_v_cnt       ;



  49.    wire                     active_area     ;

  50.    reg                      logo_rom_area        ;

  51.    reg      [15:0]          logo_rom_addr        ;

  52.    wire     [7:0]           logo_rom_data        ;

  53.    reg                      e_rom_area        ;

  54.    reg      [17:0]          e_rom_addr        ;

  55.    wire     [7:0]           e_rom_data        ;

  56.    reg      [2:0]           e_rom_addr_low    ;

  57.    reg                      e_sel             ;

  58.    



  59. always @(posedge clk or negedge rst_n) begin

  60.     if (rst_n==0) begin

  61.         h_cnt <= 0;

  62.     end

  63.     else if(add_h_cnt) begin

  64.         if(end_h_cnt)

  65.             h_cnt <= 0;

  66.         else

  67.             h_cnt <= h_cnt+1 ;

  68.    end

  69. end

  70. assign add_h_cnt = 1;

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




  72. always @(posedge clk or negedge rst_n) begin

  73.     if (rst_n==0) begin

  74.         v_cnt <= 0;

  75.     end

  76.     else if(add_v_cnt) begin

  77.         if(end_v_cnt)

  78.             v_cnt <= 0;

  79.         else

  80.             v_cnt <= v_cnt+1 ;

  81.    end

  82. end

  83. assign add_v_cnt = end_h_cnt;

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


  85. /*******************************************************/

  86.     //dclk

  87.     assign lcd_dclk = clk;


  88.     //hsync

  89.     always  @(posedge clk or negedge rst_n)begin

  90.         if(rst_n==1'b0)begin

  91.             hys <= 0;

  92.         end

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

  94.             hys <= 1;

  95.         end

  96.         else if(end_h_cnt)begin

  97.             hys <= 0;

  98.         end

  99.     end



  100.     //vsync

  101.     always  @(posedge clk or negedge rst_n)begin

  102.         if(rst_n==1'b0)begin

  103.             vys <= 0;

  104.         end

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

  106.             vys <= 1;

  107.         end

  108.         else if(end_v_cnt)begin

  109.             vys <= 0;

  110.         end

  111.     end

  112.    


  113.     //lcd_de

  114.     always  @(posedge clk or negedge rst_n)begin

  115.         if(rst_n==1'b0)begin

  116.             lcd_de <= 0;

  117.         end

  118.         else if(active_area)begin

  119.             lcd_de <= 1;

  120.         end

  121.         else begin

  122.             lcd_de <= 0;

  123.         end

  124.     end

  125.    


  126. /********************************************************************/   




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



  128. always  @(*)begin

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

  130. end


  131. always  @(*)begin

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

  133. end




  134. always  @(posedge clk or negedge rst_n)begin

  135.     if(rst_n==1'b0)begin

  136.         lcd_rgb <= 0;

  137.     end

  138.     else if(active_area)begin

  139.         if(logo_rom_area)

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

  141.         else if(e_rom_area)

  142.             lcd_rgb <= {24{e_sel}};

  143.         else

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

  145.     end

  146.     else begin

  147.         lcd_rgb <=0;

  148.     end

  149. end





  150. always  @(*)begin

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

  152. end


  153. always  @(*)begin

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

  155. end




  156. always  @(posedge clk or negedge rst_n)begin

  157.     if(rst_n==1'b0)begin

  158.         e_rom_addr_low <= 0;

  159.     end

  160.     else begin

  161.         e_rom_addr_low <= e_rom_addr[2:0];

  162.     end

  163. end



  164. always  @(*)begin

  165.     e_sel = ~e_rom_data[7-e_rom_addr_low];

  166. end



  167. fpga_rom u_fpga_rom(

  168.                    .address (logo_rom_addr),

  169.                    .clock   (clk     ),

  170.                    .q       (logo_rom_data));


  171. e_rom u_e_rom(

  172.     .address   (e_rom_addr[16:3]  ),

  173.     .clock     (clk  ),

  174.     .q         (e_rom_data  ));



  175.     endmodule

复制代码


1.5 效果和总结

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


mp801开发板



ms980试验箱




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

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


需要更多案例请联系易老师领取:13112063618

明德扬科技教育



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 7

    粉丝
  • 1

    好友
  • 4

    获赞
  • 2

    评论
  • 419

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-3-29 19:11 , Processed in 0.021360 second(s), 15 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部