明德扬吴老师 发表于 2020-11-22 00:47:51

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

至简设计系列_上位机控制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 系统结构框图系统结构框图如下所示:                              图一1.1.4模块功能
以下本工程所用到的所有模块中,除了PicZoomInAndOut模块都是明德扬提供的可用的IP模块,这些模块不允许修改避免调用IP模块使用时出现问题。
mdyPllAltera模块实现功能1.      将输入的50MHz时钟分频输出40MHz的时钟。
mdyRom模块实现功能1.      存储明德扬LOGO图标数据;2.      存储大小字母“E”图像数据。

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

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

PicZoomInAndOut模块实现功能1.      规定了明德扬LOGO图标和大写字母“E”显示的区域;2.      控制大写字母“E”显示的放大和缩小。
mdyLcd驱动模块实现功能1、产生驱动LCD屏显示的时序。
mdyGetEdge模块实现功能1.      对信号的边沿进行检测。
mdyStatic_1S模块实现功能1.      统计一段时间内的某些信号的数据。
1.1.5顶层信号
信号名I/O位宽定义
clkI1系统工作时钟 50M
rst_nI1系统复位信号,低电平有效
keyI4独立按键输入信号
uart_rxdI1串口接收接口信号
uart_txdO1串口发送接口信号
lcd_hsO1LCD 行时序信号
lcd_vsO1LCD 场时序信号
lcd_deO1LCD 数据输入使能信号
lcd_datO24LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
lcd_clkO1LCD 数据采样时钟



