请选择 进入手机版 | 继续访问电脑版

明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 7085|回复: 0

至简设计系列_上位机控制LCD显示放大和缩小图片

[复制链接]
发表于 2020-11-22 00:47:51 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
至简设计系列_上位机控制LCD显示放大和缩小图片


--作者:肖肖肖

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

1.1.2 设计目标

1.        在7寸LCD显示屏上实现明德扬LOGO图标的左上角显示和大写字母“E”图片的居中显示;
2.        可以选择使用上位机还是按键来控制“E”图片的放大和缩小;
3.        并且统计1秒时间图像的帧率。

1.1.3 系统结构框图
系统结构框图如下所示:
01.JPG
                              图一
1.1.4模块功能
以下本工程所用到的所有模块中,除了PicZoomInAndOut模块都是明德扬提供的可用的IP模块,这些模块不允许修改避免调用IP模块使用时出现问题。

mdyPllAltera模块实现功能
1.        将输入的50MHz时钟分频输出40MHz的时钟。

mdyRom模块实现功能
1.        存储明德扬LOGO图标数据;
2.        存储大小字母“E”图像数据。


mdyCfg模块实现功能
top_uart_cfg
1.        对接收的数据进行串并转换;
2.        对发送的数据进行并串转换。
mdyCfgCtrl
1.        对传输的指令进行解析。


mdyKey模块实现功能
1.        检测按下的按键并输出对应按键有效的数值。


PicZoomInAndOut模块实现功能
1.        规定了明德扬LOGO图标和大写字母“E”显示的区域;
2.        控制大写字母“E”显示的放大和缩小。

mdyLcd驱动模块实现功能
1、  产生驱动LCD屏显示的时序。

mdyGetEdge模块实现功能
1.        对信号的边沿进行检测。

mdyStatic_1S模块实现功能
1.        统计一段时间内的某些信号的数据。

1.1.5顶层信号
  
信号名
  
I/O
位宽
定义
clk
I
1
系统工作时钟 50M
rst_n
I
1
系统复位信号,低电平有效
key
I
4
独立按键输入信号
uart_rxd
I
1
串口接收接口信号
uart_txd
O
1
串口发送接口信号
lcd_hs
O
1
LCD 行时序信号
lcd_vs
O
1
LCD 场时序信号
lcd_de
O
1
LCD 数据输入使能信号
lcd_dat
O
24
LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
lcd_clk
O
1
LCD 数据采样时钟



