VGA (一)原理 时序及verilog 仿真

硬件原理

采用DB15的及接口,主要5根VGA信号线,两根I2C通讯线。5根VGA信号线是V_SYN,H_SYN分别是场同步和行同步走的是3.3V的信号,R,G,B分别是红绿蓝三基色信号。R,G,B三基色信号走的是模拟电平,峰峰值规定在0-0.714V,输入阻抗是75欧。另外两根I2C通讯线就是用来和VGA显示器协调所支持的分辨率。
DA转换用 电阻网络进行分压达到DAC效果。
VGA (一)原理 时序及verilog 仿真_第1张图片
1,R,G,B分别对应4个BIT,总共12位,所以分辨率是12位。
2. 由于R有4个位, 在0-0.714V 之间分成了16个等级。

3,H_SYN和V_SYN分别是标示一行的结束,以及一屏的结束,是数字信号。

VGA时序

VGA (一)原理 时序及verilog 仿真_第2张图片
单独看行时序和场时序:

注意FRONT_PORCH和BACK_PORCH分别是在同步信号的之前和之后。

以上时序可以变换成下面的时序:好处是便于地址从0开始计,编程非常方便。依据是VGA支持即插即用,显示器会自动寻找同步信号。

VGA (一)原理 时序及verilog 仿真_第3张图片

VGA (一)原理 时序及verilog 仿真_第4张图片
两个频率,一个是显示的频率,比方我们这里的1024768像素点,刷新率是60HZ,显示的频率就是 102476860=47.18M . 这个频率表达了对图像数据的进行处理和传输的要求。就是说实际应用这个VGA控制器时候,我们需要保证以47.18M显示位数 的速率给他提供显示数据。如果需要用一个DMA传数的话,这是DMA的最低速率要求。

一个频率是像素频率,我们这个1024768个像素点,扫描屏幕实际用了1344806个像素时钟,因此刷新率为60HZ就要求像素频率是134480660=64.99M。这个频率是我们做VGA控制器时需要设置的像素点频率,即产生vga时序的VGA控制器的输入频率。

通过修改宏定义、改像素频率,实现不同像素尺寸和频率的的显示。





// 1024 X 768 @ 60Hz with a 65.000MHz pixel clock

`define H_ACTIVE		1024
`define H_FRONT_PORCH	24
`define H_SYNCH			136	
`define H_BACK_PORCH	160	
`define H_TOTAL			( `H_SYNCH + `H_BACK_PORCH + `H_ACTIVE + `H_FRONT_PORCH ) 
//1344 // pixels

`define V_ACTIVE		768	
`define V_FRONT_PORCH	3	
`define V_SYNCH			6	 
`define V_BACK_PORCH	29	
`define V_TOTAL			 (`V_SYNCH + `V_BACK_PORCH +  `V_ACTIVE +`V_FRONT_PORCH )	
//806 // lines

