/* ============================================================================ (C) 2007 Robert T Finch All rights reserved. rob@BirdComputer.ca vgaSyncGen.v VGA sync generator This source code is available only for veiwing, testing and evaluation purposes. Any commercial use requires a license. This copyright statement and disclaimer must remain present in the file. NO WARRANTY. THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume the entire risk of using the Work. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED USE. VGA video sync generator. This module generates the basic sync timing signals required for a VGA display. This is a very flexible generator meaning any clock can be used. Default timing parameters for 31468Hz horizontal and 59.94Hz vertical timing are set given for any clock frequency. The number of bits used for the horizontal and vertical counters is programmable. The default calculates the number of bits required between 13 an 8 bits. These may need to be increased for higher resolution displays. The sync polarization is programable. A default of negative going sync is assumed. Note to self 57 LUTs / 30 slices / 138 MHz (speed Spartan3-4) ============================================================================ */ module vgaSyncGen(rst, clk, hSync, vSync, blank); parameter pClkFreq = 50000000; parameter phFreq = 36900; parameter pvFreq = 7500; // 75.00 * 100 parameter phDisplay = 720; parameter pvDisplay = 450; parameter pSyncLevel = 0; parameter phTotal = pClkFreq / phFreq; parameter phBits = phTotal>4095?13: // size of counter for horizontal phTotal>2047?12: phTotal>1023?11: phTotal>511?10: phTotal>255?9: 8; // these calcs for a standard 640 x 480 display // they may need to be adjusted for other display resolutions parameter phSyncWidth = phTotal * 120 / 1000; // 12% parameter phBlankOff = phTotal * 176 / 1000; parameter phBlankOn = phTotal * 976 / 1000; // 5.6% parameter phExtra = (phTotal * 8 / 10 - phDisplay)/2; parameter pvTotal = phFreq * 100 / pvFreq; // 3146900/5994 = 525 parameter pvBits = pvTotal>4095?13: // size of counter for vertical pvTotal>2047?12: pvTotal>1023?11: pvTotal>511?10: pvTotal>255?9: 8; parameter pvBlankOn = pvTotal-15; //10'd479; parameter pvSyncWidth = 4'd1; //2 scan lines parameter pvBlankOff = 10'd32; parameter pBits = pvBits < phBits ? phBits : pvBits; // set datapath width input rst; // reset input clk; // video clock // timing outputs output hSync, vSync; // sync outputs output blank; // blanking output //--------------------------------------------------------------------- //--------------------------------------------------------------------- reg [phBits-1:0] hCtr;// count from 0 to ??? reg [pvBits-1:0] vCtr; // count from 0 to 525 reg [4:0] vSyncCtr; // vertical sync width counter //--------------------------------------------------------------------- //--------------------------------------------------------------------- // Timing comparators // To eliminate a pair of comparators the assumption is // made that horizontal sync and vertical sync begin // when the corresponding counter is reset to zero. assign hReset = hCtr == phTotal; // 800 assign hSyncOn = hReset; assign hSyncOff = hCtr == phSyncWidth; assign hBlankOn = hCtr == phBlankOn; assign hBlankOff = hCtr == phBlankOff; assign vReset = vCtr == pvTotal; assign vBlankOn = vCtr == pvBlankOn; assign vBlankOff = vCtr == pvBlankOff; reg hSync, vSync; reg vBlank, hBlank; reg blank; // Generate composite signals always @(posedge clk) blank <= hBlank|vBlank; always @(posedge clk) vSync <= pSyncLevel ? ~vSyncCtr[4] : vSyncCtr[4]; // Horizontal counter always @(posedge clk) hCtr <= rst | hReset ? 0 : hCtr + 1; // Vertical counter always @(posedge clk) vCtr <= rst | vReset ? 0 : vCtr + hReset; // vertical sync counter // counts down the width of the vertical sync pulse always @(posedge clk) if (rst) vSyncCtr <= 5'b10000; else if (hReset) begin if (vReset) vSyncCtr <= {1'b0,pvSyncWidth}; else if (!vSyncCtr[4]) vSyncCtr <= vSyncCtr - 1; end // take care of horizontal timing signals always @(posedge clk) if (rst) begin hSync <= ~pSyncLevel; hBlank <= 1; end else begin hSync <= hSyncOn ? pSyncLevel : hSyncOff ? ~pSyncLevel : hSync; hBlank <= hBlankOn ? 1'b1 : hBlankOff ? 1'b0 : hBlank; end // take care of vertical blank signal always @(posedge clk) if (rst) vBlank <= 1; else if (hReset) vBlank <= vBlankOn ? 1'b1 : vBlankOff ? 1'b0 : vBlank; endmodule