//======================================================================
//
// clkmgr_mmcm.v
// -------------
// Xilinx MMCM primitive wrapper to avoid using Clocking Wizard IP core.
//
//
// Author: Pavel Shatov
// Copyright (c) 2019, NORDUnet A/S All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module clkmgr_mmcm
(
input fmc_clk_in,
input rst_in,
output io_clk_out,
output sys_clk_out,
output core_clk_out,
output locked_out
);
parameter integer CLK_CORE_MULT = 4;
function integer lookup_vco_freq;
input integer core_mult;
case (core_mult)
2: lookup_vco_freq = 990;
3: lookup_vco_freq = 945;
4: lookup_vco_freq = 1080;
5: lookup_vco_freq = 900;
6: lookup_vco_freq = 1080;
7: lookup_vco_freq = 945;
8: lookup_vco_freq = 1080;
endcase
endfunction
localparam real FMC_CLK_PERIOD_F = 22.222;
localparam real FB_PHASE_F = 45.0;
localparam real SYS_FREQ_F = 90.0;
localparam integer VCO_FREQ = lookup_vco_freq(CLK_CORE_MULT);
localparam integer IO_FREQ = 45;
localparam integer CORE_FREQ = CLK_CORE_MULT * IO_FREQ;
localparam real VCO_FREQ_F = 1.0 * VCO_FREQ;
localparam real FMC_FREQ_F = 1.0 * IO_FREQ;
localparam real FB_MULT_F = VCO_FREQ_F / FMC_FREQ_F;
localparam real CLK0_DIV_F = VCO_FREQ_F / SYS_FREQ_F;
localparam integer CLK1_DIV = VCO_FREQ / IO_FREQ;
localparam integer CLK2_DIV = VCO_FREQ / CORE_FREQ;
wire fmc_clk_ibufg;
IBUFG IBUFG_fmc_clk
(
.I(fmc_clk_in),
.O(fmc_clk_ibufg)
);
wire mmcm_clkout0;
wire mmcm_clkout1;
wire mmcm_clkout2;
wire mmcm_clkfbin;
wire mmcm_clkfbout;
MMCME2_BASE #
(
.CLKIN1_PERIOD (FMC_CLK_PERIOD_F),
.CLKFBOUT_MULT_F (FB_MULT_F),
.CLKFBOUT_PHASE (FB_PHASE_F),
.CLKOUT0_DIVIDE_F (CLK0_DIV_F),
.CLKOUT1_DIVIDE (CLK1_DIV),
.CLKOUT2_DIVIDE (CLK2_DIV)
)
MMCME2_BASE_io_clk
(
.CLKIN1 (fmc_clk_ibufg),
.RST (rst_in),
.PWRDWN (1'b0),
.LOCKED (locked_out),
.CLKFBOUT (mmcm_clkfbout),
.CLKFBOUTB (),
.CLKFBIN (mmcm_clkfbin),
.CLKOUT0 (mmcm_clkout0),
.CLKOUT0B (),
.CLKOUT1 (mmcm_clkout1),
.CLKOUT1B (),
.CLKOUT2 (mmcm_clkout2),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (),
.CLKOUT5 (),
.CLKOUT6 ()
);
BUFG BUFG_clkfb
(
.I(mmcm_clkfbout),
.O(mmcm_clkfbin)
);
BUFG BUFG_clk_io
(
.I(mmcm_clkout0),
.O(sys_clk_out)
);
BUFG BUFG_clk_sys
(
.I(mmcm_clkout1),
.O(io_clk_out)
);
BUFG BUFG_clk_core
(
.I(mmcm_clkout2),
.O(core_clk_out)
);
endmodule
//======================================================================
// EOF clkmgr_mmcm_io.v
//======================================================================