1.1.6参考代码
  1. module top_mdyLcdPicZoomInAndOut(
  2.     clk       ,
  3.     rst_n     ,
  4.     key       ,
  5.     uart_rxd  ,
  6.          
  7.     uart_txd  ,
  8.     lcd_hs    ,
  9.     lcd_vs    ,
  10.     lcd_de    ,
  11.     lcd_dat   ,
  12.     lcd_clk   
  13.     );

  14.     parameter   PICTURE_W   = 24  ;
  15.     parameter   KEY_W       =  4  ;


  16.     input                   clk          ;//50MHz
  17.     input                   rst_n        ;
  18.     input   [KEY_W-1 :0]    key          ;
  19.     input                   uart_rxd     ;
  20.                                  
  21.     output                  uart_txd     ;
  22.     output                  lcd_hs       ;
  23.     output                  lcd_vs       ;
  24.     output                  lcd_de       ;
  25.     output  [PICTURE_W-1:0] lcd_dat      ;
  26.     output                  lcd_clk      ;

  27.     wire                     uart_txd    ;
  28.     wire                     lcd_hs      ;
  29.     wire                     lcd_vs      ;
  30.     wire                     lcd_de      ;
  31.     wire   [PICTURE_W-1:0]   lcd_dat     ;
  32.     wire                     lcd_clk     ;

  33.     wire                     clk_0       ;
  34.     wire    [23:0]           pic_data    ;
  35.     wire    [10:0]           req_x       ;
  36.     wire    [ 9:0]           req_y       ;
  37.     wire                     frame_start ;
  38.     wire    [KEY_W-1:0]      key_vld     ;
  39.     wire                     frame_pos   ;
  40.     wire    [63:0]           uart_dout         ;
  41.     wire                     uart_dout_vld     ;
  42.     wire    [63:0]           cfgCtrl_dout      ;
  43.     wire                     cfgCtrl_dout_vld  ;

  44.     `include "mdyCfg_wire.v"

  45. /******************   PLL模块  *******************************/

  46. mdyPllAltera#(.C0_M(4),.C0_D(5)) u1_pll_40m(
  47.     .areset    (~rst_n   ), //高电平有效
  48.     .inclk0    (clk     ),
  49.     .c0        (clk_0   ),
  50.     .c1        (     ),
  51.     .c2        (     ),
  52.     .c3        (     ),
  53.     .c4        (     ),
  54.     .locked    (     )

  55. );

  56. /******************   LCD驱动模块  *******************************/

  57. mdyLcd#(.D_DLY(1))  u2_lcd_driver(
  58.    .clk          (clk_0       ),//40MHz
  59.    .rst_n        (rst_n       ),
  60.    .ack_data     (pic_data    ),
  61.                           
  62.    .req_x        (req_x       ),  
  63.    .req_y        (req_y       ),  
  64.    .req_en       (    ),                  
  65.    .req_addr     (    ),
  66.    
  67.    .hys          (lcd_hs         ),  
  68.    .vys          (lcd_vs         ),  
  69.    .lcd_de       (lcd_de      ),                  
  70.    .lcd_rgb      (lcd_dat     ),
  71.    .lcd_dclk     (lcd_clk    ),
  72.    
  73.    .frame_start  (frame_start )
  74.     );

  75. /******************  功能模块  *******************************/

  76. PicZoomInAnDout u3_PicZoomInAnDout(
  77.    .clk              (clk_0   ),
  78.    .rst_n            (rst_n   ),
  79.    .mode             (MODE_SELECT_en),
  80.    .key_en           (key_vld ),
  81.    .cpu_ZoomIn       (SOFTWARE_CTRL_in),
  82.    .cpu_ZoomOut      (SOFTWARE_CTRL_out),

  83.    .req_h            (req_x   ),   
  84.    .req_v            (req_y   ),
  85.    .pic_data         (pic_data       )
  86.    
  87.     );


  88. /*********************  按键模块 ****************************/

  89. mdyKey#(.DATA_W(24),.TIME_20MS(8_00_000)) u4_mdykey(
  90.     .clk        (clk_0   ),
  91.     .rst_n      (rst_n   ),
  92.     .key_in     (key  ),
  93.     .key_vld    (key_vld )
  94. );
  95. /*********************  边沿检测模块  ****************************/

  96. mdyGetEdge  u5_GetEdge(
  97.     .clk              (clk_0   ),
  98.     .rst_n            (rst_n   ),
  99.     .cfg_init_value   (0   ),
  100.     .din              (frame_start   ),
  101.     .dout_pos         (frame_pos),
  102.     .dout_neg         (   ),
  103.     .dout_pos_reg     (   ),
  104.     .dout_neg_reg     (   )
  105.     );

  106. /*********************  1s统计模块  ****************************/

  107. mdyStatic_1S    u6_Static_1S(
  108.     .clk          (clk_0   ),
  109.     .rst_n        (rst_n   ),
  110.     .cfg_num_1s   (50_000_000   ),
  111.     .cfg_add_1s   (1            ),
  112.     .din_vld      (frame_pos    ),
  113.     .sta_1s       (DATA_FRAME_data   ),//32bit
  114.     .sta_rt       (   )  
  115. );

  116. /*********************  指令模块  ****************************/

  117. top_uart_cfg#(.BPS(4167)) u7_top_uart_cfg(
  118.     .clk      (clk_0             ),
  119.     .rst_n    (rst_n             ),
  120.     .cfg_head (16'h55d5          ),
  121.     .rx       (uart_rxd           ),
  122.     .tx       (uart_txd           ),
  123.     .din      (cfgCtrl_dout      ),//s2p
  124.     .din_vld  (cfgCtrl_dout_vld  ),
  125.     .din_rdy  (                  ),
  126.     .dout     (uart_dout         ),//p2s
  127.     .dout_vld (uart_dout_vld     )   

  128. );

  129. mdyCfgCtrl u8_mdyCfgCtrl(
  130.     `include "mdyCfg_inst.v"
  131.     .clk         (clk_0              ),
  132.     .rst_n       (rst_n              ),
  133.     .din         (uart_dout          ),
  134.     .din_vld     (uart_dout_vld      ),
  135.     .dout        (cfgCtrl_dout       ),
  136.     .dout_vld    (cfgCtrl_dout_vld   )  

  137. );

  138. /*************************************************/
  139. endmodule
