library ieee; use ieee.std_logic_1164.all; Library UNISIM; use UNISIM.vcomponents.all; entity clock_generator is generic ( CLK_INPUT_HZ : positive := 12000000; CLK_OUTPUT_HZ : positive := 50000000 ); port ( ext_clk : in std_logic; pll_rst_in : in std_logic; pll_clk_out : out std_logic; pll_locked_out : out std_logic); end entity clock_generator; architecture rtl of clock_generator is signal clkfb : std_ulogic; type pll_settings_t is record clkin_period : real range 10.000 to 800.0; clkfbout_mult : real range 2.0 to 64.0; clkout_divide : real range 1.0 to 128.0; divclk_divide : integer range 1 to 106; force_rst : std_ulogic; end record; function gen_pll_settings ( constant input_hz : positive; constant output_hz : positive) return pll_settings_t is constant bad_settings : pll_settings_t := (clkin_period => 0.0, clkfbout_mult => 2.0, clkout_divide => 1.0, divclk_divide => 1, force_rst => '1'); begin case input_hz is when 100000000 => case output_hz is when 100000000 => return (clkin_period => 10.0, clkfbout_mult => 16.0, clkout_divide => 16.0, divclk_divide => 1, force_rst => '0'); when 50000000 => return (clkin_period => 10.0, clkfbout_mult => 16.0, clkout_divide => 32.0, divclk_divide => 1, force_rst => '0'); when others => report "Unsupported output frequency" severity failure; return bad_settings; end case; when 12000000 => case output_hz is when 100000000 => return (clkin_period => 83.33, clkfbout_mult => 50.0, clkout_divide => 6.0, divclk_divide => 1, force_rst => '0'); when 50000000 => return (clkin_period => 83.33, clkfbout_mult => 50.0, clkout_divide => 12.0, divclk_divide => 1, force_rst => '0'); when others => report "Unsupported output frequency" severity failure; return bad_settings; end case; when others => report "Unsupported input frequency" severity failure; return bad_settings; end case; end function gen_pll_settings; constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz, clk_output_hz); begin pll : MMCME2_BASE generic map ( BANDWIDTH => "OPTIMIZED", CLKFBOUT_MULT_F => pll_settings.clkfbout_mult, CLKIN1_PERIOD => pll_settings.clkin_period, CLKOUT0_DIVIDE_F => pll_settings.clkout_divide, DIVCLK_DIVIDE => pll_settings.divclk_divide, STARTUP_WAIT => FALSE) port map ( CLKFBOUT => clkfb, CLKFBOUTB => open, CLKOUT0 => pll_clk_out, CLKOUT0B => open, CLKOUT1 => open, CLKOUT1B => open, CLKOUT2 => open, CLKOUT2B => open, CLKOUT3 => open, CLKOUT3B => open, CLKOUT4 => open, CLKOUT5 => open, CLKOUT6 => open, LOCKED => pll_locked_out, CLKFBIN => clkfb, CLKIN1 => ext_clk, PWRDWN => '0', RST => pll_rst_in or pll_settings.force_rst ); end architecture rtl;