FPGA – VGA display protocol

VGA (Video Grapghics Array) is a standard protocol for video transmission using model signals. The RGB565 image mode is used here
VGA display principle
The VGA display does not directly display the image on the display, but scans the pixels that make up the image from top to bottom and from left to right under the synchronization of the horizontal synchronization signal and the vertical synchronization signal. Scan to the display screen in order from right to left.

Under the action of horizontal and vertical synchronous signals, the scanning coordinates are positioned to the coordinates of the first pixel point in the upper left corner. In the process of scanning, each pixel is assigned a value individually, so that each pixel displays the corresponding color information. When one frame of image scanning is completed, the scanning of the next frame of image starts, and the cycle repeats. When the scanning speed is sufficient Fast, coupled with the characteristics of human persistence of vision, the complete image will be displayed.
VGA Timing Standard
VGA timing is composed of two parts, line synchronization timing and field synchronization timing. The row synchronization timing is shown in the figure below.

The line scan cycle is divided into six parts, synchronization, trailing edge, left frame, active image, right frame, and leading edge. The field scanning period is similar, except for the upper and lower borders. After the scanning is completed, the image will only appear in the effective image range of the row and field.
VGA parameter setting

The picture above is one of the VGA display modes, 640×480@60. 640 means that the number of pixels of the effective line image is 640, and 480 means the number of pixels of the effective field image. 60 means that the VGA monitor refreshes the image 60 times per second, that is, the number of display frames is 60. 650×480=307200, that is, each frame of image contains 307200 pixels. The operating clock in this display mode is 25.175MHz. The clock period is equal to the line scan period × field scan period × refresh rate.
Programming
The overall design block diagram is shown in the figure below.

Clock generation module (pll): used to generate the clock for VGA work.
Image generation module (VGA_PIC): Determine the pixel points of each effective image area through the coordinate signal passed in by the control module. Enter image information. The image data generation module takes the pixel coordinates (pix_x, pix_y) passed in by the VGA timing control module as the constraint bar
file to generate the color information (pix_data) of the color bar image to be displayed
Image control module (VGA_CTRL): Longer line field synchronization signal, find out the effective image area and specify the zero point coordinates. Input RGB information and horizontal and vertical synchronization signals.

Image Control Module Code

module vga_ctrl
(
    input wire vga_clk , //input working clock, frequency 25MHz
    input wire sys_rst_n , //input reset signal, active low
    input wire [15:0] pix_data , //Input pixel color information

    output wire [9:0] pix_x , //output X-axis coordinates of pixels in VGA effective display area
    output wire [9:0] pix_y , //Output VGA effective display area pixel Y-axis coordinates
    output wire hsync , //Output line synchronization signal
    output wire vsync , //Output field sync signal
    output wire [15:0] rgb //output pixel color information
);

parameter H_SYNC = 10'd96 , //line synchronization
          H_BACK = 10'd40 , //row timing trailing edge
          H_LEFT = 10'd8 , //Left border of row timing
          H_VALID = 10'd640 , //line valid data
          H_RIGHT = 10'd8 , //Right border of row timing
          H_FRONT = 10'd8 , //leading edge of row timing
          H_TOTAL = 10'd800 ; //line scan cycle
parameter V_SYNC = 10'd2 , //field synchronization
          V_BACK = 10'd25 , // field timing trailing edge
          V_TOP = 10'd8 , //field timing top border
          V_VALID = 10'd480 , // field valid data
          V_BOTTOM = 10'd8 , //bottom frame of field timing
          V_FRONT = 10'd2 , //Front edge of field timing
          V_TOTAL = 10'd525 ; // field scan period


wire rgb_valid ; //VGA effective display area
wire pix_data_req ; //pixel color information request signal
reg [9:0] cnt_h ; // line synchronization signal counter
reg [9:0] cnt_v ; //Vertical sync signal counter


always@(posedge vga_clk or negedge sys_rst_n)
    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;


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


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


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


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


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


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: output pixel color information
assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;

endmodule

Image generation module code

module vga_pic
(
    input wire vga_clk , //input working clock, frequency 25MHz
    input wire sys_rst_n , //input reset signal, active low
    input wire [9:0] pix_x , //Input the X-axis coordinates of pixels in the VGA effective display area
    input wire [9:0] pix_y , //Input the Y-axis coordinates of pixels in the VGA effective display area

    output reg [15:0] pix_data // output pixel color information
);


parameter H_VALID = 10'd640 , //line valid data
            V_VALID = 10'd480 ; // field valid data