复制代码


1.2 mdyPllAltera模块接口说明


1.2.1接口信号
  
信号名
  
I/O
位宽
定义
areset
I
1
PLL复位信号,高电平有效
inclk0
I
1
PLL输入时钟 50MHz
c0
O
1
PLL输出时钟 40MHz

1.2.2 使用说明
本模块主要用于产生LCD驱动时序所需要的时钟,关于mdyPllAltera模块的使用详细介绍请看下方链接:


1.3 mdyRom模块设计
1.3.1接口信号
  
信号名
  
I/O
位宽
定义
address
I
16
ROM数据存放地址
clock
I
1
ROM工作时钟40MHz
q
O
8
ROM输出数据

1.3.2设计思路
本模块主要用于存储明德扬LOGO图标和大小字母“E”图像的数据,关于mdyRom模块的使用详细介绍请看下方链接:

1.4 mdyCfg模块接口说明
1.4.1接口信号
top_uart_cfg模块的接口信号:
  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
cfg_head
I
16
输入指令头数据,指令头为16’h55d5
rx
I
1
串口接收数据信号
tx
I
1
串口发送数据信号
din
I
64
输入FPGA指令数据
din_vld
I
1
输入FPGA指令数据有效指示信号
dout
O
64
输出PC指令数据
dout_vld
O
1
输出PC指令数据有效指示信号


mdyCfgCtrl模块的接口信号:

  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
din
I
64
输出PC指令数据
din_vld
I
1
输出PC指令数据有效指示信号
dout
O
64
输入FPGA指令数据
dout_vld
O
1
输入FPGA指令数据有效指示信号
DATA_FRAME_data
I
32
输出帧率数据
MODE_SELECT_en
O
1
对图片的放大和缩小控制模式选择,复位值为0,表示按键控制;1,表示上位机控制。
SOFTWARE_CTRL_in
O
1
放大控制
SOFTWARE_CTRL_out
O
1
缩小控制

1.4.2 使用说明
本模块主要用于对传输的数据进行串并转换和解析传输的指令,关于mdyCfg模块的使用详细介绍请看下方链接:
关于具体的指令信息可以查看工程里的XML表格regTable_mdyLcdPicZoomInAndOut.xml
上位机指令全长64bit,其中,
  
指令段
  
位宽
定义
[63:48]
16
指令头,固定为16’h55d5
[47]
1
读/写控制位,0表示写寄存器,1表示读寄存器
[46:32]
15
寄存器地址
[31:0]
32
数据

02.png

1.5 mdyKey模块接口说明
1.5.1接口信号
下面为使用独立按键时的接口信号:
  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
key_in
I
4
按键输入信号
key_vld
O
4
按键有效指示信号,4’b0001表示按键S1按下,控制放大,4’b0010表示按键S2按下,控制缩小。

1.5.2使用说明
本模块主要检测按下的按键并输出对应按键的有效指示信号,关于mdyKey模块的使用详细介绍请看下方链接:

1.6 PicZoomInAndOut模块接口说明
1.6.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
mode
I
1
对图片的放大和缩小控制模式选择,复位值为0,表示按键控制;1,表示上位机控制。
key_en
I
4
按键有效指示信号,4’b0001表示按键S1按下,控制放大,4’b0010表示按键S2按下,控制缩小。
cpu_ZoomIn
I
1
上位机控制住图片放大指示信号
cpu_ZoomOut
I
1
上位机控制住图片缩小指示信号
req_h
I
11
LCD显示屏有效显示区域每一行的某一像素指示信号
req_v
I
10
LCD显示屏有效显示区域某一行指示信号
pic_data
O
24
输出显示图像数据,格式为RGB888

