admin 发表于 2019-4-10 20:57:15

【设计实例】可配置的VGA通用驱动控制器,适配多种分辨率


如果您还没有注册本论坛,将无法下载论坛中附件,但是注册论坛非常简单,使用微   信 扫码即可注册。
也可以在小梅哥任意一个Q群内直接索取邀请码使用邀请码注册,小梅哥创建的任意一个群都可以。


以前自己写过单独的VGA控制器和TFT屏控制器,那些都是分开写的,每个设备(4.3寸显示屏、5寸显示屏、VGA输出等),甚至每个分辨率都要单独写一个驱动模块,那样实用不方便,也不利于工程版本的管理,给自己的例程发布和更新带来了非常大的麻烦,因此小梅哥今天痛定思痛,采用条件编译的方式,设计了一个通用的驱动模块,该模块只需要在代码中选择不同的编译参数,就能够实现不同分辨率的时序输出。用起来非常方便。

注意,每个分辨率对应的像素时钟频率是不一样的,因此需要针对不同的分辨率,给ClkDisp提供不同频率的时钟。每个分辨率对应的参数已经在条件编译的代码部分通过注释的方式提示了。



module VGA_CTRL_test(
      Clk,         //50MHZ时钟
      Rst_n,
      VGA_RGB,//TFT数据输出
      VGA_HS,      //TFT行同步信号
      VGA_VS,      //TFT场同步信号
      VGA_BLK,                //VGA 场消隐信号
      VGA_CLK                //VGA DAC输出时钟
);

      input Clk;
      input Rst_n;
      output VGA_RGB;
      output VGA_HS;
      output VGA_VS;
      output VGA_BLK;                //VGA 场消隐信号
      output VGA_CLK;                //VGA DAC输出时钟
      
      reg disp_data;
      wire hcount;
      wire vcount;
      wire ClkDisp;
      
      vga_test_pll vga_test_pll(
                .inclk0(Clk),
                .c0(ClkDisp)
      );
      
      disp_driver disp_driver(
                .ClkDisp(ClkDisp),
                .Rst_n(Rst_n),
                .Data(disp_data),
                .DataReq(),
                .H_Addr(hcount),
                .V_Addr(vcount),
                .Disp_HS(VGA_HS),
                .Disp_VS(VGA_VS),
                .Disp_Red(VGA_RGB),
                .Disp_Green(VGA_RGB),
                .Disp_Blue(VGA_RGB),
                .Disp_DE(VGA_BLK),
                .Disp_PCLK(VGA_CLK)
      );

/*      
      VGA_CTRL VGA_CTRL(
                .Clk25M(ClkDisp),      //系统输入时钟25MHZ
                .Rst_n(Rst_n),
                .data_in(disp_data),      //待显示数据
                .hcount(hcount),                //VGA行扫描计数器
                .vcount(vcount),                //VGA场扫描计数器
                .VGA_RGB(VGA_RGB),      //VGA数据输出
                .VGA_HS(VGA_HS),                //VGA行同步信号
                .VGA_VS(VGA_VS),                //VGA场同步信号
                .VGA_BLK(VGA_BLK),                //VGA 场消隐信号
                .VGA_CLK(VGA_CLK)      //VGA DAC输出时钟
      );
*/
      
//定义颜色编码
localparam
      BLACK                = 24'h000000, //黑色
      BLUE                = 24'h0000FF, //蓝色
      RED                = 24'hFF0000, //红色
      PURPPLE      = 24'hFF00FF, //紫色
      GREEN                = 24'h00FF00, //绿色
      CYAN                = 24'h00FFFF, //青色
      YELLOW      = 24'hFFFF00, //黄色
      WHITE                = 24'hFFFFFF; //白色
      
