Improve PLL/MMCM clocks configuration

We can now pass both the input clock and target clock frequency
via generics. Add support for both 50Mhz and 100Mhz target freqs
for both cases.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/77/head
Benjamin Herrenschmidt 5 years ago
parent 5f28109957
commit 9961d70dfb

@ -6,7 +6,9 @@ use UNISIM.vcomponents.all;

entity clock_generator is
generic (
clk_period_hz : positive := 12000000);
CLK_INPUT_HZ : positive := 12000000;
CLK_OUTPUT_HZ : positive := 50000000
);
port (
ext_clk : in std_logic;
pll_rst_in : in std_logic;
@ -22,28 +24,66 @@ architecture rtl of clock_generator is
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 freq_hz : positive)
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
if freq_hz = 100000000 then
return (clkin_period => 10.0,
clkfbout_mult => 16.0,
clkout_divide => 32.0,
divclk_divide => 1);
elsif freq_hz = 12000000 then
return (clkin_period => 83.33,
clkfbout_mult => 50.0,
clkout_divide => 12.0,
divclk_divide => 1);
else
report "Unsupported input frequency" severity failure;
end if;
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_period_hz);
constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz);
begin
pll : MMCME2_BASE
generic map (
@ -71,6 +111,6 @@ begin
CLKFBIN => clkfb,
CLKIN1 => ext_clk,
PWRDWN => '0',
RST => pll_rst_in
RST => pll_rst_in or pll_settings.force_rst
);
end architecture rtl;

@ -5,67 +5,89 @@ Library UNISIM;
use UNISIM.vcomponents.all;

entity clock_generator is
generic (
clk_period_hz : positive := 100000000);
port (
ext_clk : in std_logic;
pll_rst_in : in std_logic;
pll_clk_out : out std_logic;
pll_locked_out : out std_logic);
generic (
CLK_INPUT_HZ : positive := 100000000;
CLK_OUTPUT_HZ : positive := 100000000
);
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;

signal clkfb : std_ulogic;
type pll_settings_t is record
clkin_period : real range 0.000 to 52.631;
clkfbout_mult : integer range 2 to 64;
clkout_divide : integer range 1 to 128;
divclk_divide : integer range 1 to 56;
force_rst : std_ulogic;
end record;

type pll_settings_t is record
clkin_period : real range 0.000 to 52.631;
clkfbout_mult : integer range 2 to 64;
clkout_divide : integer range 1 to 128;
divclk_divide : integer range 1 to 56;
end record;
function gen_pll_settings (
constant input_hz : positive;
constant output_hz : positive)
return pll_settings_t is

function gen_pll_settings (
constant freq_hz : positive)
return pll_settings_t is
begin
if freq_hz = 100000000 then
return (clkin_period => 10.0,
clkfbout_mult => 16,
clkout_divide => 32,
divclk_divide => 1);
else
report "Unsupported input frequency" severity failure;
-- return (clkin_period => 0.0,
-- clkfbout_mult => 0,
-- clkout_divide => 0,
-- divclk_divide => 0);
end if;
end function gen_pll_settings;
constant bad_settings : pll_settings_t :=
(clkin_period => 0.0,
clkfbout_mult => 2,
clkout_divide => 1,
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,
clkout_divide => 16,
divclk_divide => 1,
force_rst => '0');
when 50000000 =>
return (clkin_period => 10.0,
clkfbout_mult => 16,
clkout_divide => 32,
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_period_hz);
constant pll_settings : pll_settings_t := gen_pll_settings(clk_input_hz,
clk_output_hz);
begin

pll : PLLE2_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => pll_settings.clkfbout_mult,
CLKIN1_PERIOD => pll_settings.clkin_period,
CLKOUT0_DIVIDE => pll_settings.clkout_divide,
DIVCLK_DIVIDE => pll_settings.divclk_divide,
STARTUP_WAIT => "FALSE")
port map (
CLKOUT0 => pll_clk_out,
CLKOUT1 => open,
CLKOUT2 => open,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
CLKFBOUT => clkfb,
LOCKED => pll_locked_out,
CLKIN1 => ext_clk,
PWRDWN => '0',
RST => pll_rst_in,
CLKFBIN => clkfb);
pll : PLLE2_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => pll_settings.clkfbout_mult,
CLKIN1_PERIOD => pll_settings.clkin_period,
CLKOUT0_DIVIDE => pll_settings.clkout_divide,
DIVCLK_DIVIDE => pll_settings.divclk_divide,
STARTUP_WAIT => "FALSE")
port map (
CLKOUT0 => pll_clk_out,
CLKOUT1 => open,
CLKOUT2 => open,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
CLKFBOUT => clkfb,
LOCKED => pll_locked_out,
CLKIN1 => ext_clk,
PWRDWN => '0',
RST => pll_rst_in or pll_settings.force_rst,
CLKFBIN => clkfb);

end architecture rtl;

@ -5,7 +5,9 @@ entity toplevel is
generic (
MEMORY_SIZE : positive := 524288;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true
RESET_LOW : boolean := true;
CLK_INPUT : positive := 100000000;
CLK_FREQUENCY : positive := 100000000
);
port(
ext_clk : in std_ulogic;
@ -43,6 +45,10 @@ begin
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => CLK_INPUT,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,

@ -81,7 +81,11 @@ targets:
nexys_a7:
default_tool: vivado
filesets: [core, nexys_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file]
parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools:
vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel
@ -89,7 +93,11 @@ targets:
nexys_video:
default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file]
parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools:
vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel
@ -97,7 +105,11 @@ targets:
arty_a7-35:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file]
parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel
@ -105,7 +117,11 @@ targets:
arty_a7-100:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file]
parameters :
- memory_size
- ram_init_file
- clk_input
- clk_frequency
tools:
vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel
@ -113,7 +129,11 @@ targets:
cmod_a7-35:
default_tool: vivado
filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx]
parameters : [memory_size, ram_init_file, reset_low=false]
parameters :
- memory_size
- ram_init_file
- reset_low=false
- clk_input=12000000
tools:
vivado: {part : xc7a35tcpg236-1}
toplevel : toplevel
@ -139,3 +159,15 @@ parameters:
datatype : bool
description : External reset button polarity
paramtype : generic

clk_input:
datatype : int
description : Clock input frequency in HZ (for top-generic based boards)
paramtype : generic
default : 100000000

clk_frequency:
datatype : int
description : Generated system clock frequency in HZ (for top-generic based boards)
paramtype : generic
default : 50000000

Loading…
Cancel
Save