002---基于Verilog HDL的VGA显示器驱动设计(二)


摘要

文章为学习记录。选用 VGA 显示模式 640x480@60,结合002–基于Verilog HDL的VGA显示器驱动设计(一)的VGA行同步时序、VGA场同步时序和VGA时序图给出驱动程序设计并输出像素点坐标、生成像素数据信息,并进行仿真。


一、简要说明

VGA 使用RGB565 图像显示模式,一个像素点位宽为 16bit,高 5 位表示红色,低 5位表示蓝色,中间 6 位表示绿色。另外,还有RGB232、RGB888 等,数据位宽越大,表示颜色种类越多,显示图像越细腻。

如下图,FPGA 输出的图像信息为数字信号,VGA 接口只能识别模拟信号,可以使用权电阻网络实现数模转换。三路模拟信号的电压高低由输入的数字信号决定。输入的 R、G、B 数字信号不同,输出的三原色红、绿、蓝模拟电压不同,颜色深浅不同,三原色相结合可以产生多种颜色。
在这里插入图片描述

二、整体框图

在这里插入图片描述

整个框图包含四个模块:

在这里插入图片描述

三、RTL

1.clk_gen

模块用于生成分频时钟。VGA 显示模式 640x480@60,理论时钟频率应为 25.175MHz,为了便于时钟生成,使用 25MHz 的时钟代替 25.175MHz 的时钟。
PLL配置:(1)和(2)
(1)
在这里插入图片描述
(2)
在这里插入图片描述

2.vga_ctrl

模块用于驱动 VGA 显示器,将输入像素点信息,按照 VGA 时序扫描显示到 VGA 显示器。并输出信号(pix_x,pix_y)作为 VGA 有效显示区域像素点坐标。

module vga_ctrl(
    input   wire            vga_clk     ,   
    input   wire            sys_rst_n   ,   
    input   wire    [15:0]  pix_data    ,   

    output  wire    [9:0]   pix_x       ,   
    output  wire    [9:0]   pix_y       ,   
    output  wire            hsync       ,   
    output  wire            vsync       ,   
    output  wire    [15:0]  rgb             
);

//parameter define
parameter H_SYNC    =   10'd96  ,   
          H_BACK    =   10'd40  ,   
          H_LEFT    =   10'd8   ,   
          H_VALID   =   10'd640 ,   
          H_RIGHT   =   10'd8   ,   
          H_FRONT   =   10'd8   ,   
          H_TOTAL   =   10'd800 ;   
parameter V_SYNC    =   10'd2   ,   
          V_BACK    =   10'd25  ,   
          V_TOP     =   10'd8   ,   
          V_VALID   =   10'd480 ,   
          V_BOTTOM  =   10'd8   ,   
          V_FRONT   =   10'd2   ,   
          V_TOTAL   =   10'd525 ;   

//wire  define
wire            rgb_valid       ;   
wire            pix_data_req    ;   

//reg   define
reg     [9:0]   cnt_h           ;   
reg     [9:0]   cnt_v           ;   