//定义每个像素块的默认显示颜色值
localparam
      R0_C0 = BLACK,      //第0行0列像素块
      R0_C1 = BLUE,      //第0行1列像素块
      R1_C0 = RED,      //第1行0列像素块
      R1_C1 = PURPPLE,//第1行1列像素块
      R2_C0 = GREEN,      //第2行0列像素块
      R2_C1 = CYAN,      //第2行1列像素块
      R3_C0 = YELLOW,      //第3行0列像素块
      R3_C1 = WHITE;      //第3行1列像素块

      wire R0_act = vcount >= 0 && vcount < 120;      //正在扫描第0行
      wire R1_act = vcount >= 120 && vcount < 240;//正在扫描第1行
      wire R2_act = vcount >= 240 && vcount < 360;//正在扫描第2行
      wire R3_act = vcount >= 360 && vcount < 480;//正在扫描第3行
      
      wire C0_act = hcount >= 0 && hcount < 320; //正在扫描第0列
      wire C1_act = hcount >= 320 && hcount < 640;//正在扫描第1列
      
      wire R0_C0_act = R0_act & C0_act;      //第0行0列像素块处于被扫描中标志信号
      wire R0_C1_act = R0_act & C1_act;      //第0行1列像素块处于被扫描中标志信号
      wire R1_C0_act = R1_act & C0_act;      //第1行0列像素块处于被扫描中标志信号
      wire R1_C1_act = R1_act & C1_act;      //第1行1列像素块处于被扫描中标志信号
      wire R2_C0_act = R2_act & C0_act;      //第2行0列像素块处于被扫描中标志信号
      wire R2_C1_act = R2_act & C1_act;      //第2行1列像素块处于被扫描中标志信号
      wire R3_C0_act = R3_act & C0_act;      //第3行0列像素块处于被扫描中标志信号
      wire R3_C1_act = R3_act & C1_act;      //第3行1列像素块处于被扫描中标志信号
      
      always@(*)
                case({R3_C1_act,R3_C0_act,R2_C1_act,R2_C0_act,
                              R1_C1_act,R1_C0_act,R0_C1_act,R0_C0_act})
                        8'b0000_0001:disp_data = R0_C0;
                        8'b0000_0010:disp_data = R0_C1;
                        8'b0000_0100:disp_data = R1_C0;
                        8'b0000_1000:disp_data = R1_C1;
                        8'b0001_0000:disp_data = R2_C0;
                        8'b0010_0000:disp_data = R2_C1;
                        8'b0100_0000:disp_data = R3_C0;
                        8'b1000_0000:disp_data = R3_C1;
                        default:disp_data = R1_C0;
                endcase
               
endmodule




