FPGA的VGA显示驱动部分知识点

vga显示这边的的的知识点不难,在我写代码的时候却没能显示成功,现在重新设计一遍设计思路。

根据下面的这个时序图,可以用计数器的方式来设计,在不同时间段选择显示情况。

目前我电脑的副屏是一个1440*900的显示器,在网上找到了他的VGA时序图。

根据这个与时序表对应。完成项目代码,最后顶层文件例化框图如下,显示效果如下


在第一次模仿写代码的时候,一直不显示,没信号,后来发现是时钟IP核的复位是高电平有效,例化的时候需要取反。

vga_ctrl驱动

module  vga_ctrl(
    clk_106m,   //1904*932*60hz = 106,471,680HZ = 106.5Mhz 时钟IP核只能到这个点
    reset_n,
    
    //vga
    vga_data_in,   //想要输入的信号值
    vga_data_out,  //实际输出的信号值
    hs_count,   //行计数
    vs_count,   //列计数
    vga_hs,     //行使能
    vga_vs,     //列使能
    vga_blk,    //实际显示信号使能
    vga_clk
);

    input   clk_106m;
    input   reset_n;
    
    input   [23:0]   vga_data_in;  //8位 R G B
    output [23:0]   vga_data_out;
    output [11:0] hs_count;  //实际图像区域的像素计数
    output [11:0] vs_count;
    output  vga_hs;
    output  vga_vs;
    output  vga_blk;
    output  vga_clk;
//    hs_whole = 1904;    
//    hs_front_porch = 80;
//    hs_sync_pulse = 152;
//    hs_real_data = 1440  
//    hs_back_porch = 232                 
    
    
    parameter  hs_whole = 1904;
    parameter  hs_data_begin = 384;  //hs_sync_porch + hs_back_porch
    parameter  hs_sync_pulse = 152;
    parameter  hs_data_end = 1824; //hs_data_begin + hs_real_data

    parameter  vs_whole = 932;
    parameter  vs_data_begin = 31;  //hs_sync_porch + hs_back_porch
    parameter  vs_sync_pulse = 3;
    parameter  vs_data_end = 931; //hs_data_begin + hs_real_data
    
    reg [11:0]  hs_count_r;  //行列像素计数
    reg [11:0]  vs_count_r;
    
    //行计数到最大值清零
    always @(posedge clk_106m or negedge reset_n)
        if(!reset_n)
            hs_count_r <= 0;
        else if(hs_count_r == hs_whole - 1)
            hs_count_r <= 0;
        else
            hs_count_r <= hs_count_r + 1'd1;
            
        //列计数到行计数一行结束,到最大值清零
    always @(posedge clk_106m or negedge reset_n)
        if(!reset_n)
            vs_count_r <= 0;
        else if(hs_count_r == hs_whole - 1) begin
            if(vs_count_r == vs_whole - 1)
                vs_count_r <= 0;
            else
                vs_count_r <= vs_count_r + 1'd1;
        end
        else
            vs_count_r <= vs_count_r;
       
       //阻塞赋值     
       assign  vga_blk = ((hs_count_r >= hs_data_begin) && (hs_count_r < hs_data_end ) 
                                && (vs_count_r >= vs_data_begin) && (vs_count_r < vs_data_end)) ? 1'b1:1'b0;
                                
       assign   vga_hs = (hs_count_r <= hs_sync_pulse)?1'b0:1'b1;
       assign   vga_vs = (vs_count_r <= vs_sync_pulse)?1'b0:1'b1;
       assign   vga_data_out = (vga_blk)?vga_data_in:24'h000000;
       assign   hs_count = (vga_blk)?(hs_count_r - hs_data_begin):12'd0; //实际的显示图像计数
       assign   vs_count = (vga_blk)?(vs_count_r - vs_data_begin):12'd0;
       assign   vga_clk=clk_106m;
       
  
 endmodule           

顶层文件中时钟例化,生成一个106.5M的时钟。

vga_test顶层文件
 module  vga_test(
    clk,
    reset_n,
    

    vga_data_out,  //实际输出的信号值
    vga_hs,     //行使能
    vga_vs,     //列使能
    vga_blk,    //实际显示信号使能
    vga_clk


);
    input   clk;
    input   reset_n;
    
    output  [23:0] vga_data_out;
    output vga_hs;
    output  vga_vs;
    output  vga_blk;
    output  vga_clk;
    
    reg  [23:0]  vga_data_in;
    wire    [11:0]  hs_count;
    wire    [11:0]  vs_count;
    wire    clk_106m;
    wire locked;
    
   	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;//白色
					 
	  clk_wiz_0 instance_name
   (
    // Clock out ports
    .clk_out1(clk_106m),     // output clk_out1
    // Status and control signals
    .reset(!reset_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(clk)
    );      // input clk_in1				 
					 
	vga_ctrl vga_ctrl_inst(
	
	.clk_106m(clk_106m),   //1904*932*60hz = 106,471,680HZ = 106.5Mhz 时钟IP核只能到这个点
    .reset_n(reset_n),
   
    //vga
    .vga_data_in(vga_data_in),   //想要输入的信号值
    .vga_data_out(vga_data_out),  //实际输出的信号值
    .hs_count(hs_count),   //行计数
    .vs_count(vs_count),   //列计数
    .vga_hs(vga_hs),     //行使能
    .vga_vs(vga_vs),     //列使能
    .vga_clk(vga_clk),
    .vga_blk(vga_blk)    //实际显示信号使能
	
	);	
	
	//4行2列
	wire v0_act = hs_count >= 0 && hs_count < 720;  //第一列
	wire v1_act = hs_count >= 720 && hs_count < 1440; //第二列
	
	wire h0_act = vs_count >= 0 && vs_count < 225;   //第一行
    wire h1_act = vs_count >= 225 && vs_count < 450;
    wire h2_act = vs_count >= 450 && vs_count < 675;
    wire h3_act = vs_count >= 675 && vs_count < 900;  //第四行
    
    wire h0_v0_act = h0_act & v0_act;
    wire h0_v1_act = h0_act & v1_act;
    wire h1_v0_act = h1_act & v0_act;
    wire h1_v1_act = h1_act & v1_act;
    wire h2_v0_act = h2_act & v0_act;
    wire h2_v1_act = h2_act & v1_act;
    wire h3_v0_act = h3_act & v0_act;
    wire h3_v1_act = h3_act & v1_act;
	
	always @(posedge clk)
	   	 begin
	   	 case({h3_v1_act,h3_v0_act,h2_v1_act,h2_v0_act,h1_v1_act,h1_v0_act,h0_v1_act,h0_v0_act})
	   	       8'b0000_0001: vga_data_in <= BLACK;
	   	       8'b0000_0010: vga_data_in <= BLUE;
	   	       8'b0000_0100: vga_data_in <= RED;
	   	       8'b0000_1000: vga_data_in <= PURPPLE;
	   	       8'b0001_0000: vga_data_in <= GREEN;
	   	       8'b0010_0000: vga_data_in <= CYAN;
	   	       8'b0100_0000: vga_data_in <= YELLOW;
	   	       8'b1000_0000: vga_data_in <= WHITE;
		endcase
		end			 
endmodule					 
posted @ 2024-03-16 18:57  祈愿树下  阅读(19)  评论(0编辑  收藏  举报
// 侧边栏目录 // https://blog-static.cnblogs.com/files/douzujun/marvin.nav.my1502.css