`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:  Universität des Saarlands
// Engineer: Erik Endres
//
// Create Date:   01:29:18 09/15/2007
// Design Name:   DLX
// Module Name:   DcmClk_unit
// Project Name:  DLX
// Target Device:  Spartan3
// Tool versions:  8.1i
// Description:	 This modul generates the clk signals for the DLX design with a DCM. 
//			It holds up the reset_o signal for a specified period so that the signal from 
//			a bouncing switch it fixed and releases the reset_o signal after the DCM
//			has locked the clk signals.
//			The clk input has to be a 66 MHz clk signal, the genereated clk signals are
//			clk_o		16,5 Mhz for the DLX
//			uartclk_o	66Mhz for the UART interface
//
// Dependencies:
// 
// Revision:
// Revision 0.02
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module DcmClk_unit(clk_i, reset_i, clk_o, uartclk_o, reset_o);

	input clk_i, reset_i;
	output clk_o, uartclk_o, reset_o;
	
	reg [31:0] resetcnt = 1500;
	reg dcm_reset = 1;
	
	wire clkin_ibufg;
	wire clk_buf;
	wire uartclk_buf;
	wire locked;
	wire clkfb_in;
	
	wire GND1;
   
   assign GND1 = 0;
	assign reset_o = dcm_reset || !locked;
	assign uartclk_o = clkfb_in;

   IBUFG clkin_ibufg_inst (
		.I(clk_i), 
      .O(clkin_ibufg));

	BUFG uartclk_buf_inst(
		.I (uartclk_buf),
		.O (clkfb_in));
	
	BUFG clk_buf_inst(
		.I (clk_buf),
		.O (clk_o));

	DCM dlx_dcm(
		.CLKFB(clkfb_in),
		.CLKIN(clkin_ibufg),
		.DSSEN(GND1),
		.PSCLK(GND1),
		.PSEN(GND1),
		.PSINCDEC(GND1),
		.RST(dcm_reset),
		.CLKDV(clk_buf),
		.CLKFX(),
		.CLKFX180(),
		.CLK0(uartclk_buf),
		.CLK2X(),
		.CLK2X180(),
		.CLK90(),
		.CLK180(),
		.CLK270(),
		.LOCKED(locked),
		.PSDONE(),
		.STATUS());
		
   defparam dlx_dcm.CLK_FEEDBACK = "1X";
   defparam dlx_dcm.CLKDV_DIVIDE = 4.000000;
   defparam dlx_dcm.CLKFX_DIVIDE = 1;
   defparam dlx_dcm.CLKFX_MULTIPLY = 4;
   defparam dlx_dcm.CLKIN_DIVIDE_BY_2 = "FALSE";
   defparam dlx_dcm.CLKIN_PERIOD = 15.1515;
   defparam dlx_dcm.CLKOUT_PHASE_SHIFT = "NONE";
   defparam dlx_dcm.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
   defparam dlx_dcm.DFS_FREQUENCY_MODE = "LOW";
   defparam dlx_dcm.DLL_FREQUENCY_MODE = "LOW";
   defparam dlx_dcm.DUTY_CYCLE_CORRECTION = "TRUE";
   defparam dlx_dcm.FACTORY_JF = 16'h8080;
   defparam dlx_dcm.PHASE_SHIFT = 0;
   defparam dlx_dcm.STARTUP_WAIT = "FALSE";
	
	// synthesis attribute CLK_FEEDBACK of dlx_dcm is "1X"
	// synthesis attribute CLKDV_DIVIDE of dlx_dcm is 4.0
	// synthesis attribute CLKFX_DIVIDE of dlx_dcm is 1
	// synthesis attribute CLKFX_MULTIPLY of dlx_dcm is 4
	// synthesis attribute CLKIN_DIVIDE_BY_2 of dlx_dcm is "FALSE"
	// synthesis attribute CLKIN_PERIOD of dlx_dcm is 15.151500
	// synthesis attribute CLKOUT_PHASE_SHIFT of dlx_dcm is "NONE"
	// synthesis attribute DESKEW_ADJUST of dlx_dcm is "SYSTEM_SYNCHRONOUS"
	// synthesis attribute DFS_FREQUENCY_MODE of dlx_dcm is "LOW"
	// synthesis attribute DLL_FREQUENCY_MODE of dlx_dcm is "LOW"
	// synthesis attribute DUTY_CYCLE_CORRECTION of dlx_dcm is "TRUE"
	// synthesis attribute FACTORY_JF of dlx_dcm is 8080
	// synthesis attribute PHASE_SHIFT of dlx_dcm is 0
	// synthesis attribute STARTUP_WAIT of dlx_dcm is "FALSE"

	always@(posedge clkin_ibufg)
	begin
		if (reset_i)
			begin
				resetcnt <= 1500;
				dcm_reset <= 1'b1;
			end
		else
			begin
				if (resetcnt == 0)
					dcm_reset <= 1'b0;
				else
					begin
						resetcnt <= resetcnt - 1;
						dcm_reset <= 1'b1;
					end
			end
	end

endmodule