parameter RED = 16'hF800, //red
            ORANGE = 16'hFC00, //Orange
            YELLOW = 16'hFFE0, //yellow
            GREEN = 16'h07E0, //green
            CYAN = 16'h07FF, //cyan
            BLUE = 16'h001F, //blue
            PURPPLE = 16'hF81F, //purple
            BLACK = 16'h0000, //black
            WHITE = 16'hFFFF, //white
            GRAY = 16'hD69A; // gray

//pix_data: Output pixel color information, specify the current pixel color data according to the current pixel coordinates
always@(posedge vga_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        pix_data <= 16'd0;
    else if((pix_x >= 0) & amp; & amp; (pix_x < (H_VALID/10)*1))
        pix_data <= RED;
    else if((pix_x >= (H_VALID/10)*1) & amp; & amp; (pix_x < (H_VALID/10)*2))
        pix_data <= ORANGE;
    else if((pix_x >= (H_VALID/10)*2) & amp; & amp; (pix_x < (H_VALID/10)*3))
        pix_data <= YELLOW;
    else if((pix_x >= (H_VALID/10)*3) & amp; & amp; (pix_x < (H_VALID/10)*4))
        pix_data <= GREEN;
    else if((pix_x >= (H_VALID/10)*4) & amp; & amp; (pix_x < (H_VALID/10)*5))
        pix_data <= CYAN;
    else if((pix_x >= (H_VALID/10)*5) & amp; & amp; (pix_x < (H_VALID/10)*6))
        pix_data <= BLUE;
    else if((pix_x >= (H_VALID/10)*6) & amp; & amp; (pix_x < (H_VALID/10)*7))
        pix_data <= PURPPLE;
    else if((pix_x >= (H_VALID/10)*7) & amp; & amp; (pix_x < (H_VALID/10)*8))
        pix_data <= BLACK;
    else if((pix_x >= (H_VALID/10)*8) & amp; & amp; (pix_x < (H_VALID/10)*9))
        pix_data <= WHITE;
    else if((pix_x >= (H_VALID/10)*9) & amp; & amp; (pix_x < H_VALID))
        pix_data <= GRAY;
    else
        pix_data <= BLACK;

endmodule

top level module

module vga_colorbar
(
    input wire sys_clk , //input working clock, frequency 50MHz
    input wire sys_rst_n , //input reset signal, active low

    output wire hsync , //Output line synchronization signal
    output wire vsync , //Output field sync signal
    output wire [15:0] rgb // output pixel information
);


wire vga_clk ; //VGA working clock, frequency 25MHz
wire locked; //PLL locked signal
wire rst_n ; //VGA module reset signal
wire [9:0] pix_x ; //VGA effective display area X-axis coordinates
wire [9:0] pix_y ; //VGA effective display area Y-axis coordinates
wire [15:0] pix_data; //VGA pixel color information


assign rst_n = (sys_rst_n & locked);



clk_gen clk_gen_inst
(
    .areset (~sys_rst_n ), //Input reset signal, active high, 1bit
    .inclk0 (sys_clk ), //Input 50MHz crystal oscillator clock, 1bit

    .c0 (vga_clk ), //output VGA working clock, frequency 25Mhz, 1bit
    .locked (locked ) //Output pll locked signal, 1bit
);


vga_ctrl vga_ctrl_inst
(
    .vga_clk (vga_clk ), //Input working clock, frequency 25MHz, 1bit
    .sys_rst_n (rst_n ), //Input reset signal, active low, 1bit
    .pix_data (pix_data ), //Input pixel color information, 16bit

    .pix_x (pix_x ), //Output X-axis coordinates of pixels in VGA effective display area, 10bit
    .pix_y (pix_y ), //Output Y-axis coordinates of pixels in VGA effective display area, 10bit
    .hsync (hsync ), //Output line synchronization signal, 1bit
    .vsync (vsync ), //Output field sync signal, 1bit
    .rgb (rgb ) //output pixel color information, 16bit
);


vga_pic vga_pic_inst
(
    .vga_clk (vga_clk ), //Input working clock, frequency 25MHz, 1bit
    .sys_rst_n (rst_n ), //Input reset signal, active low, 1bit
    .pix_x (pix_x ), //Input the X-axis coordinates of pixels in the VGA effective display area, 10bit
    .pix_y (pix_y ), //Input the Y-axis coordinates of pixels in the VGA effective display area, 10bit

    .pix_data (pix_data ) //output pixel color information, 16bit

);

endmodule

Simulation results

Refresh sixty times per second, about 16.6666ms each time, as shown in the figure above.