library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library UNISIM; use UNISIM.VComponents.all; entity clock_gen is generic ( rst_width : integer := 32 -- width of the reset pulse in clk40-cycles -- valid : 0..63 ); port ( CLK120_N : in std_logic; -- 120MHz clock input from DCS board CLK120_P : in std_logic; CLK40_N : in std_logic; -- 40MHz clock input from DCS board CLK40_P : in std_logic; rst_req : in std_logic; -- async reset request clk40 : out std_logic; -- Post DCM clock output clk40_90 : out std_logic; clk40_180 : out std_logic; -- clocks are derived from clk40 clk80 : out std_logic; clk120 : out std_logic; -- and have constant phase relationship clk120_180 : out std_logic; clk160 : out std_logic; ps_adjust : in std_logic_vector(1 downto 0); ps_state : out std_logic_vector(9 downto 0); clk40_ps : out std_logic; -- 40 MHz clock with phase shift clk40_ps_180 : out std_logic; -- 40 MHz clock with phase shift (inverted) clk120dcs : out std_logic; rst40 : out std_logic; rst40_n : out std_logic; rst80 : out std_logic; rst120 : out std_logic; rst120_n : out std_logic; rst160 : out std_logic ); end clock_gen; architecture default of clock_gen is signal clk40_pre_dcm : std_logic; signal clk40_i : std_logic; signal clk40_90_i : std_logic; signal clk40_180_i : std_logic; signal clk80_i : std_logic; signal clk120_i : std_logic; signal clk120_180_i : std_logic; signal clk160_i : std_logic; signal clk40_pre_buf : std_logic; signal clk40_90_pre_buf : std_logic; signal clk40_180_pre_buf : std_logic; signal clk80_pre_buf : std_logic; signal clk120_pre_buf : std_logic; signal clk120_180_pre_buf : std_logic; signal clk40_fb : std_logic; signal clk40_fb_pre_buf : std_logic; signal clk160_pre_buf : std_logic; signal ps_adjust_r : std_logic_vector(ps_adjust'range); signal ps_en : std_logic; signal ps_value : std_logic_vector(8 downto 0); signal ps_done : std_logic; signal clk40_ps_fb_pre_buf : std_logic; signal clk40_ps_fb : std_logic; signal clk40_ps_180_fb_pre_buf : std_logic; signal clk40_ps_180_fb : std_logic; signal clk120dcs_pre_buf : std_logic; signal dcm_120_locked : std_logic; signal dcm_160_locked : std_logic; signal rst_master : std_logic; signal rst_cnt : std_logic_vector(5 downto 0); signal rst_pulse_width : std_logic_vector(5 downto 0); begin -- default -- -- Output mapping clk40 <= clk40_i; clk40_90 <= clk40_90_i; clk40_180 <= clk40_180_i; clk40_ps <= clk40_ps_fb; clk40_ps_180 <= clk40_ps_180_fb; clk80 <= clk80_i; clk120 <= clk120_i; clk120_180 <= clk120_180_i; clk160 <= clk160_i; clk120dcs <= clk120dcs_pre_buf; -- -- Clock buffers sys_clk_inbuf : IBUFGDS port map ( I => CLK40_P, IB => CLK40_N, O => clk40_pre_dcm ); bufg_clk40 : BUFG port map ( I => clk40_pre_buf, O => clk40_i ); bufg_clk40_90 : BUFG port map ( I => clk40_90_pre_buf, O => clk40_90_i ); bufg_clk40inv : BUFG port map ( I => clk40_180_pre_buf, O => clk40_180_i ); bufg_clk80 : BUFG port map ( I => clk80_pre_buf, O => clk80_i ); bufg_clk120 : BUFG port map ( I => clk120_pre_buf, O => clk120_i ); bufg_clk120inv : BUFG port map ( I => clk120_180_pre_buf, O => clk120_180_i ); clk120_inbuf : IBUFGDS port map ( I => CLK120_P, IB => CLK120_N, O => clk120dcs_pre_buf ); bufg_clk160 : BUFG port map ( I => clk160_pre_buf, O => clk160_i ); -- -- DCM for generation of clk40 and clk120 dcm_clk120 : DCM_SP generic map ( DLL_FREQUENCY_MODE => "LOW", CLK_FEEDBACK => "1X", DUTY_CYCLE_CORRECTION => TRUE, CLKDV_DIVIDE => 16.0, CLKFX_MULTIPLY => 3, CLKFX_DIVIDE => 1, PHASE_SHIFT => 0, CLKOUT_PHASE_SHIFT => "NONE", DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- ??? DFS_FREQUENCY_MODE => "LOW", -- ??? DLL_FREQUENCY_MODE => "LOW", STARTUP_WAIT => TRUE, CLKIN_DIVIDE_BY_2 => FALSE ) port map ( CLKIN => clk40_pre_dcm, CLKFB => clk40_i, RST => '0', PSEN => open, PSINCDEC => open, PSCLK => open, CLK0 => clk40_pre_buf, CLK90 => clk40_90_pre_buf, CLK180 => clk40_180_pre_buf, CLK270 => open, CLK2X => open, --clk80_pre_buf, CLK2X180 => open, CLKDV => open, CLKFX => clk120_pre_buf, CLKFX180 => clk120_180_pre_buf, STATUS => open, LOCKED => dcm_120_locked, PSDONE => open ); -- -- DCM for generation of clk160 dcm_clk160 : DCM_SP generic map ( DLL_FREQUENCY_MODE => "LOW", CLK_FEEDBACK => "1X", DUTY_CYCLE_CORRECTION => TRUE, --CLKIN_PERIOD => 8.333, -- needed, since FX port in use CLKDV_DIVIDE => 16.0, CLKFX_MULTIPLY => 4, CLKFX_DIVIDE => 1, PHASE_SHIFT => 1, CLKOUT_PHASE_SHIFT => "FIXED", DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- ??? DFS_FREQUENCY_MODE => "LOW", -- ??? DLL_FREQUENCY_MODE => "LOW", STARTUP_WAIT => TRUE, CLKIN_DIVIDE_BY_2 => FALSE ) port map ( CLKIN => clk40_i, CLKFB => clk40_fb, RST => '0', PSEN => open, PSINCDEC => open, PSCLK => open, CLK0 => clk40_fb_pre_buf, CLK90 => open, CLK180 => open, CLK270 => open, CLK2X => clk80_pre_buf, CLK2X180 => open, CLKDV => open, CLKFX => clk160_pre_buf, CLKFX180 => open, STATUS => open, LOCKED => dcm_160_locked, PSDONE => open ); -- -- DCM for generation of shifted clk40 dcm_clk40_ps : DCM_SP generic map ( DLL_FREQUENCY_MODE => "LOW", CLK_FEEDBACK => "1X", DUTY_CYCLE_CORRECTION => TRUE, --CLKIN_PERIOD => 8.333, -- needed, since FX port in use CLKDV_DIVIDE => 16.0, CLKFX_MULTIPLY => 3, CLKFX_DIVIDE => 1, PHASE_SHIFT => 67, CLKOUT_PHASE_SHIFT => "VARIABLE", DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- ??? DFS_FREQUENCY_MODE => "LOW", -- ??? DLL_FREQUENCY_MODE => "LOW", STARTUP_WAIT => TRUE, CLKIN_DIVIDE_BY_2 => FALSE ) port map ( CLKIN => clk40_i, CLKFB => clk40_ps_fb, RST => '0', PSEN => ps_en, PSINCDEC => ps_adjust(1), PSCLK => clk40_i, CLK0 => clk40_ps_fb_pre_buf, CLK90 => open, CLK180 => clk40_ps_180_fb_pre_buf, CLK270 => open, CLK2X => open, CLK2X180 => open, CLKDV => open, CLKFX => open, CLKFX180 => open, STATUS => open, LOCKED => open, PSDONE => ps_done ); bufg_clk40fb : BUFG port map ( I => clk40_fb_pre_buf, O => clk40_fb ); bufg_clk40_ps_fb : BUFG port map ( I => clk40_ps_fb_pre_buf, O => clk40_ps_fb ); bufg_clk40_180_ps_fb : BUFG port map ( I => clk40_ps_180_fb_pre_buf, O => clk40_ps_180_fb ); -- -- Reset pulse generation rst_pulse_width <= conv_std_logic_vector( rst_width, rst_pulse_width'length ); process( clk40_i, rst_req, dcm_120_locked, dcm_160_locked ) begin if rst_req = '1' or dcm_120_locked = '0' or dcm_160_locked = '0' then rst_master <= '1'; rst_cnt <= ( others => '0' ); elsif rising_edge( clk40_i ) then if rst_cnt = rst_pulse_width then rst_master <= '0'; rst_cnt <= rst_cnt; else rst_cnt <= rst_cnt + '1'; rst_master <= '1'; end if; end if; end process; process (clk40_i) begin if rst_master = '1' then ps_adjust_r <= (others => '0'); elsif rising_edge(clk40_i) then ps_adjust_r <= ps_adjust; ps_en <= '0'; if ps_adjust_r(0) = '0' and ps_adjust(0) = '1' then ps_state(9) <= '0'; ps_en <= '1'; if ps_adjust(1) = '1' then ps_value <= ps_value + '1'; else ps_value <= ps_value - '1'; end if; end if; if ps_done = '1' then ps_state(9) <= '1'; end if; end if; end process; -- -- Output mapping ps_state(8 downto 0) <= ps_value; -- clk40, clk120 and clk80 are phase locked => no synchronizers rst40 <= rst_master; rst40_n <= not rst_master; rst80 <= rst_master; rst120 <= rst_master; rst120_n <= not rst_master; rst160 <= rst_master; end default;