// this is small generator of static test pattern
// to check that VGA output is working on the board.
// It is working off the default 27MHz clock,
// and should output slightly out-of spec VGA signal
// that is acceptable by small monitor as 480*800 px image.
// Total is 840 pixels per line (including blanking)
// and 536 lines in frame (also including blanking)
// at 60 Hz framerate
module vga(
    input i_clk, // assuming 27MHz

    output o_hsync,
    output o_vsync,
    output [5:0] o_rgb222
);

    // set for 640*480 @ 60Hz; 
    // Because pixel clock is faster than standard,
    // actual image is 686 by 480 pixels
    // with rectangular pixels with height/width 
    // ratio of ~1.07
    localparam HBLANK_START = 686;
    localparam HSYNC_START = 706;
    localparam HSYNC_DURATION = 40;
    localparam LINE_END = 858;

    localparam VBLANK_START = 480;
    localparam VSYNC_START = 492;
    localparam VSYNC_DURATION = 2;
    localparam FRAME_END = 525;

    reg [9:0] r_pix_cnt = 10'h000;
    reg [9:0] r_line_cnt = 10'h000;
    reg [5:0] r_rgb_color = 6'b000000;
    reg       r_h_active = 1'b1;
    reg       r_v_active = 1'b1;
    reg       r_h_sync = 1'b0;
    reg       r_v_sync = 1'b0;

    always @(posedge i_clk) begin
        r_pix_cnt <= r_pix_cnt + 1;

        if(r_pix_cnt == HBLANK_START) begin
            r_h_active <= 1'b0;
        end

        if(r_pix_cnt == HSYNC_START) begin
            r_h_sync <= 1'b1;
        end

        if(r_pix_cnt == HSYNC_START + HSYNC_DURATION) begin
            r_h_sync <= 1'b0;
        end

        if(r_pix_cnt == LINE_END) begin
            r_h_active <= 1'b1;
            r_line_cnt <= r_line_cnt + 1;
            r_pix_cnt <= 10'h000;
        end

        if(r_line_cnt == VBLANK_START) begin
            r_v_active <= 1'b0;
        end

        if(r_line_cnt == VSYNC_START) begin
            r_v_sync <= 1'b1;
        end

        if(r_line_cnt == VSYNC_START + VSYNC_DURATION) begin
            r_v_sync <= 1'b0;
        end

        if(r_line_cnt == FRAME_END) begin
            r_v_active <= 1'b1;
            r_line_cnt <= 10'h000;
        end

        if(r_h_active == 1'b1 && r_v_active == 1'b1) begin
            r_rgb_color <= {r_pix_cnt[8:5], r_line_cnt[6:5]};
        end else begin
            r_rgb_color <= 6'h00;
        end
    end

    assign o_vsync = r_v_sync;
    assign o_hsync = r_h_sync;
    assign o_rgb222 = r_rgb_color;

endmodule