1.1.6参考代码module top_mdyLcdPicZoomInAndOut(
    clk       ,
    rst_n   ,
    key       ,
    uart_rxd,
         
    uart_txd,
    lcd_hs    ,
    lcd_vs    ,
    lcd_de    ,
    lcd_dat   ,
    lcd_clk   
    );

    parameter   PICTURE_W   = 24;
    parameter   KEY_W       =4;


    input                   clk          ;//50MHz
    input                   rst_n      ;
    input       key          ;
    input                   uart_rxd   ;
                                 
    output                  uart_txd   ;
    output                  lcd_hs       ;
    output                  lcd_vs       ;
    output                  lcd_de       ;
    output lcd_dat      ;
    output                  lcd_clk      ;

    wire                     uart_txd    ;
    wire                     lcd_hs      ;
    wire                     lcd_vs      ;
    wire                     lcd_de      ;
    wire      lcd_dat   ;
    wire                     lcd_clk   ;

    wire                     clk_0       ;
    wire             pic_data    ;
    wire             req_x       ;
    wire    [ 9:0]         req_y       ;
    wire                     frame_start ;
    wire          key_vld   ;
    wire                     frame_pos   ;
    wire             uart_dout         ;
    wire                     uart_dout_vld   ;
    wire             cfgCtrl_dout      ;
    wire                     cfgCtrl_dout_vld;

    `include "mdyCfg_wire.v"

/******************   PLL模块*******************************/

mdyPllAltera#(.C0_M(4),.C0_D(5)) u1_pll_40m(
    .areset    (~rst_n   ), //高电平有效
    .inclk0    (clk   ),
    .c0      (clk_0   ),
    .c1      (   ),
    .c2      (   ),
    .c3      (   ),
    .c4      (   ),
    .locked    (   )

);

/******************   LCD驱动模块*******************************/

mdyLcd#(.D_DLY(1))u2_lcd_driver(
   .clk          (clk_0       ),//40MHz
   .rst_n      (rst_n       ),
   .ack_data   (pic_data    ),
                        
   .req_x      (req_x       ),
   .req_y      (req_y       ),
   .req_en       (    ),                  
   .req_addr   (    ),
   
   .hys          (lcd_hs         ),
   .vys          (lcd_vs         ),
   .lcd_de       (lcd_de      ),                  
   .lcd_rgb      (lcd_dat   ),
   .lcd_dclk   (lcd_clk    ),
   
   .frame_start(frame_start )
    );

/******************功能模块*******************************/

PicZoomInAnDout u3_PicZoomInAnDout(
   .clk            (clk_0   ),
   .rst_n            (rst_n   ),
   .mode             (MODE_SELECT_en),
   .key_en         (key_vld ),
   .cpu_ZoomIn       (SOFTWARE_CTRL_in),
   .cpu_ZoomOut      (SOFTWARE_CTRL_out),

   .req_h            (req_x   ),   
   .req_v            (req_y   ),
   .pic_data         (pic_data       )
   
    );


/*********************按键模块 ****************************/

mdyKey#(.DATA_W(24),.TIME_20MS(8_00_000)) u4_mdykey(
    .clk      (clk_0   ),
    .rst_n      (rst_n   ),
    .key_in   (key),
    .key_vld    (key_vld )
);
/*********************边沿检测模块****************************/

mdyGetEdgeu5_GetEdge(
    .clk            (clk_0   ),
    .rst_n            (rst_n   ),
    .cfg_init_value   (0   ),
    .din            (frame_start   ),
    .dout_pos         (frame_pos),
    .dout_neg         (   ),
    .dout_pos_reg   (   ),
    .dout_neg_reg   (   )
    );

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

mdyStatic_1S    u6_Static_1S(
    .clk          (clk_0   ),
    .rst_n      (rst_n   ),
    .cfg_num_1s   (50_000_000   ),
    .cfg_add_1s   (1            ),
    .din_vld      (frame_pos    ),
    .sta_1s       (DATA_FRAME_data   ),//32bit
    .sta_rt       (   )
);

/*********************指令模块****************************/

top_uart_cfg#(.BPS(4167)) u7_top_uart_cfg(
    .clk      (clk_0             ),
    .rst_n    (rst_n             ),
    .cfg_head (16'h55d5          ),
    .rx       (uart_rxd         ),
    .tx       (uart_txd         ),
    .din      (cfgCtrl_dout      ),//s2p
    .din_vld(cfgCtrl_dout_vld),
    .din_rdy(                  ),
    .dout   (uart_dout         ),//p2s
    .dout_vld (uart_dout_vld   )   

);

mdyCfgCtrl u8_mdyCfgCtrl(
    `include "mdyCfg_inst.v"
    .clk         (clk_0            ),
    .rst_n       (rst_n            ),
    .din         (uart_dout          ),
    .din_vld   (uart_dout_vld      ),
    .dout      (cfgCtrl_dout       ),
    .dout_vld    (cfgCtrl_dout_vld   )

);

/*************************************************/
endmodule


1.2 mdyPllAltera模块接口说明


1.2.1接口信号

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

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

1.3 mdyRom模块设计
1.3.1接口信号
信号名I/O位宽定义
addressI16ROM数据存放地址
clockI1ROM工作时钟40MHz
qO8ROM输出数据

1.3.2设计思路本模块主要用于存储明德扬LOGO图标和大小字母“E”图像的数据,关于mdyRom模块的使用详细介绍请看下方链接:http://www.fpgabbs.cn/thread-1192-1-1.html
1.4 mdyCfg模块接口说明
1.4.1接口信号
top_uart_cfg模块的接口信号:
信号名I/O位宽定义
clkI1输入时钟信号,40MHz
rst_nI1输入复位信号,低电平有效
cfg_headI16输入指令头数据,指令头为16’h55d5
rxI1串口接收数据信号
txI1串口发送数据信号
dinI64输入FPGA指令数据
din_vldI1输入FPGA指令数据有效指示信号
doutO64输出PC指令数据
dout_vldO1输出PC指令数据有效指示信号


mdyCfgCtrl模块的接口信号:

信号名I/O位宽定义
clkI1输入时钟信号,40MHz
rst_nI1输入复位信号,低电平有效
dinI64输出PC指令数据
din_vldI1输出PC指令数据有效指示信号
doutO64输入FPGA指令数据
dout_vldO1输入FPGA指令数据有效指示信号
DATA_FRAME_dataI32输出帧率数据
MODE_SELECT_enO1对图片的放大和缩小控制模式选择,复位值为0,表示按键控制;1,表示上位机控制。
SOFTWARE_CTRL_inO1放大控制
SOFTWARE_CTRL_outO1缩小控制

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


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

1.5.2使用说明本模块主要检测按下的按键并输出对应按键的有效指示信号,关于mdyKey模块的使用详细介绍请看下方链接:http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=1181&fromuid=100105
1.6 PicZoomInAndOut模块接口说明
1.6.1接口信号

信号名I/O位宽定义
clkI1输入时钟信号,40MHz
rst_nI1输入复位信号,低电平有效
modeI1对图片的放大和缩小控制模式选择,复位值为0,表示按键控制;1,表示上位机控制。
key_enI4按键有效指示信号,4’b0001表示按键S1按下,控制放大,4’b0010表示按键S2按下,控制缩小。
cpu_ZoomInI1上位机控制住图片放大指示信号
cpu_ZoomOutI1上位机控制住图片缩小指示信号
req_hI11LCD显示屏有效显示区域每一行的某一像素指示信号
req_vI10LCD显示屏有效显示区域某一行指示信号
pic_dataO24输出显示图像数据,格式为RGB888

1.6.2参考代码module PicZoomInAnDout(
    clk               ,
    rst_n             ,
    mode            ,
    key_en            ,
    cpu_ZoomIn      ,   
    cpu_ZoomOut       ,
               
    req_h             ,//h_cnt - THB   
    req_v             ,//v_cnt - TVB
    pic_data         
    );

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


    parameter      DATA_W    =         8;
    parameter      KEY_W   =         4;

    //输入信号定义
    input                     clk          ;
    input                     rst_n      ;
    input                     mode         ;
    input                     cpu_ZoomIn   ;
    input                     cpu_ZoomOut;
    input         key_en       ;

    //输出信号定义
    input               req_h      ;
    input   [ 9:0]            req_v      ;
    output            pic_data   ;

    //输出信号reg定义
    reg               pic_data   ;
   
    //中间信号
    reg               logo_rom_addr   ;
    reg                         logo_rom_area   ;
    wire                   logo_rom_data   ;
    reg               e_rom_addr      ;
    reg                         e_rom_area      ;
    reg                  e_rom_addr_low;
    reg                         e_dataout       ;
    wire                   e_rom_data      ;
                                                
    reg   [ 2:0]            size            ;
    reg   [ 2:0]            size_ff0      ;

    wire                   len_size      ;
    wire                   wid_size      ;
    wire                   e_x0            ;
    wire                   e_x1            ;
    wire                   e_y0            ;
    wire                   e_y1            ;
    wire                   x               ;
    wire                   y               ;

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