/*============================================================================
*
*LOGIC CORE:          显示设备驱动模块               
*MODULE NAME:         disp_driver()
*COMPANY:             武汉芯路恒科技有限公司
*                     http://xiaomeige.taobao.com
*      author:                                        小梅哥
*      Website:                                        www.corecourse.cn
*REVISION HISTORY:
*
*    Revision 1.004/10/2019   Description: Initial Release.
*
*FUNCTIONAL DESCRIPTION:
===========================================================================*/
`include "disp_parameter_cfg.v"

module disp_driver(
      ClkDisp,
      Rst_n,
      
      Data,
      DataReq,
      
      H_Addr,
      V_Addr,
      
      Disp_HS,
      Disp_VS,
      Disp_Red,
      Disp_Green,
      Disp_Blue,
      Disp_DE,
      Disp_PCLK
);

      input ClkDisp;
      input Rst_n;
      input [`Red_Bits + `Green_Bits + `Blue_Bits - 1:0] Data;
      output DataReq;
      
      output H_Addr;
      output V_Addr;
      
      output reg Disp_HS;
      output reg Disp_VS;

      output reg [`Red_Bits - 1 :0]Disp_Red;
      output reg [`Green_Bits - 1 :0]Disp_Green;
      output reg [`Blue_Bits - 1 :0]Disp_Blue;
      
      output reg Disp_DE;
      output Disp_PCLK;
      
      wire hcount_ov;
      wire vcount_ov;
               
      //----------------内部寄存器定义----------------
      reg hcount_r;   //行扫描计数器
      reg vcount_r;   //场扫描计数器
      
      assign Disp_PCLK = ~ClkDisp;
      assign DataReq = Disp_DE;
      
      parameter hdat_begin = `H_Sync_Time + `H_Back_Porch + `H_Left_Border - 1'b1;
      parameter hdat_end = `H_Total_Time - `H_Right_Border - `H_Front_Porch - 1'b1;
      
      parameter vdat_begin      = `V_Sync_Time + `V_Back_Porch + `V_Top_Border - 1'b1;
      parameter vdat_end = `V_Total_Time - `V_Bottom_Border - `V_Front_Porch - 1'b1;      
      
      assign H_Addr = Disp_DE?(hcount_r - hdat_begin):12'd0;
      assign V_Addr = Disp_DE?(vcount_r - vdat_begin):12'd0;

      //行扫描
      assign hcount_ov = (hcount_r >= `H_Total_Time - 1);
      
      always@(posedge ClkDisp or negedge Rst_n)
      if(!Rst_n)
                hcount_r <= 0;
      else if(hcount_ov)
                hcount_r <= 0;
      else
                hcount_r <= hcount_r + 1'b1;

      //场扫描
      assign vcount_ov = (vcount_r >= `V_Total_Time - 1);

      always@(posedge ClkDisp or negedge Rst_n)
      if(!Rst_n)
                vcount_r <= 0;
      else if(hcount_ov) begin
                if(vcount_ov)
                        vcount_r <= 0;
                else
                        vcount_r <= vcount_r + 1'd1;
      end
      else
                vcount_r <= vcount_r;
               
      always@(posedge ClkDisp)
                Disp_DE <= ((hcount_r >= hdat_begin)&&(hcount_r < hdat_end))
                                        &&((vcount_r >= vdat_begin)&&(vcount_r < vdat_end));
      
      always@(posedge ClkDisp)      begin                        
                Disp_HS <= (hcount_r > `H_Sync_Time - 1);
                Disp_VS <= (vcount_r > `V_Sync_Time - 1);
                {Disp_Red,Disp_Green,Disp_Blue} <= (Disp_DE)?Data:1'd0;
      end
               
endmodule






/*============================================================================
*
*LOGIC CORE:          显示设备驱动硬件配置头文件      
*MODULE NAME:         disp_parameter_cfg()
*COMPANY:             武汉芯路恒科技有限公司
*                     http://xiaomeige.taobao.com
*      author:                                        小梅哥
*      Website:                                        www.corecourse.cn
*REVISION HISTORY:
*
*    Revision 1.004/10/2019   Description: Initial Release.
*
*FUNCTIONAL DESCRIPTION:
===========================================================================*/

/*
使用时根据实际工作需求选择几个预定义参数就可以

MODE_RGB888和MODE_RGB565两个参数二选一,用来决定驱动工作在16位模式还是24位模式
针对小梅哥提供的一系列显示设备,各个设备参数如下所述
      4.3寸屏:16位色RGB565模式
      5寸屏:16位色RGB565模式
      GM7123模块使用24位色RGB888模式,

Resolution_xxxx预定义用来决定显示设备分辨率,常见设备分辨率如下所述

4.3寸TFT显示屏:Resolution_480x272
5寸TFT显示屏:Resolution_800x480

VGA常见分辨率:
      Resolution_640x480
      Resolution_800x600
      Resolution_1024x768
      Resolution_1280x720
      Resolution_1920x1080
*/

//以下两行预定义根据实际使用的模式,选择一个使能,另外一个使用注释的方式屏蔽

`define MODE_RGB888
//`define MODE_RGB565

//以下7行预定义根据实际使用的分辨率,选择一个使能,另外6个使用注释的方式屏蔽

//`define Resolution_480x272 1      //时钟为9MHz
`define Resolution_640x480 1      //时钟为25.175MHz
//`define Resolution_800x480 1      //时钟为33MHz
//`define Resolution_800x600 1      //时钟为40MHz
//`define Resolution_1024x768 1      //时钟为65MHz
//`define Resolution_1280x720 1      //时钟为74.25MHz
//`define Resolution_1920x1080 1      //时钟为148.5MHz

//定义不同的颜色深度
`ifdef MODE_RGB888
      `define Red_Bits 8
      `define Green_Bits 8
      `define Blue_Bits 8
      
`elsif MODE_RGB565
      `define Red_Bits 5
      `define Green_Bits 6
      `define Blue_Bits 5
`endif

//定义不同分辨率的时序参数
`ifdef Resolution_480x272
      `define H_Total_Time12'd525
      `define H_Right_Border12'd0
      `define H_Front_Porch12'd2
      `define H_Sync_Time12'd41
      `define H_Back_Porch12'd2
      `define H_Left_Border12'd0

      `define V_Total_Time12'd286
      `define V_Bottom_Border12'd0
      `define V_Front_Porch12'd2
      `define V_Sync_Time12'd10
      `define V_Back_Porch12'd2
      `define V_Top_Border12'd0
      
`elsif Resolution_640x480
      `define H_Total_Time12'd800
      `define H_Right_Border12'd8
      `define H_Front_Porch12'd8
      `define H_Sync_Time12'd96
      `define H_Back_Porch12'd40
      `define H_Left_Border12'd8

      `define V_Total_Time12'd525
      `define V_Bottom_Border12'd8
      `define V_Front_Porch12'd2
      `define V_Sync_Time12'd2
      `define V_Back_Porch12'd25
      `define V_Top_Border12'd8

`elsif Resolution_800x480
      `define H_Total_Time 12'd1056
      `define H_Right_Border 12'd0
      `define H_Front_Porch 12'd40
      `define H_Sync_Time 12'd128
      `define H_Back_Porch 12'd88
      `define H_Left_Border 12'd0

      `define V_Total_Time 12'd525
      `define V_Bottom_Border 12'd8
      `define V_Front_Porch 12'd2
      `define V_Sync_Time 12'd2
      `define V_Back_Porch 12'd25
      `define V_Top_Border 12'd8

`elsif Resolution_800x600
      `define H_Total_Time 12'd1056
      `define H_Right_Border 12'd0
      `define H_Front_Porch 12'd40
      `define H_Sync_Time 12'd128
      `define H_Back_Porch 12'd88
      `define H_Left_Border 12'd0

      `define V_Total_Time 12'd628
      `define V_Bottom_Border 12'd0
      `define V_Front_Porch 12'd1
      `define V_Sync_Time 12'd4
      `define V_Back_Porch 12'd23
      `define V_Top_Border 12'd0

`elsif Resolution_1024x768
      `define H_Total_Time 12'd1344
      `define H_Right_Border 12'd0
      `define H_Front_Porch 12'd24
      `define H_Sync_Time 12'd136
      `define H_Back_Porch 12'd160
      `define H_Left_Border 12'd0

      `define V_Total_Time 12'd806
      `define V_Bottom_Border 12'd0
      `define V_Front_Porch 12'd3
      `define V_Sync_Time 12'd6
      `define V_Back_Porch 12'd29
      `define V_Top_Border 12'd0

`elsif Resolution_1280x720
      `define H_Total_Time 12'd1650
      `define H_Right_Border 12'd0
      `define H_Front_Porch 12'd110
      `define H_Sync_Time 12'd40
      `define H_Back_Porch 12'd220
      `define H_Left_Border 12'd0

      `define V_Total_Time 12'd750
      `define V_Bottom_Border 12'd0
      `define V_Front_Porch 12'd5
      `define V_Sync_Time 12'd5
      `define V_Back_Porch 12'd20
      `define V_Top_Border 12'd0
               
`elsif Resolution_1920x1080
      `define H_Total_Time 12'd2200
      `define H_Right_Border 12'd0
      `define H_Front_Porch 12'd88
      `define H_Sync_Time 12'd44
      `define H_Back_Porch 12'd148
      `define H_Left_Border 12'd0

      `define V_Total_Time 12'd1125
      `define V_Bottom_Border 12'd0
      `define V_Front_Porch 12'd4
      `define V_Sync_Time 12'd5
      `define V_Back_Porch 12'd36
      `define V_Top_Border 12'd0      
      
`endif






晴空万_PCfoC 发表于 2019-4-15 10:03:26

很好,最近正在学这个,项目上正要使用

sijin 发表于 2019-10-11 13:45:59

请问安装VGA控制器后,就能跑桌面系统了吗,可以运行QT界面吧,谢谢

liuyun2020 发表于 2020-3-15 13:48:02

给梅哥点赞:loveliness:在做摄像头相关实验
页: [1]
查看完整版本: 【设计实例】可配置的VGA通用驱动控制器,适配多种分辨率