//-------------------------------------------------------------------
//
//  Filename      : VGA_Controller.v
//  Author        : Huang Lei Lei
//  Created       : 2015-08-09
//  Description   : vga controller modified from TERASIC's VGA_Controller.v
//
//-------------------------------------------------------------------

module VGA_Controller(
  // Control Signal
  iCLK           ,
  iRST_N         ,
  // Host Side
  iRed           ,
  iGreen         ,
  iBlue          ,
  oRequest       ,
  // VGA Side
  oVGA_R         ,
  oVGA_G         ,
  oVGA_B         ,
  oVGA_H_SYNC    ,
  oVGA_V_SYNC    ,
  oVGA_SYNC      ,
  oVGA_BLANK
  );


//*** PARAMETER DECLARATION ****************************************************

  // Horizontal Parameter
  parameter H_SYNC_CYC   = 96   ;
  parameter H_SYNC_BACK  = 48   ;
  parameter H_SYNC_ACT   = 640  ;
  parameter H_SYNC_FRONT = 16   ;
  parameter H_SYNC_TOTAL = 800  ;
  // Vertical Parameter
  parameter V_SYNC_CYC   = 2    ;
  parameter V_SYNC_BACK  = 33   ;
  parameter V_SYNC_ACT   = 480  ;
  parameter V_SYNC_FRONT = 10   ;
  parameter V_SYNC_TOTAL = 525  ;
  //  Start Offset
  parameter X_START      = H_SYNC_CYC+H_SYNC_BACK ;
  parameter Y_START      = V_SYNC_CYC+V_SYNC_BACK ;


//*** INPUT/OUTPUT DECLARATION *************************************************

  //  Control Signal
  input                  iCLK        ;
  input                  iRST_N      ;
  // Host Side
  input      [9  : 0]    iRed        ;
  input      [9  : 0]    iGreen      ;
  input      [9  : 0]    iBlue       ;
  output reg             oRequest    ;
  // VGA Side
  output reg [9  : 0]    oVGA_R      ;
  output reg [9  : 0]    oVGA_G      ;
  output reg [9  : 0]    oVGA_B      ;
  output reg             oVGA_H_SYNC ;
  output reg             oVGA_V_SYNC ;
  output reg             oVGA_SYNC   ;
  output reg             oVGA_BLANK  ;


//*** WIRE/REG DECLARATION *****************************************************

  wire       [9  : 0]    mVGA_R      ;
  wire       [9  : 0]    mVGA_G      ;
  wire       [9  : 0]    mVGA_B      ;
  reg                    mVGA_H_SYNC ;
  reg                    mVGA_V_SYNC ;
  wire                   mVGA_SYNC   ;
  wire                   mVGA_BLANK  ;

  reg        [10 : 0]    H_Cont      ;
  reg        [10 : 0]    V_Cont      ;

  wire       [10 : 0]    v_mask      ;


//*** MAIN BODY ****************************************************************

  assign v_mask = 11'd0 ;

  assign mVGA_BLANK = mVGA_H_SYNC & mVGA_V_SYNC;
  assign mVGA_SYNC  = 1'b0;

  assign mVGA_R     = (  H_Cont>=X_START        && H_Cont<X_START+H_SYNC_ACT
                      && V_Cont>=Y_START+v_mask && V_Cont<Y_START+V_SYNC_ACT )  ? iRed   : 0 ;
  assign mVGA_G     = (  H_Cont>=X_START        && H_Cont<X_START+H_SYNC_ACT
                      && V_Cont>=Y_START+v_mask && V_Cont<Y_START+V_SYNC_ACT )  ? iGreen : 0 ;
  assign mVGA_B     = (  H_Cont>=X_START        && H_Cont<X_START+H_SYNC_ACT
                      && V_Cont>=Y_START+v_mask && V_Cont<Y_START+V_SYNC_ACT )  ? iBlue  : 0 ;

  always@(posedge iCLK or negedge iRST_N ) begin
    if( !iRST_N ) begin
      oVGA_R      <= 0 ;
      oVGA_G      <= 0 ;
      oVGA_B      <= 0 ;
      oVGA_BLANK  <= 0 ;
      oVGA_SYNC   <= 0 ;
      oVGA_H_SYNC <= 0 ;
      oVGA_V_SYNC <= 0 ;
    end
    else begin
      oVGA_R      <= mVGA_R      ;
      oVGA_G      <= mVGA_G      ;
      oVGA_B      <= mVGA_B      ;
      oVGA_BLANK  <= mVGA_BLANK  ;
      oVGA_SYNC   <= mVGA_SYNC   ;
      oVGA_H_SYNC <= mVGA_H_SYNC ;
      oVGA_V_SYNC <= mVGA_V_SYNC ;
    end
  end

  //  Pixel LUT Address Generator
  always@(posedge iCLK or negedge iRST_N ) begin
    if( !iRST_N )
      oRequest  <=  0;
    else begin
      if(  H_Cont>=X_START-2 && H_Cont<X_START+H_SYNC_ACT-2
        && V_Cont>=Y_START   && V_Cont<Y_START+V_SYNC_ACT )
        oRequest <= 1;
      else begin
        oRequest <= 0;
      end
    end
  end

  always@(posedge iCLK or negedge iRST_N ) begin
    if( !iRST_N ) begin
      H_Cont      <= 0 ;
      mVGA_H_SYNC <= 0 ;
    end
    else begin
      if( H_Cont < H_SYNC_TOTAL )
        H_Cont <= H_Cont+1 ;
      else begin
        H_Cont <= 0 ;
      end
      if( H_Cont < H_SYNC_CYC   )
        mVGA_H_SYNC <= 0 ;
      else begin
        mVGA_H_SYNC <= 1 ;
      end
    end
  end

  always@(posedge iCLK or negedge iRST_N ) begin
    if( !iRST_N ) begin
      V_Cont      <= 0 ;
      mVGA_V_SYNC <= 0 ;
    end
    else begin
      if( H_Cont==0 ) begin
        if( V_Cont < V_SYNC_TOTAL )
          V_Cont <= V_Cont+1 ;
        else begin
          V_Cont <= 0 ;
        end
        if( V_Cont < V_SYNC_CYC   )
          mVGA_V_SYNC <= 0 ;
        else begin
          mVGA_V_SYNC <= 1 ;
        end
      end
    end
  end

endmodule