VGA/TFT显示图像学习笔记

VGA显示图像学习笔记

一、VGA显示原理

首先,我们需要先了解一下屏幕图像显示中的分辨率/像素,先了解有关像素的知识,日常生活中所描述的分辨率,比如640×480,1920×1080等等,这指的都是屏幕显示区域的像素值,即,宽有640个像素,长有480个像素,而每一个像素都是由R、G、B三种原色组成的,这三种颜色,按照亮度,每一种颜色都可以分为0~255共256个等级,0表示亮度为0%,255表示亮度为100%,数值代表的是颜色的亮度,三种颜色的不同亮度相互组合成立了大千世界的各种颜色而在数字电路中,每一种颜色我们都可以定义为位宽为8比特的数据。所以每一个像素的数据位宽即为3×8,即位宽为24

其次,需要了解一下VGA显示的扫描方式,如图所示。常见的彩色显示器一般由CRT(阴极射线管)构成,色彩是由RGB三基色组成,显示是用逐行扫描的方式解决,阴极射线枪发出的电子束打在涂有荧光粉的的荧光屏上,产生RGB三基色,合成一个彩色像素,扫描从屏幕左上方开始,从左到右,从上到下进行扫描,每扫描完一行,电子束都回到屏幕的下一行左边的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行行同步,扫描完所有行,用场同步信号进行场同步,并使扫描回到屏幕的左上方,同时进行场消隐,预备下一场的扫描。随着显示技术的,出现了液晶显示器,液晶显示器的成像原理与CRT 不同,液晶显示器是通过对液晶像素点单元施加电压与否,来实现液晶单元的透明程度,并添加三色滤光片、分别使R、G、B 这三种光线透过滤光片,最后通过3 个像素点合成一个彩色像素点,从而实现彩色显示。由于液晶技术晚于CRT 显示技术诞生,为了能够兼容传统的显示接口,液晶显示器通过内部电路实现了对VGA 接口的完全兼容。因此,在使用显示器时,只要该显示器带有标准的VGA 接口,就不用去关注其成像原理,直接使用标准的VGA 时序即可驱动。RGB 接口的TFT 屏,扫描方式与VGA 完全一致。不同之处只是在于,VGA 显示器是接收模拟信号,而TFT 屏则省略了这一过程,直接接受数字信号。例如,在驱动VGA 时首先产生对应像素的颜色数字信号编码,再使用数模转换电路(例如ADV7123)将数字转换为模拟信号,然后通过VGA 线缆将模拟信号传输到VGA 显示器上进行显示。而TFT 屏则直接省略了数模转换这一过程,直接将接收到的数字信号进行显示。因此在控制器设计端,并没有任何区别,
只是需要适当的根据不同的分辨率修改相对应的一些参数即可。

VGA显示图像模块划分

根据VGA的显示原理,结合待显示的内容,我们对VGA显示进行模块划分,需要根据任务要求(譬如我这次是做一个200×200的图片显示)划分模块,如图所示,VGA_control即为VGA控制器,这个模块是输出VGA的行场控制信号,数据使能信号,显示数据,VGA/TFT工作时钟以及扫描位置信号,image_extract是桥接VGA_control和ROM IP,VGA_control输出扫描位置信号至image_extract,其产生数据读取的地址,从ROM IP中读取数据,并传输至VGA_控制器中,由其转化为待显示的RGB数据。pll是时钟分频IP,用来生成不同的时钟频率,由于我此次使用显示屏分辨率是800×480,开发板的时钟频率为50M,而以每秒60帧显示的话,VGA/TFT的工作时钟则为33M,VGA_top是用来协调各个模块。
在这里插入图片描述

VGA控制器模块

完整源码及注释如图所示

