Index: rtl/vid_ctl/vid_control.v
===================================================================
--- rtl/vid_ctl/vid_control.v	(revision 284)
+++ rtl/vid_ctl/vid_control.v	(working copy)
@@ -49,7 +49,8 @@
    Copyright 2006-2007, Timothy Miller - howard.parkin@gmail.com
    Copyright 2006-2007, Howard Parkin - theosib@gmail.com
    Copyright 2006-2007, Patrick McNamara - wpm@openhardwarefoundation.net
- 
+   Copyright 2008, Michael Meeuwisse
+
  Comments:
  
  file changelog:
@@ -69,9 +70,8 @@
            controller functionality.                                            
                                                                                 
 inputs:                                                                         
- vid_clock -- clock: Clock signal that drives the majority of the video         
-              controlller logic.  Frequency is 1/2 the pixel clock frequency of 
-              the current screen mode.                                          
+ base_clock0 -- clock: Base 133 MHz clock, used for generating other clocks
+ base_clock1 -- clock: Base 156.25 MHz clock, used for generating other clocks
  pci_clock -- clock: PCI bus clock signal.  Provides a clock signal for the     
               control register logic that must be written from the PCI clock    
               domain.                                                           
@@ -97,6 +97,9 @@
                     the data is ready or not, so the signal is irrelivant.      
                                                                                 
 outputs:                                                                        
+ vid_clock -- clock: Clock signal that drives the majority of the video         
+              controlller logic.  Frequency is 1/2 the pixel clock frequency of 
+              the current screen mode.                                          
  req_addr -- bus, 25:  This is the starting address for a pixel data fetch being
              submitted to the memory controller for processing.                 
  req_enq -- active high:  If this signal is asserted during the rising edge of  
@@ -155,6 +158,8 @@
 
 ***********************************************************************************/
 module vid_control(
+		   base_clock0,
+		   base_clock1,
 		   vid_clock,
 		   pci_clock,
 
@@ -182,7 +187,8 @@
 		   );
 
    //Module inputs.
-   input vid_clock;
+   input base_clock0;
+   input base_clock1;
    input pci_clock;
    input reset_;
    input [31:0] reg_write_data;
@@ -191,6 +197,7 @@
    input [0:255] in_fifo_data;
 
    //Module outputs
+   output vid_clock;
    output [11:0] req_count;
    output [27:0] req_addr;
    output 	 req_enq;
@@ -230,8 +237,12 @@
    reg  	  pix_per_ck;
    //register for stretching program reset signal
    reg [7:0] rst_reg;
+   //Registers for the clock generator
+   reg oe;
+   reg [5:0] divisor0;
+   reg [2:0] divisor1;
+   reg base_clock;
 
-   
    //Module wires
 
    //Contains the data enable, hsync, vsync, and cursor control signals from
@@ -269,10 +280,23 @@
    wire 	  addr;
    wire 	  inc;
    wire 	  send;
-   
-   
-   
+   //Output from clock generator
+   wire 	  out_clock;
 
+   assign vid_clock = out_clock;
+
+   // Instantiate a clock generator
+   clock_gen clock_generator(
+		.base_clock0(base_clock0),
+		.base_clock1(base_clock1),
+		.reset_(reset_),
+		.oe(oe),
+		.divisor0(divisor0),
+		.divisor1(divisor1),
+		.base_clock(base_clock),
+		.out_clock(out_clock)
+		);
+
    //instantiate a block RAM for the instruction unit program storage.
    //Layout is 512x36
    // synopsys translate_off
