首页 > 学院 > 开发设计 > 正文

FPGA 学习笔记(十一) VGA驱动的实现

2019-11-08 20:02:01
字体:
来源:转载
供稿:网友

VGA时序图

1)行扫描时序图

a:行同步时期,扫描地址的复位 b:行消隐后肩,扫描地址转移后的稳定等待准备期 c:行显示时期,数据有效区域 d:行消隐前肩,扫描地址转移的准备 e:行扫描总时间,一行扫描的总时间

2)场扫描时序图

o:场同步时期,扫描地址的复位 p:场消隐后肩,扫描地址转移后的稳定等待准备期 q:场显示时期,数据有效区域 r:场消隐前肩,扫描地址转移的准备 s:场扫描总时间,一场扫描的总时间

3)VGA显示器扫描轨迹

常见的刷新率时序表

由于FPGA擅长计数电路这里采用像素表示法来设计驱动

FPGA硬件 测试时要将sys_pll中的输出频率改为25MHZ。

驱动电路的verilog设计(lcd_driver)

由亍目前液晶显示器的普及,而高于 60Hz 的刷新率对于液晶来说,没有任何意义,所以我们以 640*480 在 60Hz 的刷新率下为例。

本次我们采用的是ADV7123视频转换芯片来实现。

1)为便于移植,根据640*480 60hz分辨率下的参数,宏定义相关数据

//---------------------------------// 640 * 480`define H_FRONT 11'd16`define H_SYNC 11'd96 `define H_BACK 11'd48 `define H_DISP 11'd640 `define H_TOTAL 11'd800 `define V_FRONT 11'd10 `define V_SYNC 11'd2 `define V_BACK 11'd33 `define V_DISP 11'd480 `define V_TOTAL 11'd525

2)行扫描单位hcnt计数

/******************************************* SYNC--BACK--DISP--FRONT*******************************************///------------------------------------------//h_sync counter & generatorreg [10:0] hcnt; always @ (posedge clk or negedge rst_n)begin if (!rst_n) hcnt <= 11'd0; else begin if(hcnt < `H_TOTAL - 1'b1) //line over hcnt <= hcnt + 1'b1; else hcnt <= 11'd0; endend assign lcd_hs = (hcnt <= `H_SYNC - 1'b1) ? 1'b0 : 1'b1;//VGA行同步信号

3)列扫描单位vcnt计数 每扫描完一行,即hcnt完成H_TOTAL次计数后,vcnt进行自加。

//------------------------------------------//v_sync counter & generatorreg [10:0] vcnt;always@(posedge clk or negedge rst_n)begin if (!rst_n) vcnt <= 11'b0; else if(hcnt == `H_TOTAL - 1'b1) //line over begin if(vcnt < `V_TOTAL - 1'b1) //frame over vcnt <= vcnt + 1'b1; else vcnt <= 11'd0; endendassign lcd_vs = (vcnt <= `V_SYNC - 1'b1) ? 1'b0 : 1'b1;//VGA场同步信号

4)ADV7123控制信号输出 为了实现数据在lcd_dclk上升沿有效,我们将clk翻转输出,已实现上升沿采样 lcd_blank作为显示空白信号,低电平有效。 设计中不需要lcd_sync信息,可以直接接地。

//------------------------------------------//LCELL LCELL(.in(clk),.out(lcd_dclk));assign lcd_dclk = ~clk;assign lcd_blank = lcd_hs & lcd_vs; assign lcd_sync = 1'b0;

5)有效显示使能信号输出 当使能信号有效时,接收外部输入的RGB数据lcd_data.

//-----------------------------------------assign lcd_en = (hcnt >= `H_SYNC + `H_BACK && hcnt < `H_SYNC + `H_BACK + `H_DISP) && (vcnt >= `V_SYNC + `V_BACK && vcnt < `V_SYNC + `V_BACK + `V_DISP) ? 1'b1 : 1'b0;assign lcd_rgb = lcd_en ? lcd_data : 24'h000000; //ffffff;

6)外部数据请求控制信号。 为了实现数据的稳定,lcd_request要提前一个时钟请求外部输入数据 同时,设计中实时显示下一时刻的扫描地址lcd_xpos、lcd_ypos,也要提前一个时钟输出,以保证外部数据输入的同步化。 lcd_xpos、lcd_ypos作为显示器有效显示区域的行列坐标计数值。

//------------------------------------------//ahead x clocklocalparam H_AHEAD = 11'd1;assign lcd_request = (hcnt >= `H_SYNC + `H_BACK - H_AHEAD && hcnt < `H_SYNC + `H_BACK + `H_DISP - H_AHEAD) && (vcnt >= `V_SYNC + `V_BACK && vcnt < `V_SYNC + `V_BACK + `V_DISP) ? 1'b1 : 1'b0;//lcd xpos & yposassign lcd_xpos = lcd_request ? (hcnt - (`H_SYNC + `H_BACK - H_AHEAD)) : 11'd0;assign lcd_ypos = lcd_request ? (vcnt - (`V_SYNC + `V_BACK)) : 11'd0;

模拟VGA图像数据的输入

1)宏定义三原色组合的颜色如下

//define colors RGB--8|8|8`define RED 24'hFF0000 /*11111111,00000000,00000000 */`define GREEN 24'h00FF00 /*00000000,11111111,00000000 */`define BLUE 24'h0000FF /*00000000,00000000,11111111 */`define WHITE 24'hFFFFFF /*11111111,11111111,11111111 */`define BLACK 24'h000000 /*00000000,00000000,00000000 */`define YELLOW 24'hFFFF00 /*11111111,11111111,00000000 */`define CYAN 24'hFF00FF /*11111111,00000000,11111111 */`define ROYAL 24'h00FFFF /*00000000,11111111,11111111 */

2)根据输入的行、列地址信号,输出三原色组合后得到的8条彩色。

//-------------------------------------------`ifdef VGA_HORIZONTAL_COLORalways@(posedge clk or negedge rst_n)begin if(!rst_n) lcd_data <= 24'h0; else begin if (lcd_ypos >= 0 && lcd_ypos < (`V_DISP/8)*1) lcd_data <= `RED; else if(lcd_ypos >= (`V_DISP/8)*1 && lcd_ypos < (`V_DISP/8)*2) lcd_data <= `GREEN; else if(lcd_ypos >= (`V_DISP/8)*2 && lcd_ypos < (`V_DISP/8)*3) lcd_data <= `BLUE; else if(lcd_ypos >= (`V_DISP/8)*3 && lcd_ypos < (`V_DISP/8)*4) lcd_data <= `WHITE; else if(lcd_ypos >= (`V_DISP/8)*4 && lcd_ypos < (`V_DISP/8)*5) lcd_data <= `BLACK; else if(lcd_ypos >= (`V_DISP/8)*5 && lcd_ypos < (`V_DISP/8)*6) lcd_data <= `YELLOW; else if(lcd_ypos >= (`V_DISP/8)*6 && lcd_ypos < (`V_DISP/8)*7) lcd_data <= `CYAN; else// if(lcd_ypos >= (`V_DISP/8)*7 && lcd_ypos < (`V_DISP/8)*8) lcd_data <= `ROYAL; endend`endif
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表