module VGA_control(
input               rst_n    ,
input               clk      ,
input        [23:0] data     ,//输入的图像数据
output   reg [23:0] VGA_RGB  ,//输出的图像数据
output   reg        VGA_BLK  ,//数据有效信号
output   reg        data_req ,
output   reg        VGA_HS   ,//行同步信号
output   reg        VGA_VS   ,//场同步信号
output   reg [11:0] h_count  , //当前行扫描位置坐标
output   reg [11:0] v_count    //当前场扫描位置坐标
);

`include "vga_parameter.v"
localparam hsync_end = `H_Total_Time;
localparam hs_end = `H_Sync_Time;
localparam hdata_begin = `H_Sync_Time + `H_Back_Porch + `H_Left_Border;
localparam hdata_end = `H_Sync_Time + `H_Left_Border + `H_Back_Porch + `H_Data_Time;
localparam vsync_end = `V_Total_Time;
localparam vs_end = `V_Sync_Time;
localparam vdata_begin =  `V_Sync_Time + `V_Back_Porch + `V_Top_Border;
localparam vdata_end = `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time;

reg [11:0]   HS_cnt; //行扫描计数器
reg [11:0]   VS_cnt; //场扫描计数器
//行扫描计数器
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        HS_cnt <= 0;
    end
    else if(HS_cnt >= hsync_end - 1) begin
        HS_cnt <= 0;
    end
    else begin
        HS_cnt <= HS_cnt + 1'b1;
    end
end
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        VGA_HS <= 0 ;
    end
    else if (HS_cnt >= hs_end) begin
        VGA_HS <= 1'b1;
    end
    else begin
        VGA_HS <= 0;
    end
end
//场扫描计数器
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        VS_cnt <= 0;
    end
    else if(HS_cnt == hsync_end - 1 ) begin
        if(VS_cnt >= vsync_end - 1)
            VS_cnt <= 0;
        else
            VS_cnt <= VS_cnt + 1'd1;
    end
    else begin
        VS_cnt <= VS_cnt;
    end
end
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        VGA_VS <= 0 ;
    end
    else if (VS_cnt >= vs_end) begin
        VGA_VS <= 1'b1;
    end
    else begin
        VGA_VS <= 0;
    end
end


//如果不加这个data_req,那么VGA_RGB输出得数据总是会比data慢一拍,加了data_req,并且在tb中让data_req低电平得时候,就把数据给进来
//这样子就能消除VGA_BLK慢了一拍得影响
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) 
        data_req <= 0 ;
    else if (HS_cnt >= hdata_begin - 1) 
        if (HS_cnt < hdata_end - 1)
            if(VS_cnt >= vdata_begin)
                if(VS_cnt < vdata_end)
                    data_req <= 1'b1;
                else 
                    data_req <= 0;               
            else 
                data_req <= 0;
        else
            data_req <= 0;        
    else 
        data_req <= 0;
end

always@(posedge clk or negedge rst_n) begin
     if (!rst_n) 
        VGA_BLK <= 0 ;
    else
        VGA_BLK <= data_req;