//cnt_h:
always@(posedge vga_clk or  negedge sys_rst_n)
begin
    if(sys_rst_n == 1'b0)
        cnt_h   <=  10'd0   ;
    else    if(cnt_h == H_TOTAL - 1'd1)
        cnt_h   <=  10'd0   ;
    else
        cnt_h   <=  cnt_h + 1'd1   ;
end

//hsync:
assign  hsync = (cnt_h  <=  H_SYNC - 1'd1) ? 1'b1 : 1'b0  ;

//cnt_v:
always@(posedge vga_clk or  negedge sys_rst_n)
begin
    if(sys_rst_n == 1'b0)
        cnt_v   <=  10'd0 ;
    else    if(cnt_h == H_TOTAL - 1'd1)
	    begin
		    if(cnt_v == V_TOTAL - 1'd1)
			    cnt_v   <=  10'd0 ;
			else
			    cnt_v   <=  cnt_v + 1'd1 ;
		end    
    else
        cnt_v   <=  cnt_v ;
end

//vsync:
assign  vsync = (cnt_v  <=  V_SYNC - 1'd1) ? 1'b1 : 1'b0  ;

//rgb_valid:
assign  rgb_valid = (((cnt_h >= H_SYNC + H_BACK + H_LEFT)
                    && (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID))
                    &&((cnt_v >= V_SYNC + V_BACK + V_TOP)
                    && (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
                    ? 1'b1 : 1'b0;

//pix_data_req:
assign  pix_data_req = (((cnt_h >= H_SYNC + H_BACK + H_LEFT - 1'b1)
                    && (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1))
                    &&((cnt_v >= V_SYNC + V_BACK + V_TOP)
                    && (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
                    ? 1'b1 : 1'b0;

//pix_x,pix_y:
assign  pix_x = (pix_data_req == 1'b1)
                ? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 10'h3ff;
assign  pix_y = (pix_data_req == 1'b1)
                ? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 10'h3ff;

//rgb:
assign  rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;

endmodule

3.vga_pic

vga_pic模块接收 模块 vga_ctrl 传入的像素点坐标(pix_x,pix_y)信号,并以此为约束条件产生并回传像素点色彩信息。该模块可产生想要生成的图像像素点信息。

module  vga_pic
(
    input   wire            vga_clk     ,   //输入工作时钟,频率25MHz
    input   wire            sys_rst_n   ,   //输入复位信号,低电平有效
    input   wire    [9:0]   pix_x       ,   //输入VGA有效显示区域像素点X轴坐标
    input   wire    [9:0]   pix_y       ,   //输入VGA有效显示区域像素点Y轴坐标

    output  reg     [15:0]  pix_data        //输出像素点色彩信息
);


//parameter define
parameter   H_VALID =   10'd640 ,   //行有效数据
            V_VALID =   10'd480 ;   //场有效数据

parameter   RED     =   16'hF800,   //红色
            ORANGE  =   16'hFC00,   //橙色
            YELLOW  =   16'hFFE0,   //黄色
            GREEN   =   16'h07E0,   //绿色
            CYAN    =   16'h07FF,   //青色
            BLUE    =   16'h001F,   //蓝色
            PURPPLE =   16'hF81F,   //紫色
            BLACK   =   16'h0000,   //黑色
            WHITE   =   16'hFFFF,   //白色
            GRAY    =   16'hD69A;   //灰色



//pix_data:
always@(posedge vga_clk or negedge sys_rst_n)
begin
    if(sys_rst_n == 1'b0)
        pix_data    <= 16'd0;
    else    if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
        pix_data    <=  RED;
    else    if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
        pix_data    <=  ORANGE;
    else    if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
        pix_data    <=  YELLOW;
    else    if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
        pix_data    <=  GREEN;
    else    if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
        pix_data    <=  CYAN;
    else    if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
        pix_data    <=  BLUE;
    else    if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
        pix_data    <=  PURPPLE;
    else    if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
        pix_data    <=  BLACK;
    else    if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
        pix_data    <=  WHITE;
    else    if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
        pix_data    <=  GRAY;
    else
        pix_data    <=  BLACK;
end

endmodule

4.vga_colorbar

module vga_colorbar(
input    wire          sys_clk,
input    wire          sys_rst_n,
                       
output   wire           hsync,
output   wire           vsync,
output   wire   [15:0]  rgb
    );
    
//wire define
wire            clk_25m ;   
wire            locked  ;   
wire            rst_n   ;   
wire    [9:0]   pix_x   ;   
wire    [9:0]   pix_y   ;   
wire    [15:0]  pix_data;   

//rst_n:
assign  rst_n = (sys_rst_n & locked);

//------------- clk_gen_inst -------------
  clk_gen clk_gen_inst
   (
    // Clock out ports
    .clk_out1(clk_25m),     // output clk_out1
    // Status and control signals
    .reset(~sys_rst_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(sys_clk)      // input clk_in1
	);
    

//------------- vga_ctrl_inst --
vga_ctrl  vga_ctrl_inst
(
    .vga_clk    (clk_25m    ),  
    .sys_rst_n  (rst_n      ),  
    .pix_data   (pix_data   ),  

    .pix_x      (pix_x      ),  
    .pix_y      (pix_y      ),  
    .hsync      (hsync      ),  
    .vsync      (vsync      ),  
    .rgb        (rgb        )   
);

//------------- vga_pic_inst ---
vga_pic vga_pic_inst
(
    .vga_clk    (clk_25m    ),  
    .sys_rst_n  (rst_n      ),  
    .pix_x      (pix_x      ),  
    .pix_y      (pix_y      ),  

    .pix_data   (pix_data   )   

);   
    
endmodule

四、Testbench

1.仿真代码

module tb_vga_colorbar();

//reg   define
reg             sys_clk     ;
reg             sys_rst_n   ;

//wire  define
wire            hsync       ;
wire    [15:0]  rgb         ;
wire            vsync       ;

//sys_rst_n:
initial
begin
    sys_rst_n  =  1'b0;
    #201
    sys_rst_n  =  1'b1;
    #1_300_000
    $stop;
end

//sys_clk:
initial
begin
    sys_clk    =   1'b1;
end
always  #5 sys_clk = ~sys_clk  ;

//------------- vga_colorbar_inst -------------
vga_colorbar    vga_colorbar_inst
(
    .sys_clk    (sys_clk    ),  
    .sys_rst_n  (sys_rst_n  ),  

    .hsync      (hsync      ),  
    .vsync      (vsync      ),  
    .rgb        (rgb        )   
);

endmodule

2. 仿真分析

rgb_valid 信号只有在图像显示有效区域保持高电平,其他区域为低电平;pix_data_req 信号超前 rgb_valid 信号一个时钟周期;
pix_x 信号在图像显示有效区域循环计数,计数范围 0-639,计数 640 次;
pix_y 信号在图像显示有效区域循环计数,计数范围 0-479,计数 480 次;
rgb 在 rgb_valid 信号有效时,被赋值为 pix_data,rgb_valid 信号无效时,赋值为 0。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值