module my_vga_syn (
        input pixel_clock,	rst_i,
        output  reg 	h_synch,	v_synch,
        output reg 	dp_en,
        output reg  [10:0]	line_count  ,
        output reg  [10:0]  pixel_count
    );

    /*
      1),做2个计数器,一个用来记录行内的像素点时钟数,
      一个用来记录行数。
      这两个计数器除了复位信号外不受别的因素影响,
      在一直自己循环累加。
    */

    always @(posedge pixel_clock)
        if ( rst_i )pixel_count<=0;
        else if (pixel_count == (`H_TOTAL-1))pixel_count<=0;
        else pixel_count<=pixel_count+1;

    always @(posedge pixel_clock)
        if (rst_i)line_count<=0;
        else if (pixel_count==(`H_TOTAL-1)) begin

            if ( line_count==(`V_TOTAL-1))line_count<=0;
            else line_count<=line_count+1;

        end

    /*
    2),两个计数器的数值就对应上图的所处的位置。
    我们找到实际要显示区域对应的像素计数器和行计数器
    的数值,只要两个计数器满足在这个区域,
    就允许显示,否则进行消音输出(R,G,B都输出为0)。
    */
    reg h_en  ;
    always@(posedge pixel_clock)
        if (pixel_count == (`H_TOTAL-1) )h_en<=1;
        else if (pixel_count==(`H_ACTIVE-1))h_en<=0;

    reg v_en ;
    always@(posedge pixel_clock)
        if (pixel_count == (`H_TOTAL-1) )begin

            if (line_count==(`V_TOTAL-1))v_en<=1;
            else if (line_count==(`V_ACTIVE-1))v_en<=0;

        end

    always@(posedge pixel_clock)
        dp_en <= v_en & h_en ;

    /*
    if (    
          (pixel_count <= (`H_ACTIVE-1))  
            && 
    	   (line_count<=(`V_ACTIVE-1))
    	   )
    	   dp_en <= 1 ;
    	   else 
    	   dp_en <= 0 ;
    */



    //3),从图中找到H_SYN的时间段和V_SYN的时间段,
    //将这个时间段同步信号对应设置为低电平。

    always@(posedge pixel_clock)
        if ( pixel_count ==(`H_ACTIVE+`H_FRONT_PORCH-1))
            h_synch<=0;
        else if ( pixel_count ==(`H_ACTIVE+`H_FRONT_PORCH+`H_SYNCH-1))
            h_synch<=1;

    always@(posedge pixel_clock)
        if ( pixel_count ==(`H_TOTAL-1))

        begin
            if (line_count==(`V_ACTIVE+`V_FRONT_PORCH-1))
                v_synch<=0;
            else if ( line_count ==(`V_ACTIVE+`V_FRONT_PORCH + `V_SYNCH-1))
                v_synch<=1;

        end
endmodule

line_count ,pixel_count可以看做二维数组的行列序号下标,输出行列的对应位置,根据位置进行赋值(0~1023, 0 ~757),即可显示图像。

RTL schematic
VGA (一)原理 时序及verilog 仿真_第5张图片
tb

`timescale 1ns/1ns 
module vga_sim_top;

    reg pixel_clock ,rst_i;
    wire dp_en ;
    wire h_synch,v_synch;

    wire   [9:0]	line_count;
    wire   [10:0]	pixel_count	  ;

    reg  [9:0]	line_countr ;
    reg [10:0]	pixel_countr ;

    wire   [9:0]	line_countro ;
    wire   [10:0]   pixel_countro ;

    assign pixel_countro = (dp_en==0)?  0 : pixel_countr ;
    assign line_countro = (dp_en==0)?  0 : line_countr ;

    always@(posedge pixel_clock)
    begin
        line_countr <= line_count ;
        pixel_countr <= pixel_count ;
    end

    always #30 pixel_clock = ~pixel_clock ;

    initial begin

        pixel_clock=0;rst_i=1;
        #100   rst_i=0 ;

    end

    my_vga_syn my_vga_syn(
                   .pixel_clock(pixel_clock  ),
                   .rst_i( rst_i ),
                   .h_synch( h_synch ),
                   .v_synch( v_synch ),
                   .dp_en( dp_en),
                   .line_count(line_count  ),
                   .pixel_count ( pixel_count )
               );

endmodule



一帧

VGA (一)原理 时序及verilog 仿真_第6张图片
一行数据选通
0-1023

VGA (一)原理 时序及verilog 仿真_第7张图片
VGA (一)原理 时序及verilog 仿真_第8张图片
正确

前后沿
VGA (一)原理 时序及verilog 仿真_第9张图片

RGB赋值顶层

时钟生成
VGA (一)原理 时序及verilog 仿真_第10张图片
竖条的静态图像

module vga_test (
output [3:0] R,G,B,
output h_synch,v_synch,
input clk_i,rst_i
);

wire clk65M ;
wire dp_en ;

design_1 DCM (
             .clk_in1(clk_i),
             .clk_out1(clk65M),
             .locked(),
             .reset(1'b0)
         );

wire [9:0]line_count ;
wire [10:0]pixel_count ;

my_vga_syn my_vga_syn(
               .pixel_clock( clk65M  ),
               .rst_i( rst_i ),
               .h_synch( h_synch ),
               .v_synch( v_synch ),
               .dp_en( dp_en ),
               .line_count( line_count  ),
               .pixel_count ( pixel_count )
           );

reg[3:0] Rr , Gr , Br ;
always@ (posedge clk65M)
case ( pixel_count )
    128*4 : { Rr , Gr , Br } <={ 4'b0000  ,  4'b0000  ,  4'b0000  } ;
    128*1 : { Rr , Gr , Br } <={ 4'b0000  ,  4'b0000  ,  4'b1111  } ;
    128*2 : { Rr , Gr , Br } <={ 4'b0000  ,  4'b1111  ,  4'b0000  } ;
    128*3 : { Rr , Gr , Br } <={ 4'b0000  ,  4'b1111  ,  4'b1111  } ;
    128*0 : { Rr , Gr , Br } <={ 4'b1111  ,  4'b0000  ,  4'b0000  } ;
    128*5 : { Rr , Gr , Br } <={ 4'b1111  ,  4'b0000  ,  4'b1111  } ;
    128*6 : { Rr , Gr , Br } <={ 4'b1111  ,  4'b1111  ,  4'b0000  } ;
    128*7 : { Rr , Gr , Br } <={ 4'b1111  ,  4'b1111  ,  4'b1111  } ;
endcase

assign B = ( dp_en == 0 ) ? 0 : Br ;
assign G = ( dp_en == 0 ) ? 0 : Gr ;
assign R = ( dp_en == 0 ) ? 0 : Rr ;

endmodule

你可能感兴趣的:(verilog)