end
always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        VGA_RGB <= 0;
    else if(data_req <= 1'b1)
        VGA_RGB <= data;
    else
        VGA_RGB <= 0;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        h_count <= 0;
    else if (data_req == 1'b1)
        h_count <= HS_cnt - hdata_begin;
    else 
        h_count <= 0;
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        v_count <= 0;
    else if (data_req == 1'b1)
        v_count <= VS_cnt - vdata_begin;
    else 
        v_count <= 0;
end

endmodule

image_extract模块

完整源码及其注释如图所示

module image_extract(

input     clk_ctrl,
input     reset_n,

input    disp_data_req,
input   [11:0]  visible_hcount ,
input   [11:0]  visible_vcount ,
input       Frame_Begin,

input    [15:0]  rom_data,

input    [15:0]  disp_back_color,
output   [15:0]  disp_data,
output reg [15:0] rom_addra

);

parameter H_Visible_area = 800;
parameter V_Visible_area = 480;
parameter IMG_WIDTH = 200;
parameter IMG_HEIGHT = 200;
parameter img_disp_hbegin = (H_Visible_area - IMG_WIDTH)/2;
parameter img_disp_vbegin = (V_Visible_area - IMG_HEIGHT)/2;


  wire       img_h_disp;
  wire       img_v_disp;
  wire       img_disp;
  wire [15:0]hcount_max;

  //判断设置的显示的起始位置是否会导致显示超出范围
 //assign h_exceed = img_disp_hbegin + IMG_WIDTH  > H_Visible_area - 1'b1;
  //assign v_exceed = img_disp_vbegin + IMG_HEIGHT > V_Visible_area - 1'b1;
  //不同的设置情况,显示区域做不同的处理
  assign img_h_disp = (visible_hcount >= img_disp_hbegin && visible_hcount < img_disp_hbegin + IMG_WIDTH);  
  
  assign img_v_disp = (visible_vcount >= img_disp_vbegin && visible_vcount < img_disp_vbegin + IMG_HEIGHT);
     
  assign img_disp = disp_data_req && img_h_disp && img_v_disp;
  
     
  always@(posedge clk_ctrl or negedge reset_n)
  begin
    if(!reset_n)
      rom_addra <= 16'd0;
    else if(Frame_Begin)
      rom_addra <= 16'd0; 
    else if(img_disp)begin
        rom_addra <= rom_addra + 1'b1;
    end    
    else
      rom_addra <= rom_addra;
  end

  assign disp_data = img_disp ? rom_data : disp_back_color;

 endmodule

VGA_top模块

module TFT_top(

input   clk50M,
input   reset_n,

output [15:0]  tft_rgb,
output tft_hs,
output tft_vs,
output tft_blk,//数据使能
output tft_bl,//背光控制
output tft_clk
);



  wire                      pll_locked;
  wire                      clk_ctrl;
  wire                      tft_reset_n;
  wire [15:0]             rom_addra;
	wire [15:0]               disp_data;
	wire [15:0]               rom_data;
    wire                      disp_data_req;
	wire [11:0]               visible_hcount;
	wire [11:0]               visible_vcount;
    wire [15:0]tft_rgb;
    wire Frame_Begin;
    assign tft_reset_n = pll_locked;
    assign tft_bl=1'b1; 
parameter DISP_BACK_COLOR = 116'hFFFF;
  pll pll
  (
    // Clock out ports
    .clk_out1(clk_ctrl    ), // output clk_out1
    // Status and control signals
    .resetn  (reset_n     ), // input reset,active low
    .locked  (pll_locked  ), // output locked
    // Clock in ports
    .clk_in1 (clk50M      )  // input clk_in1
  ); 

  rom_image rom_image (
    .clka  (clk_ctrl  ),   // input wire clka
    .addra (rom_addra ),   // input wire [16 : 0] addra
    .douta (rom_data  )    // output wire [15 : 0] douta
  );  
  

  image_extract image_extract(
    .clk_ctrl       (clk_ctrl       ),
    .reset_n        (tft_reset_n    ),
    .disp_back_color(DISP_BACK_COLOR),
    .rom_addra      (rom_addra      ),
    .rom_data       (rom_data       ),
    .Frame_Begin    (Frame_Begin    ),
    .disp_data_req  (disp_data_req  ),
    .visible_hcount (visible_hcount ),
    .visible_vcount (visible_vcount ),
    .disp_data      (disp_data      )
  );
  
  	TFT_driver TFT_driver(
		.ClkDisp(clk_ctrl),
		.rst_n(tft_reset_n),

		.data(disp_data),
		.data_req(disp_data_req),

		.h_count(visible_hcount),
		.v_count(visible_vcount),
                            
		.TFT_HS(tft_hs),
		.TFT_VS(tft_vs),
        .TFT_RGB(tft_rgb),
		.Frame_Begin(Frame_Begin),             
		.TFT_BLK(tft_blk),
		.TFT_PCLK(tft_clk)
	);
    
    endmodule

板级测试效果

VGA/TFT显示图像

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新芯设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值