From dd24468d48d6a508c300ec9ce22aa373b795e5d4 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Thu, 5 Nov 2009 12:02:23 +0000 Subject: [PATCH] Initial version Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@609 cc03376c-175c-47c8-b038-4cd826a8556b --- projects/mips_sys/src/clockgen_virtex4.vhd | 310 +++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 projects/mips_sys/src/clockgen_virtex4.vhd diff --git a/projects/mips_sys/src/clockgen_virtex4.vhd b/projects/mips_sys/src/clockgen_virtex4.vhd new file mode 100644 index 0000000..9e40184 --- /dev/null +++ b/projects/mips_sys/src/clockgen_virtex4.vhd @@ -0,0 +1,310 @@ +------------------------------------------------------------------------- +-- 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 . +-- +-- For questions and ideas, please contact the author at jens@jayfield.org +-- +-------------------------------------------------------------------------- + +library ieee, work; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +USE WORK.utils_pkg.ALL; + +Library UNISIM; +use UNISIM.vcomponents.all; + +entity clockgen is + generic + ( + clk_in_freq_hz : integer := 100E6; + vga_clk_out_freq_hz : integer := 0; + sdr_clk0_out_phaseshift : integer := 0; + sdr_clk1_out_phaseshift : integer := 0 + ); + port + ( + -- Clocks and Reset + rst : in std_logic; -- external async reset, low active + clk_in : in std_logic; -- system clock (e.g. 100MHz), from board + sys_clk_out : out std_logic; + vga_clk_out : out std_logic; + sdr_clk0_fb_in : in std_logic; -- feedback clock + sdr_clk0_0_out : out std_logic; -- System clock #0, dcm#0 output 0° + sdr_clk0_270_out : out std_logic; -- System clock #0, dcm#0 output 270° + sdr_clk1_0_out : out std_logic; -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 0° + sdr_clk1_270_out : out std_logic; -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 270° + locked_out : out std_logic; -- DCM locked status + error_out : out std_logic -- indicates DCM Errors + ); +end; + +architecture tech of clockgen is + + signal locked : unsigned(2 downto 0); + signal dcm_rst : unsigned(2 downto 0); + signal dcm0_clk0 : std_logic; + signal dcm0_clk0_bufg : std_logic; + signal dcm0_clkfx : std_logic; + signal dcm1_clk0 : std_logic; + signal dcm1_clk270 : std_logic; + signal dcm1_clk0_bufg : std_logic; + signal dcm1_clk270_bufg : std_logic; + signal dcm2_clk0 : std_logic; + signal dcm2_clk270 : std_logic; + signal dcm2_clk0_bufg : std_logic; + signal dcm2_clk270_bufg : std_logic; + signal dcm0_locked : unsigned(2 downto 0); + signal dcm1_locked : unsigned(2 downto 0); + signal dcm2_locked : unsigned(2 downto 0); + signal cnt_q : unsigned(4 downto 0); + + type STATE_TYPE is (s0, s1, s2, s3, s4); + signal state_q : STATE_TYPE; + +begin + + sdr_clk0_0_out <= dcm1_clk0_bufg; + sdr_clk0_270_out <= dcm1_clk270_bufg; + sdr_clk1_0_out <= dcm2_clk0_bufg; + sdr_clk1_270_out <= dcm2_clk270_bufg; + +bufg11: bufg + port map + ( + o => dcm1_clk0_bufg, + i => dcm1_clk0 + ); + +bufg12: bufg + port map ( + o => dcm1_clk270_bufg, + i => dcm1_clk270 + ); + +bufg13: bufg + port map + ( + o => dcm2_clk0_bufg, + i => dcm2_clk0 + ); + +bufg14: bufg + port map ( + o => dcm2_clk270_bufg, + i => dcm2_clk270 + ); + + ------------------------------------------------------------------------------------------------------- + -- Clock generation + ------------------------------------------------------------------------------------------------------- + + -- Compnent instantiation + inst_DCM_BASE_0 : 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_hz, vga_clk_out_freq_hz), -- Can be any interger from 1 to 32 + CLKFX_MULTIPLY => UTILS_FREQ_M(clk_in_freq_hz, vga_clk_out_freq_hz), -- 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_hz), -- 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 => "SYSTEM_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 => dcm0_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 => dcm0_clkfx, -- DCM CLK synthesis out (M/D) + CLKFX180 => open, -- 180 degree CLK synthesis out + LOCKED => locked(0), -- DCM LOCK status output + CLKFB => dcm0_clk0_bufg, -- DCM clock feedback + CLKIN => clk_in, -- Clock input (from IBUFG, BUFG or DCM) + RST => dcm_rst(0) -- DCM asynchronous reset input + ); + + BUFG_dcm_clk_fb : BUFG + port map + ( + O => dcm0_clk0_bufg, -- Clock buffer output + I => dcm0_clk0 -- Clock buffer input + ); + + BUFG_clk_out : BUFG + port map + ( + O => vga_clk_out, -- Clock buffer output + I => dcm0_clkfx -- Clock buffer input + ); + + sys_clk_out <= dcm0_clk0_bufg; + +inst_DCM_BASE_1 : 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 => 1, -- Can be any interger from 1 to 32 + CLKFX_MULTIPLY => 4, -- 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_hz), -- Specify period of input clock in ns from 1.25 to 1000.00 + CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift mode of NONE or FIXED + CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE or 1X + DCM_AUTOCALIBRATION => TRUE, -- DCM calibrartion circuitry TRUE/FALSE + 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 => sdr_clk0_out_phaseshift, -- Amount of fixed phase shift from -255 to 1023 + STARTUP_WAIT => FALSE -- Delay configuration DONE until DCM LOCK, TRUE/FALSE + ) + port map + ( + CLK0 => dcm1_clk0, -- 0 degree DCM CLK ouptput + CLK180 => open, -- 180 degree DCM CLK output + CLK270 => dcm1_clk270, -- 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 => open, -- DCM CLK synthesis out (M/D) + CLKFX180 => open, -- 180 degree CLK synthesis out + LOCKED => locked(1), -- DCM LOCK status output + CLKFB => sdr_clk0_fb_in, -- DCM clock feedback + CLKIN => dcm0_clk0_bufg, -- Clock input (from IBUFG, BUFG or DCM) + RST => dcm_rst(1) -- DCM asynchronous reset input + ); + + dcm_rst(1) <= not locked(0); + + inst_DCM_BASE_2 : 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 => 1, -- Can be any interger from 1 to 32 + CLKFX_MULTIPLY => 4, -- 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_hz), -- Specify period of input clock in ns from 1.25 to 1000.00 + CLKOUT_PHASE_SHIFT => "FIXED", -- Specify phase shift mode of NONE or FIXED + CLK_FEEDBACK => "1X", -- Specify clock feedback of NONE or 1X + DCM_AUTOCALIBRATION => TRUE, -- DCM calibrartion circuitry TRUE/FALSE + DCM_PERFORMANCE_MODE => "MAX_SPEED", -- Can be MAX_SPEED or MAX_RANGE + DESKEW_ADJUST => "SYSTEM_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 => sdr_clk1_out_phaseshift, -- Amount of fixed phase shift from -255 to 1023 + STARTUP_WAIT => FALSE -- Delay configuration DONE until DCM LOCK, TRUE/FALSE + ) + port map + ( + CLK0 => dcm2_clk0, -- 0 degree DCM CLK ouptput + CLK180 => open, -- 180 degree DCM CLK output + CLK270 => dcm2_clk270, -- 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 => open, -- DCM CLK synthesis out (M/D) + CLKFX180 => open, -- 180 degree CLK synthesis out + LOCKED => locked(2), -- DCM LOCK status output + CLKFB => dcm2_clk0_bufg, -- DCM clock feedback + CLKIN => sdr_clk0_fb_in, -- Clock input (from IBUFG, BUFG or DCM) + RST => dcm_rst(2) -- DCM asynchronous reset input + ); + + dcm_rst(2) <= not locked(1); + +dcm_fsm: + process(rst, clk_in) + begin + if rst = '1' then + state_q <= s0; + dcm_rst(0) <= '0'; + cnt_q <= "11111"; + error_out <= '0'; + locked_out <= '0'; + dcm0_locked <= (others => '0'); + dcm1_locked <= (others => '0'); + dcm2_locked <= (others => '0'); + elsif rising_edge(clk_in) then + case state_q is + when s0 => + state_q <= s1; + + when s1 => + cnt_q <= cnt_q - 1; + if cnt_q = 0 then + dcm_rst(0) <= '1'; + state_q <= s2; + end if; + + when s2 => + cnt_q <= cnt_q - 1; + if cnt_q = 0 then + dcm_rst(0) <= '0'; + state_q <= s3; + end if; + + when s3 => + if dcm0_locked(2)='1' and dcm1_locked(2)='1' and dcm2_locked(2)='1' then + state_q <= s4; + error_out <= '0'; + end if; + + when s4 => + if dcm0_locked(2)='1' and dcm1_locked(2)='1' and dcm2_locked(2)='1' then + locked_out <= '1'; + else + error_out <= '1'; + end if; + end case; + + -- synchronize 'dcm1_locked' + dcm0_locked <= dcm0_locked(1 downto 0) & locked(0); + dcm1_locked <= dcm1_locked(1 downto 0) & locked(1); + dcm2_locked <= dcm2_locked(1 downto 0) & locked(2); + + end if; + end process; + +end architecture tech; + +