1.6.2参考代码
  1. module PicZoomInAnDout(
  2.     clk               ,
  3.     rst_n             ,
  4.     mode              ,
  5.     key_en            ,
  6.     cpu_ZoomIn        ,   
  7.     cpu_ZoomOut       ,
  8.                
  9.     req_h             ,//h_cnt - THB   
  10.     req_v             ,//v_cnt - TVB
  11.     pic_data         
  12.     );

  13.     //LCD显示屏居中
  14.     parameter       HDE_CENTRE  = 400      ;//800/2
  15.     parameter       VDE_CENTRE  = 240      ;//480/2


  16.     parameter      DATA_W    =         8;
  17.     parameter      KEY_W     =         4;

  18.     //输入信号定义
  19.     input                       clk          ;
  20.     input                       rst_n        ;
  21.     input                       mode         ;
  22.     input                       cpu_ZoomIn   ;
  23.     input                       cpu_ZoomOut  ;
  24.     input   [KEY_W-1 :0]        key_en       ;

  25.     //输出信号定义
  26.     input   [10:0]              req_h        ;
  27.     input   [ 9:0]              req_v        ;
  28.     output  [23:0]              pic_data     ;

  29.     //输出信号reg定义
  30.     reg     [23:0]              pic_data     ;
  31.    
  32.     //中间信号
  33.     reg     [15:0]              logo_rom_addr   ;
  34.     reg                         logo_rom_area   ;
  35.     wire    [7:0]               logo_rom_data   ;
  36.     reg     [17:0]              e_rom_addr      ;
  37.     reg                         e_rom_area      ;
  38.     reg      [2:0]              e_rom_addr_low  ;
  39.     reg                         e_dataout       ;
  40.     wire    [7:0]               e_rom_data      ;
  41.                                                 
  42.     reg     [ 2:0]              size            ;
  43.     reg     [ 2:0]              size_ff0        ;

  44.     wire    [9:0]               len_size        ;
  45.     wire    [9:0]               wid_size        ;
  46.     wire    [9:0]               e_x0            ;
  47.     wire    [9:0]               e_x1            ;
  48.     wire    [9:0]               e_y0            ;
  49.     wire    [9:0]               e_y1            ;
  50.     wire    [9:0]               x               ;
  51.     wire    [9:0]               y               ;

  52. /******************************************************/




  53. always  @(posedge clk or negedge rst_n)begin
  54.     if(rst_n==1'b0)begin
  55.         size <= 0;
  56.     end
  57.     else if(mode==1)begin
  58.         if(cpu_ZoomOut)begin
  59.             if(size!=3)
  60.                 size <= size + 1;
  61.         end
  62.         else if(cpu_ZoomIn)begin
  63.             if(size!=0)
  64.                 size <= size - 1;
  65.         end
  66.     end
  67.     else if(mode==0)begin
  68.         if(key_en==4'b0010)begin
  69.             if(size!=3)
  70.                 size <= size + 1;
  71.         end
  72.         else if(key_en==4'b0001)begin
  73.             if(size!=0)
  74.                 size <= size - 1;
  75.         end
  76.     end
  77. end

  78. always  @(posedge clk or negedge rst_n)begin
  79.     if(rst_n==1'b0)begin
  80.         size_ff0 <= 0;
  81.     end
  82.     else if(req_h==(HDE_CENTRE-200) && req_v==(VDE_CENTRE-150)) begin
  83.         size_ff0 <= size;
  84.     end
  85. end

  86. assign len_size = 400 >> size_ff0;//缩小多少倍
  87. assign wid_size = 300 >> size_ff0;


  88. assign   e_x0 = (HDE_CENTRE-len_size[9:1]);
  89. assign   e_x1 = (HDE_CENTRE+len_size[9:1]);
  90. assign   e_y0 = (VDE_CENTRE-wid_size[9:1]);
  91. assign   e_y1 = (VDE_CENTRE+wid_size[9:1]);

  92. assign x = (req_h-e_x0)<<size;
  93. assign y = (req_v-e_y0)<<size;




  94. always  @(*)begin
  95.     e_rom_area = req_h >=(e_x0+5) && req_h < e_x1 && req_v >= e_y0 && req_v < (e_y1+5);
  96. end

  97. always  @(*)begin
  98.     e_rom_addr = x + 400*y;
  99. end



  100. /******************************************************/
  101.    
  102. //120*55
  103. always  @(*)begin
  104.     logo_rom_area = req_h >=0 && req_h < 119 && req_v >= 0 && req_v < 54;
  105. end

  106. always  @(*)begin
  107.     logo_rom_addr = req_h + 120*req_v;
  108. end


  109. /******************************************************/

  110. always  @(posedge clk or negedge rst_n)begin
  111.     if(rst_n==1'b0)begin
  112.         e_rom_addr_low <= 0;
  113.     end
  114.     else begin
  115.         e_rom_addr_low <= e_rom_addr[2:0];
  116.     end
  117. end

  118. always  @(*)begin
  119.     if(e_rom_area)
  120.         e_dataout = ~e_rom_data[7-e_rom_addr_low];
  121.     else
  122.         e_dataout = 1;
  123. end

  124. always  @(posedge clk or negedge rst_n)begin
  125.     if(rst_n==1'b0)begin
  126.         pic_data <= 0;
  127.     end
  128.     else if(e_rom_area)begin
  129.         pic_data <= {24{e_dataout}};
  130.     end
  131.     else if(logo_rom_area)begin
  132.         pic_data <= {logo_rom_data[7:5],5'b11111,logo_rom_data[4:2],5'b11111,logo_rom_data[1:0],6'b111111} ;
  133.     end
  134. end

  135. /******************************************************/
  136. mdyRom#(.MIF("../src/data/logo.mif"),.DEP(8192),.D_W(8))  u_fpga_rom(
  137.     .address  (logo_rom_addr   ),
  138.     .clock    (clk   ),
  139.     .q        (logo_rom_data   )
  140. );

  141. mdyRom#(.MIF("../src/data/e.mif"),.DEP(16384),.D_W(8))  u_e_rom(
  142.     .address  (e_rom_addr[16:3]   ),
  143.     .clock    (clk   ),
  144.     .q        (e_rom_data   )
  145. );

  146.     endmodule
复制代码


1.7 mdyLcd驱动模块设计1.7.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
模块工作时钟 40MHz
rst_n
I
1
系统复位信号,低电平有效
ack_data
I
24
输入的图像有效显示数据
req_x
O
11
输出的LCD显示屏有效显示区域每一行某一像素点指示信号
req_y
O
10
输出的LCD显示屏有效显示区域某一行指示信号
frame_start
O
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.7.1使用说明
本模块主要用于产生LCD显示屏的驱动时序,关于mdyLcd模块的使用详细介绍请看下方链接:


1.8 mdyGetEdge模块接口说明


1.8.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
cfg_init_value
I
1
检测边沿的初始值,初始值为0
din
I
1
输入的检测信号,图像帧开始指示信号
dout_pos
O
1
输出的上升沿检测有效指示信号

1.8.2使用说明
本模块主要用于检测特定信号的边沿,关于mdyGetEdge模块的使用详细介绍请看下方链接:

1.9 mdyStatic_1S模块接口说明
1.9.1接口信号
  
信号名
  
I/O
位宽
定义
clk
I
1
输入时钟信号,40MHz
rst_n
I
1
输入复位信号,低电平有效
cfg_num_1s
I
32
多少时间统计一次对应的时钟个数
cfg_add_1s
I
8
统计一次增加多少数值
din_vld
I
1
输入的上升沿检测有效指示信号
sta_1s
O
32
输出的规定时间内统计的数据

1.9.2使用说明
本模块主要用于统计数据,关于mdyStatic_1S模块的使用详细介绍请看下方链接:

1.10 效果和总结
以下为工程上板后的现象效果图:
mp801开发板——缩小0
03.jpg


mp801开发板——缩小1

04.jpg

mp801开发板——缩小2

05.jpg

mp801开发板——缩小3

06.jpg

感兴趣的朋友也可以访问明德扬论坛(http://www.fpgabbs.cn/)进行FPGA相关工程设计学习,也可以看一下我们往期的文章:

1.11 公司简介
明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801
开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。

【设计教程下载】 至简设计系列_LCD显示放大和缩小图片.pdf (1.17 MB, 下载次数: 780)
FPGA视频课程  培训班 FPGA学习资料
吴老师 18022857217(微信同号) Q1241003385
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号 )

GMT+8, 2024-3-29 19:22 , Processed in 0.060249 second(s), 25 queries .

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表