-------------------------------------------------------------------------
-- Project: SDRAM controller
-- This file: Clock generator (Virtex-4 specific)
--
-- Copyright (C) 2007 J. Ahrensfeld
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------

library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

library WORK;
USE WORK.utils_pkg.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

entity clockgen is
	generic
	(
		clk_in_freq			: real	:= 100.0;
		clk_out_freq		: real	:= 100.0
	);
	port 
	(
		-- Clocks and Reset
		rst_in				: in std_logic;   -- external async reset, low active
		clk_in				: in std_logic;   -- system clock (e.g. 100MHz), from board
		rst_out				: out std_logic;
		clk_out				: out std_logic
	);
end;

architecture tech of clockgen is

	signal clk0               	: std_logic;
	signal clk0_bufg			: std_logic;
	signal clkfx	           	: std_logic;
	signal fx_lock				: std_logic;


begin 

	-------------------------------------------------------------------------------------------------------
	-- Clock generation
	-------------------------------------------------------------------------------------------------------

	inst_DCM_FX : DCM_BASE
	generic map 
	(
		CLKDV_DIVIDE => 2.0, -- Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
						   --   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
		CLKFX_DIVIDE => UTILS_FREQ_D(clk_in_freq, clk_out_freq),   -- Can be any interger from 1 to 32
		CLKFX_MULTIPLY => UTILS_FREQ_M(clk_in_freq, clk_out_freq), -- Can be any integer from 2 to 32
		CLKIN_DIVIDE_BY_2 => FALSE, -- TRUE/FALSE to enable CLKIN divide by two feature
		CLKIN_PERIOD => UTILS_PERIOD_NS(clk_in_freq), -- Specify period of input clock in ns from 1.25 to 1000.00
		CLKOUT_PHASE_SHIFT => "NONE", -- Specify phase shift mode of NONE or FIXED
		CLK_FEEDBACK => "1X",         -- Specify clock feedback of NONE or 1X
		DCM_PERFORMANCE_MODE => "MAX_SPEED",   -- Can be MAX_SPEED or MAX_RANGE
		DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
											 --   an integer from 0 to 15
		DFS_FREQUENCY_MODE => "LOW",   -- LOW or HIGH frequency mode for frequency synthesis
		DLL_FREQUENCY_MODE => "LOW",   -- LOW, HIGH, or HIGH_SER frequency mode for DLL
		DUTY_CYCLE_CORRECTION => TRUE, -- Duty cycle correction, TRUE or FALSE
		FACTORY_JF => X"F0F0",          -- FACTORY JF Values Suggested to be set to X"F0F0" 
		PHASE_SHIFT => 0, -- Amount of fixed phase shift from -255 to 1023
		STARTUP_WAIT => FALSE -- Delay configuration DONE until DCM LOCK, TRUE/FALSE
	)
	port map
	(
		CLK0 => clk0,         -- 0 degree DCM CLK ouptput
		CLK180 => open,     -- 180 degree DCM CLK output
		CLK270 => open,     -- 270 degree DCM CLK output
		CLK2X => open,       -- 2X DCM CLK output
		CLK2X180 => open, -- 2X, 180 degree DCM CLK out
		CLK90 => open,       -- 90 degree DCM CLK output
		CLKDV => open,       -- Divided DCM CLK out (CLKDV_DIVIDE)
		CLKFX => clkfx,       -- DCM CLK synthesis out (M/D)
		CLKFX180 => open, -- 180 degree CLK synthesis out
		LOCKED => fx_lock,     -- DCM LOCK status output
		CLKFB => clk0_bufg,       -- DCM clock feedback
		CLKIN => clk_in,       -- Clock input (from IBUFG, BUFG or DCM)
		RST => rst_in            -- DCM asynchronous reset input
	);

BUFG_clk0 : BUFG
	port map
	(
		O => clk0_bufg,     -- Clock buffer output
		I => clk0        -- Clock buffer input
	);

	clk_out	<= clkfx;

rst_out_reg:
	process(clkfx)
	begin
		if rising_edge(clkfx) then
			rst_out	<= not fx_lock;
		end if;
	end process;
		

end architecture tech;


