本文为明德扬原创文章,转载请注明出处!1.1 总体设计
1.1.1 概述
液晶显示器是一-种通过液晶和色彩过滤器过滤光源,在平面面板上产生图像的数字显示器。LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置薄膜晶体管,.上基板玻璃上设置彩色滤光片,通过薄膜晶体管上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。与传统的阴极射线管相比,LCD具有占用空间小,低功耗,低辐射,无闪烁,降低视觉疲劳等优点。现在LCD已渐替代CRT成为主流,价格也已经下降了很多,并已充分的普及。本设计的主要任务是基于FPGA的LCD显示控制器设计,兼顾程序的易用性,方便此后模块的移植和应用。采用VHDL硬件描述语言在QUARTUS II软件平台上实现FPGA对LCD的控制,在LCD模块上实现任意彩色图片的显示,与此同时还须实现实时刷新数据的功能。这将有助于采用FPGA的系列产品的开发,特别是需要用到LCD而采用FPGA的产品的开发。不但缩短了FPGA的开发周期,也使更多采用FPGA设计的产品上出现LCD,增加了人机之间的交互性。
1.1.2 设计目标
此设计通过fpga给lcd发送图片信息,然后直接在LCD显示矩形动画,矩形的宽从2变化到600,矩形的高从2变化到400
1.1.3信号列表
 信号名 接口方向 定义 clk_50m 输入 系统时钟 rst_n 输入 低电平复位信号 lcd_hsync 输出 行同步信号 lcd_vsync 输出 场同步信号 lcd_de 输出 行和场同时显示时序段有效显示数据段信号 lcd_rgb 输出 显示颜色RGB[23:16]:表示的是R[7:0][15:8]:表示的是G[7:0][7:0]:表示的是B[7:0] lcd_dclk 输出 像素时钟信号