@@ -286,7 +310,7 @@
    RAMB16_S36_S36 dlist_ram (
 			     .DOA(ins), .DOPA(),
 			     .DOB(), .DOPB(),
-			     .ADDRA(ins_addr),  .CLKA(vid_clock),
+			     .ADDRA(ins_addr),  .CLKA(out_clock),
 			     .DIA(32'b0),  .DIPA(4'b0), 
 			     .DIB(reg_write_data),  .DIPB(4'b0),
 			     .ADDRB(reg_write_addr[8:0]),  .CLKB(pci_clock),
@@ -297,7 +321,7 @@
    //Instatiate pixel fetch unit.  Handles generation of of the fetch
    //address sent off to the memory controller
    pixel_fetch pix_fetch (
-			  .vid_clock (vid_clock),
+			  .vid_clock (out_clock),
 			  .reset_ (reset_),
 			  .load (load),
 			  .addr_base (addr_base),
@@ -313,7 +337,7 @@
    //Instatiate pixel send unit.  Takes pixel data coming back from the
    //memory controller and formats it for output.
    pixel_send pix_send (
-			.vid_clock (vid_clock),
+			.vid_clock (out_clock),
 			.reset_ (reset_),
 			.send (send),
 			.req_deq (deq_in_fifo),
@@ -328,7 +352,7 @@
    //video controller and executes the video controller program to
    //coordinate all the other functions.
    ins_unit ins_unit (
-		      .vid_clock (vid_clock),		  
+		      .vid_clock (out_clock),		  
 		      .reset_ (cpu_reset_),
 		      .out_signals(out_signals),
 		      .interrupt(interrupt),
@@ -351,7 +375,7 @@
    //XY tracking unit.  Tracks the current (x,y) location of the output
    //pixels for later use by the overlay units.
    pixelxy_ctl xy_unit(
-		       .vid_clock   (vid_clock),
+		       .vid_clock   (out_clock),
 		       .reset_      (reset_),
 		       .send         (send),
 		       .pix_per_ck   (pix_per_ck),
@@ -364,7 +388,7 @@
 
    //Self contained does not depend on reset_
    //The logic here is really just some signal delays and stretching
-   always @(posedge vid_clock) begin
+   always @(posedge out_clock) begin
       //delay the sync and data valid signals by three video clock
       //cycles to keep then in sync with the pixel output.
       sync_del1<=out_signals[4:2];
@@ -397,6 +421,10 @@
 	 video_enable <= 0;
 	 int_en <= 0;
 	 pc_start <=0;
+	 oe <= 0;
+	 divisor0 <= 0;
+	 divisor1 <= 0;
+	 base_clock <= 0;
    
       end else begin // if (!reset_)
 
@@ -416,6 +444,7 @@
 	      5: int_en <= reg_write_data;
 	      6: video_enable <= reg_write_data;
 	      8: pc_start <= reg_write_data;
+	      9: {oe, base_clock, divisor0, divisor1} <= reg_write_data;
 	      
 	    endcase
 	 end
Index: rtl/vid_ctl/clock_gen.v
===================================================================
--- rtl/vid_ctl/clock_gen.v	(revision 0)
+++ rtl/vid_ctl/clock_gen.v	(revision 0)
@@ -0,0 +1,201 @@
+/*
+ DUAL LICENSING
+ (1) This Work is licensed under GPL 2.0.  You have the right to use and
+ modify this Work, as long as you publish your changes to the Work.  See
+ the file GPL2.0 for the complete contents of the GNU GPL.
+ 
+ (2) This Work is also licensed as a proprietary work, all rights
+ belonging to Traversal Technology.   Traversal Technology may use this
+ Work under those terms and has the right to publish, license, and sell
+ this Work and derivative works as they see fit, all rights reserved.  
+ To remove these rights, you must remove this clause.
+ 
+ (3) Use of this work without clause (2) forfeits the right to use any 
+ trademarks owned by Traversal Technology, the Open Graphics Project, or 
+ related organizations.
+ 
+ (4) Patches, modifications, and extensions ("patches") to this Work 
+ that are submitted to the Open Graphics Project, the Open Graphics 
+ Mailing List, directly to Traversal Technology must be SIGNED by the 
+ author of said patch, granting Traversal Technology "rights to use"
+ under clause (2), as well as clause (1).  Unsigned patches will be 
+ ignored.
+
+ (5) Patches [see (4)] committed directly to an officially recognized 
+ source code repository are signed implicitly.  Those who have write
+ access to such a repository and who commit patches to that repository
+ grant Traversal Technology under clause (2), as well as clause (1), by 
+ virtue of having write access and choosing to submit patches.
+
+ (6) You retain the right to use the contents of your patches, and you
+ may retain copyright to your patches.  Sections (1) through (5) still 
+ apply. For special situations, you are encouraged to add comments to the
+ "contributions" section of this Work, indicating the nature of your 
+ patch.
+
+File: clock_gen.v
+
+Modules:  
+ clock_gen -- video clock generator
+ 
+Maintainer:
+ 
+Copyright:
+ Copyright 2008, Michael Meeuwisse
+                                                                                   
+Module: clock_gen
+
+Function: Generate arbitrary clock as set by divisors
+                                                                                
+Inputs:                                                                         
+ base_clock0 -- clock: First clock used as source to generate others.
+ base_clock1 -- clock: Second clock used as source to generate others.
+ reset_      -- active low: System reset signal. Resets the divisors.
+ oe          -- active high: Enable output.
+ divisor0    -- bus, 6: The value used in the first division.
+ divisor1    -- bus, 3: The (encoded) value used in the second division.
+ base_clock  -- active high: Base clock to use for output
+
+Outputs:
+ out_clock   -- clock: Arbitrary generated clock
+
+Comments:
+ The base clocks are 133 and 156.25MHz. This is divided by divisor0,
+  after which the resulting clock may not be higher than 6.875MHz. This
+  is then multiplied by 48 (which has an upper limit of 330MHz, hence the
+  6.875MHz input limit) and divided again by 1, 2, 4, 8, 16 or 32.
+  The values for the divisor can be determined externally. For example;
+  (156.25 / 75) * 48 / 4 = 25 MHz out. Note that the video controller
+  needs half the frequency of the current screen mode, so a divisor of 8 
+  should be used.
+
+ divisor0 may not be lower than 23 when base_clock1 is selected, and not
+  be lower than 19 when base_clock0 is selected.
+
+ divisor1 is set as follows:
+  000 - illegal
+  001 - divide by 1
+  010 - divide by 2
+  011 - divide by 4
+  100 - divide by 8
+  101 - divide by 16
+  110 - divide by 32
+  111 - illegal
+
+Module change log:
+
+TODO:
+ What is the behaviour of the DCM when its input clock is too fast?
+
+*/
+
+`timescale 1ns / 1ps
+
+module clock_gen (
+	base_clock0,
+	base_clock1,
+	reset_,
+	oe,
+	divisor0,
+	divisor1,
+	base_clock,
+	out_clock
+	);
+
+input base_clock0;
+input base_clock1;
+input reset_;
+input oe;
+input [5:0] divisor0;
+input [2:0] divisor1;
+input base_clock;
+
+output out_clock;
+
+reg [5:0] divisor0_cur;
+reg [3:0] divisor1_cur;
+
+wire divisor0_in;
+reg divisor0_out;
+wire divisor1_in;
+reg divisor1_out;
+wire out_clock_int;
+
+// Was the last division by floor or ceil?
+reg toggle_odd;
+
+// Tie selected clock to divisor0_in
+assign divisor0_in = base_clock? base_clock1: base_clock0;
+
+// Divide base clock
+always @(posedge divisor0_in or negedge reset_) begin
+	if(!reset_) begin
+		divisor0_cur <= 0;
+		divisor1_cur <= 0;
+		divisor0_out <= 0;
+		divisor1_out <= 0;
+		toggle_odd <= 0;
+	end else begin
+		if(!divisor0_cur) begin
+			divisor0_out <= ~divisor0_out;
+			// Toggle causes a non-50/50 duty cycle, DCM corrects this
+			divisor0_cur <= (divisor0 >> 1) + (divisor0[0] & toggle_odd) - 1;
+			toggle_odd <= ~toggle_odd;
+		end else
+			divisor0_cur <= divisor0_cur - 1;
+	end
+end
+
+// Tie DCM to output of first division
+DCM Vid_DCM ( 
+    .CLKIN     (divisor0_out), // insert clock input
+    .CLKFB     (), // insert clock feedback
+    .DSSEN     (1'b0), // Spread spectrum enable input
+    .PSINCDEC  (1'b0), // Phase shifting - increment/decrement input
+    .PSEN      (1'b0), // Phase shifting - enable input 
+    .PSCLK     (1'b0), // Phase shifting - clock input
+    .RST       (1'b0), // DCM reset input
+    .CLK0      (), // clock output
+    .CLK90     (), // clock output
+    .CLK180    (), // clock output
+    .CLK270    (), // clock output
+    .CLK2X     (), // clock output
+    .CLK2X180  (), // clock output
+    .CLKDV     (), // clock output
+    .CLKFX     (divisor1_in), // clock output
+    .CLKFX180  (), // clock output
+    .LOCKED    (), // Locked signal
+    .PSDONE    (), // Phase shifting done output
+    .STATUS    ()  // Status bus output
+    );
+
+defparam Vid_DCM.DLL_FREQUENCY_MODE = "HIGH";
+defparam Vid_DCM.DUTY_CYCLE_CORRECTION = "TRUE";
+defparam Vid_DCM.STARTUP_WAIT = "FALSE";
+defparam Vid_DCM.CLKFX_DIVIDE = 1;
+defparam Vid_DCM.CLKFX_MULTIPLY = 48;
+
+// Divide the second time
+always @(posedge divisor1_in) begin
+	if(!divisor1_cur) begin
+		divisor1_out = ~divisor1_out;
+		case(divisor1) begin
+			2: divisor1_cur <= 4'b0000; // n/2
+			3: divisor1_cur <= 4'b0001; // n/4
+			4: divisor1_cur <= 4'b0010; // n/8
+			5: divisor1_cur <= 4'b0100; // n/16
+			default: divisor1_cur <= 4'b1000; // n/32
+		end
+	end else
+		divisor1_cur <= divisor1_cur - 1;
+end
+
+// Output the result, mux from divisor1_in if divisor1 is set to 1
+assign out_clock_int = oe & (divisor1 == 3'b001? divisor1_in: divisor1_out);
+
+BUFG out_clock_BUFG(
+	.I(out_clock_int),
+	.O(out_clock)
+	);
+
+endmodule
Index: rtl/oga1/s3/s3_top_level.v
===================================================================
--- rtl/oga1/s3/s3_top_level.v	(revision 284)
+++ rtl/oga1/s3/s3_top_level.v	(working copy)
@@ -51,6 +51,7 @@
    Copyright 2007, Nicholas Sinnott-Armstrong - nova@macintoshclub.com
    Copyright 2007, Patrick McNamara - wpm@openhardwarefoundation.net
    Copyright 2008, Andre Pouliot - andre.pouliot@gmail.com
+   Copyright 2008, Michael Meeuwisse
  
  Comments:
  
@@ -114,9 +115,9 @@
 module Spartan3_top_level(
     // Clock inputs
     // Tempory hack to make everything pass synthesis
-	input mem_clock_ext,
-    input vid0_clock_ext,
-    input vid1_clock_ext,
+    input mem_clock_ext,
+    input base_clock0,
+    input base_clock1,
 	 
 	 //reset
 	 input reset_,//AP
@@ -549,16 +550,6 @@
     .O(mem_clock_rd) 
     );
     
-BUFG Vid0_BUFG ( 
-    .I(vid0_clock_ext),
-    .O(vid0_clock) 
-    );
-    
-BUFG Vid1_BUFG ( 
-    .I(vid1_clock_ext),
-    .O(vid1_clock) 
-    );
-
 s3_bridge bridge(
     .clock(br_clock),
     .reset_(reset_),
@@ -863,9 +854,11 @@
 
 
 video_wrapper vc0(
-    .vid_clock(vid0_clock),
+    .base_clock0(base_clock0),
+    .base_clock1(base_clock1),
     .mem_clock(mem_clock),
     .reset_(reset_),
+    .vid_clock(vid0_clock),
     
     .reg_clock(br_clock),
     .reg_write_addr(eng_addr_int[9:0]),
@@ -891,9 +884,11 @@
 
 // vid1
 video_wrapper vc1(
-    .vid_clock(vid1_clock),
+    .base_clock0(base_clock0),
+    .base_clock1(base_clock1),
     .mem_clock(mem_clock),
     .reset_(reset_),
+    .vid_clock(vid1_clock),
     
     .reg_clock(br_clock),
     .reg_write_addr(eng_addr_int[9:0]),
Index: rtl/oga1/s3/vid_wrapper.v
===================================================================
--- rtl/oga1/s3/vid_wrapper.v	(revision 284)
+++ rtl/oga1/s3/vid_wrapper.v	(working copy)
@@ -1,10 +1,12 @@
 
 
 module video_wrapper(
-    input vid_clock,
+    input base_clock0,
+    input base_clock1,
     input mem_clock,
     input reset_,
-    
+    output vid_clock,
+
     input reg_clock,
     input [31:0] reg_write_data,
     input [9:0] reg_write_addr,
@@ -32,10 +34,14 @@
 wire [11:0] req_count_fifo;
 wire req_enq_fifo;
 
+wire out_clock;
+
+assign vid_clock = out_clock;
+
 async_fifo_16 #(25+10) request (
     .reset(reset_ && vid_rst_),
     
-    .in_clock(vid_clock),
+    .in_clock(out_clock),
     
     // Only forward a 25-bit address and 10-bit count for now
     .data_in({req_addr_fifo[24:0], req_count_fifo[9:0]}),
@@ -53,7 +59,9 @@
 
 
 vid_control vc(
-    .vid_clock(vid_clock),
+    .base_clock0(base_clock0),
+    .base_clock1(base_clock1),
+    .vid_clock(out_clock),
     .pci_clock(reg_clock),
     .reset_(reset_),
     