always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      size <= 0;
    end
    else if(mode==1)begin
      if(cpu_ZoomOut)begin
            if(size!=3)
                size <= size + 1;
      end
      else if(cpu_ZoomIn)begin
            if(size!=0)
                size <= size - 1;
      end
    end
    else if(mode==0)begin
      if(key_en==4'b0010)begin
            if(size!=3)
                size <= size + 1;
      end
      else if(key_en==4'b0001)begin
            if(size!=0)
                size <= size - 1;
      end
    end
end

always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      size_ff0 <= 0;
    end
    else if(req_h==(HDE_CENTRE-200) && req_v==(VDE_CENTRE-150)) begin
      size_ff0 <= size;
    end
end

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


assign   e_x0 = (HDE_CENTRE-len_size);
assign   e_x1 = (HDE_CENTRE+len_size);
assign   e_y0 = (VDE_CENTRE-wid_size);
assign   e_y1 = (VDE_CENTRE+wid_size);

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




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

always@(*)begin
    e_rom_addr = x + 400*y;
end



/******************************************************/
   
//120*55
always@(*)begin
    logo_rom_area = req_h >=0 && req_h < 119 && req_v >= 0 && req_v < 54;
end

always@(*)begin
    logo_rom_addr = req_h + 120*req_v;
end


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

always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      e_rom_addr_low <= 0;
    end
    else begin
      e_rom_addr_low <= e_rom_addr;
    end
end

always@(*)begin
    if(e_rom_area)
      e_dataout = ~e_rom_data;
    else
      e_dataout = 1;
end

always@(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
      pic_data <= 0;
    end
    else if(e_rom_area)begin
      pic_data <= {24{e_dataout}};
    end
    else if(logo_rom_area)begin
      pic_data <= {logo_rom_data,5'b11111,logo_rom_data,5'b11111,logo_rom_data,6'b111111} ;
    end
end

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

mdyRom#(.MIF("../src/data/e.mif"),.DEP(16384),.D_W(8))u_e_rom(
    .address(e_rom_addr   ),
    .clock    (clk   ),
    .q      (e_rom_data   )
);

    endmodule


1.7 mdyLcd驱动模块设计1.7.1接口信号
信号名I/O位宽定义
clkI1模块工作时钟 40MHz
rst_nI1系统复位信号,低电平有效
ack_dataI24输入的图像有效显示数据
req_xO11输出的LCD显示屏有效显示区域每一行某一像素点指示信号
req_yO10输出的LCD显示屏有效显示区域某一行指示信号
frame_startO1每帧图像开始指示信号
hysO1LCD 行时序信号
vysO1LCD 场时序信号
lcd_deO1LCD 数据输出使能信号
lcd_rgbO24LCD RGB信号,RGB格式为使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
lcd_dclkO1LCD 数据采样时钟

1.7.1使用说明本模块主要用于产生LCD显示屏的驱动时序,关于mdyLcd模块的使用详细介绍请看下方链接:http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=1177&fromuid=100105

1.8 mdyGetEdge模块接口说明


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

1.8.2使用说明本模块主要用于检测特定信号的边沿,关于mdyGetEdge模块的使用详细介绍请看下方链接:http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=1190&fromuid=100105
1.9 mdyStatic_1S模块接口说明
1.9.1接口信号

信号名I/O位宽定义
clkI1输入时钟信号,40MHz
rst_nI1输入复位信号,低电平有效
cfg_num_1sI32多少时间统计一次对应的时钟个数
cfg_add_1sI8统计一次增加多少数值
din_vldI1输入的上升沿检测有效指示信号
sta_1sO32输出的规定时间内统计的数据

1.9.2使用说明本模块主要用于统计数据,关于mdyStatic_1S模块的使用详细介绍请看下方链接:http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=1188&fromuid=100105
1.10 效果和总结
以下为工程上板后的现象效果图:mp801开发板——缩小0倍


mp801开发板——缩小1倍


mp801开发板——缩小2倍


mp801开发板——缩小3倍


感兴趣的朋友也可以访问明德扬论坛(http://www.fpgabbs.cn/)进行FPGA相关工程设计学习,也可以看一下我们往期的文章:《至简设计系列_LCD入门案例_边框显示》《至简设计系列_BCD译码实现》《至简设计系列_简易计算器》《至简设计系列_基于FPGA的超声波测距系统设计》《至简设计系列_串口回环工程》《至简设计系列_LCD入门案例-动态矩形》《至简设计系列_闹钟》《至简设计系列_7段数码管显示》《阻塞赋值与非阻塞赋值》《参数例化时自动计算位宽的解决办法》
1.11 公司简介明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA。周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。
【设计教程下载】

【设计视频教程】

https://www.bilibili.com/video/BV1Af4y117H4?p=52

【工程源码】



页: [1]
查看完整版本: 至简设计系列_上位机控制LCD显示放大和缩小图片