1.1.4 设计思路
设计行显示时序段和场显示时序段,来确定矩形边框的宽度,根据各种颜色的数值来确定lcd显示屏显示出的边框颜色行时钟计数器cnt_hys:用来计算行同步信号的帧长,加一条件是1,结束条件为数到1056个像素就结束场时钟计数器cnt_vys:用来计算场同步信号的帧长,加一条件是场信号每数到1056个像素(即为一行结束的时刻),结束条件为数到525行就结束
1.1.5参考代码
- module mdyLcdDispDynaRect(
 - clk_50m ,
 - rst_n ,
 - 
					
 - lcd_hsync ,
 - lcd_vsync ,
 - lcd_de ,
 - 
					
 - 
					
 - lcd_rgb ,
 - lcd_dclk
 - );
 - 
					
 - input clk_50m ;
 - input rst_n ;
 - output lcd_hsync ;
 - output lcd_vsync ;
 - output lcd_de ;
 - 
					
 - output [23:0] lcd_rgb ;
 - output lcd_dclk ;
 - 
					
 - reg [30:0] h ;
 - reg [30:0] v ;
 - reg lcd_hsync ;
 - reg lcd_vsync ;
 - 
					
 - reg [23:0] lcd_rgb ;
 - 
					
 - 
					
 - parameter LINE_PR = 1056 ;
 - parameter FRAME_PER = 525 ;
 - 
					
 - 
					
 - parameter H_SYNC = 20 ;
 - parameter V_SYNC = 10 ;
 - 
					
 - parameter HDE_START = 46 ;
 - parameter HDE_END = 846 ;
 - parameter VDE_START = 23 ;
 - parameter VDE_END = 503 ;
 - 
					
 - 
					
 - reg [12:0] cnt_hsy ;
 - reg [12:0] cnt_vsy ;
 - reg hsync_de ;
 - reg vsync_de ;
 - 
					
 - wire display_area ;
 - wire e_area ;
 - wire add_cnt_hsy ;
 - wire end_cnt_hsy ;
 - wire add_cnt_vsy ;
 - wire end_cnt_vsy ;
 - reg [ 7:0] cnt0 ;
 - wire add_cnt0 ;
 - wire end_cnt0 ;
 - reg [15:0] cnt1 ;
 - wire add_cnt1 ;
 - wire end_cnt1 ;
 - 
					
 - 
					
 - assign clk = clk_50m ;
 - assign lcd_dclk = ~ clk_50m ;
 - assign lcd_de = hsync_de & vsync_de ;
 - 
					
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - cnt_hsy <= 0;
 - end
 - else if(add_cnt_hsy)begin
 - if(end_cnt_hsy)
 - cnt_hsy <= 0;
 - else
 - cnt_hsy <= cnt_hsy + 1;
 - end
 - end
 - assign add_cnt_hsy = 1;
 - assign end_cnt_hsy = add_cnt_hsy && cnt_hsy == LINE_PR -1;
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - cnt_vsy <= 0;
 - end
 - else if(add_cnt_vsy)begin
 - if(end_cnt_vsy)
 - cnt_vsy <= 0;
 - else
 - cnt_vsy <= cnt_vsy + 1;
 - end
 - end
 - assign add_cnt_vsy = end_cnt_hsy;
 - assign end_cnt_vsy = add_cnt_vsy && cnt_vsy == FRAME_PER - 1;
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - lcd_hsync <= 1'b0 ;
 - end
 - else if(end_cnt_hsy)begin
 - lcd_hsync <= 1'b0;
 - end
 - else if(add_cnt_hsy && cnt_hsy == H_SYNC-1 )begin
 - lcd_hsync <= 1'b1;
 - end
 - end
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - hsync_de <= 1'b0;
 - end
 - else if(add_cnt_hsy && cnt_hsy == HDE_START-1)begin
 - hsync_de <= 1'b1;
 - end
 - else if(add_cnt_hsy && cnt_hsy == HDE_END-1)begin
 - hsync_de <= 1'b0;
 - end
 - end
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - lcd_vsync <= 1'b0 ;
 - end
 - else if(add_cnt_vsy && cnt_vsy == V_SYNC-1 )begin
 - lcd_vsync <= 1'b1;
 - end
 - else if(end_cnt_vsy)begin
 - lcd_vsync <= 1'b0;
 - end
 - 
					
 - end
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - vsync_de <= 1'b0;
 - end
 - else if(add_cnt_vsy && cnt_vsy == VDE_START-1)begin
 - vsync_de <= 1'b1;
 - end
 - else if(add_cnt_vsy && cnt_vsy ==VDE_END-1)begin
 - vsync_de <= 1'b0;
 - end
 - end
 - 
					
 - 
					
 - assign display_area = hsync_de && vsync_de;
 - 
					
 - 
					
 - assign blue_area = (cnt_hsy >= HDE_START + 400-h) && (cnt_hsy<HDE_START+400+h) &&
 - (cnt_vsy >= VDE_START + 240-v) && (cnt_vsy<VDE_START+240+v) ;
 - 
					
 - 
					
 - always @(posedge clk or negedge rst_n)begin
 - if(rst_n==1'b0)begin
 - h<=1;
 - end
 - else if(end_cnt_vsy && h<300)begin
 - h<=h+2;
 - end
 - end
 - 
					
 - always @(posedge clk or negedge rst_n)begin
 - if(rst_n==1'b0)begin
 - v<=1;
 - end
 - else if(end_cnt_vsy && v<200)begin
 - v<=v+1;
 - end
 - end
 - 
					
 - 
					
 - always @ (posedge clk or negedge rst_n)begin
 - if(!rst_n)begin
 - lcd_rgb <= 0;
 - end
 - else if(display_area)begin
 - if(blue_area)begin
 - lcd_rgb <= 24'h00_00_ff ;
 - end
 - else begin
 - lcd_rgb <= 24'hff_ff_ff ;
 - end
 - end
 - else begin
 - lcd_rgb <= 0;
 - end
 - end
 - 
					
 - 
					
 - 
					
 - endmodule
 
复制代码
1.2 效果和总结
本案例我们设计了蓝色的矩形,蓝色矩形的场信号是从2行变到400行、行信号是从2个像素变到600个像素;在这个设计案例中,至简设计法和明德扬计数器模板发挥了至关重要的作用,使我能够快速准确完成设计。希望有兴趣的同学可以运用至简设计法和明德扬模板尝试一下拓展设计哦。
设计教学视频和工程源代码,请到明德扬论坛(www.fpgabbs.cn)学习:http://www.fpgabbs.cn/thread-1156-1-1.html
      














