| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849 |
- //-------------------------------------------------------------------------------------------
- // ____ ____
- // / /\/ /
- // /___/ \ /
- // \ \ \/ � Copyright 2019 Xilinx, Inc. All rights reserved.
- // \ \ This file contains confidential and proprietary information of Xilinx, Inc.
- // / / and is protected under U.S. and international copyright and other
- // /___/ /\ intellectual property laws.
- // \ \ / \
- // \___\/\___\
- //
- //-------------------------------------------------------------------------------------------
- // Device: 7_Series
- // Author: Tatsukawa, Kruger, Ribbing, Defossez
- // Entity Name: mmcme2_drp
- // Purpose: This calls the DRP register calculation functions and
- // provides a state machine to perform MMCM reconfiguration
- // based on the calculated values stored in a initialized
- // ROM.
- // 7-Series MMCM is called: MMCME2
- // Ultrascale MMCM is called: MMCME3
- // UltrascalePlus MMCM is called: MMCME4
- // MMCME3 attributes
- // CLKINx_PERIOD: 0.968 to 100.000 (x = 1 or 2)
- // REF_JITTERx: 0.001 to 0.999 (x = 1 or 2)
- // BANDWIDTH: LOW, HIGH, OPTIMIZED and POSTCRC
- // COMPENSATION: AUTO, ZHOLD, EXTERNAL, INTERNAL and BUF_IN
- // DIVCLK_DIVIDE: 1 to 106
- // CLKFBOUT_MULT_F: 2 to 64
- // CLKFBOUT_PHASE: -360 to 360
- // CLKOUTn_DIVIDE: 1 to 128 (n = 0 to 6)
- // CLKOUTn_PHASE: -360 to 360 (n = 0 to 6)
- // CLKOUTn_DUTY_CYCLE: 0.01 to 0.99 (n = 0 to 6)
- //
- // Tools: Vivado_2019.1 or newer
- // Limitations: None
- //
- // Vendor: Xilinx Inc.
- // Version: 1.40
- // Filename: mmcme3_drp.v
- // Date Created: 22-Oct-2014
- // Date Last Modified: 25-Jun-2019
- //-------------------------------------------------------------------------------------------
- // Disclaimer:
- // This disclaimer is not a license and does not grant any rights to the materials
- // distributed herewith. Except as otherwise provided in a valid license issued to you
- // by Xilinx, and to the maximum extent permitted by applicable law: (1) THESE MATERIALS
- // ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL
- // WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED
- // TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR
- // PURPOSE; and (2) Xilinx shall not be liable (whether in contract or tort, including
- // negligence, or under any other theory of liability) for any loss or damage of any
- // kind or nature related to, arising under or in connection with these materials,
- // including for any direct, or any indirect, special, incidental, or consequential
- // loss or damage (including loss of data, profits, goodwill, or any type of loss or
- // damage suffered as a result of any action brought by a third party) even if such
- // damage or loss was reasonably foreseeable or Xilinx had been advised of the
- // possibility of the same.
- //
- // CRITICAL APPLICATIONS
- // Xilinx products are not designed or intended to be fail-safe, or for use in any
- // application requiring fail-safe performance, such as life-support or safety devices
- // or systems, Class III medical devices, nuclear facilities, applications related to
- // the deployment of airbags, or any other applications that could lead to death,
- // personal injury, or severe property or environmental damage (individually and
- // collectively, "Critical Applications"). Customer assumes the sole risk and
- // liability of any use of Xilinx products in Critical Applications, subject only to
- // applicable laws and regulations governing limitations on product liability.
- //
- // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
- //
- // Contact: e-mail hotline@xilinx.com phone + 1 800 255 7778
- //-------------------------------------------------------------------------------------------
- // Revision History:
- // Rev: 13-Jan-2011 - Tatsukawa
- // Updated ROM[18,41] LOCKED bitmask to 16'HFC00
- // Rev: 30-May-2013 - Tatsukawa
- // Adding Fractional support for CLKFBOUT_MULT_F, CLKOUT0_DIVIDE_F
- // Rev: 30-Apr-2014 - Tatsukawa
- // For fractional multiply changed order to enable fractional
- // before the multiply is applied to prevent false VCO DRCs
- // (e.g. DADDR 7'h15 must be set before updating 7'h14)
- // Rev: 24-Oct-2014 - Ribbing
- // Parameters have been added to clarify Reg1/Reg2/Shared registers
- // Rev: 08-Jun-2015 - Kruger
- // WAIT_LOCK update
- // Rev: 02-May-2016 - Kruger
- // Reordering FRAC_EN bits DADDR(7'h09, 7'h15)
- // Registers before frac settings (7'h08, 7'h14)
- // Rev: 19-Sep-2018 - Defossez
- // Updated comments of BANDWIDTH.
- // Corrected some typos.
- // Rev: 25-Jun-2019 - Defossez
- // Adding registering possibility for LOCKE signal.
- //-------------------------------------------------------------------------------------------
- //
- `timescale 1ps/1ps
- //
- module mmcme2_drp
- #(
- // Register the LOCKED signal with teh MMCME3_ADV input clock.
- // The LOCKED_IN (LOCKED from the MMCME3_ADV) is fed into a register and then
- // passed the LOCKED_OUT when REGISTER_LOCKED is set to "Reg" or when set to
- // "NoReg" LOCKED_IN is just passed on to LOCKED_OUT without being registered.
- parameter REGISTER_LOCKED = "Reg",
- // Use the registered LOCKED signal from the MMCME3 also for the DRP state machine.
- parameter USE_REG_LOCKED = "No",
- // Possible/allowed combinations of above two parameters:
- // | REGISTER_LOCKED | USE_REG_LOCKED | |
- // |-----------------|----------------|--------------------------------------------|
- // | "NoReg" | "No" | LOCKED is just passed through mmcme3_drp |
- // | | | and is used as is with the state machine |
- // | "NoReg" | "Yes" | NOT ALLOWED |
- // | "Reg" | "No" | LOCKED is registered but the unregistered |
- // | | | version is used for the state machine. |
- // | "Reg" | "Yes" | LOCKED is registered and the registered |
- // | | | version is also used by the state machine. |
- //
- //***********************************************************************
- // State 1 Parameters - These are for the first reconfiguration state.
- //***********************************************************************
- //
- // These parameters have an effect on the feedback path. A change on
- // these parameters will effect all of the clock outputs.
- //
- // The parameters are composed of:
- // _MULT: This can be from 2 to 64. It has an effect on the VCO
- // frequency which consequently, effects all of the clock
- // outputs.
- // _PHASE: This is the phase multiplied by 1000. For example if
- // a phase of 24.567 deg was desired the input value would be
- // 24567. The range for the phase is from -360000 to 360000.
- // _FRAC: This can be from 0 to 875. This represents the fractional
- // divide multiplied by 1000.
- // M = _MULT + _FRAC / 1000
- // e.g. M=8.125
- // _MULT = 8
- // _FRAC = 125
- // _FRAC_EN: This indicates fractional divide has been enabled. If 1
- // then the fractional divide algorithm will be used to calculate
- // register settings. If 0 then default calculation to be used.
- parameter S1_CLKFBOUT_MULT = 5,
- parameter S1_CLKFBOUT_PHASE = 0,
- parameter S1_CLKFBOUT_FRAC = 125,
- parameter S1_CLKFBOUT_FRAC_EN = 1,
- //
- // The bandwidth parameter effects the phase error and the jitter filter
- // capability of the MMCM. For more information on this parameter see the
- // Device user guide.
- // Possible values are: "LOW", "LOW_SS", "HIGH" and "OPTIMIZED"
- parameter S1_BANDWIDTH = "LOW",
- //
- // The divclk parameter allows the input clock to be divided before it
- // reaches the phase and frequency comparator. This can be set between
- // 1 and 128.
- parameter S1_DIVCLK_DIVIDE = 1,
- // The following parameters describe the configuration that each clock
- // output should have once the reconfiguration for state one has
- // completed.
- //
- // The parameters are composed of:
- // _DIVIDE: This can be from 1 to 128
- // _PHASE: This is the phase multiplied by 1000. For example if
- // a phase of 24.567 deg was desired the input value would be
- // 24567. The range for the phase is from -360000 to 360000.
- // _DUTY: This is the duty cycle multiplied by 100,000. For example if
- // a duty cycle of .24567 was desired the input would be
- // 24567.
- //
- parameter S1_CLKOUT0_DIVIDE = 1,
- parameter S1_CLKOUT0_PHASE = 0,
- parameter S1_CLKOUT0_DUTY = 50000,
- parameter S1_CLKOUT0_FRAC = 125,
- parameter S1_CLKOUT0_FRAC_EN = 1,
- //
- parameter S1_CLKOUT1_DIVIDE = 1,
- parameter S1_CLKOUT1_PHASE = 0,
- parameter S1_CLKOUT1_DUTY = 50000,
- //
- parameter S1_CLKOUT2_DIVIDE = 1,
- parameter S1_CLKOUT2_PHASE = 0,
- parameter S1_CLKOUT2_DUTY = 50000,
- //
- parameter S1_CLKOUT3_DIVIDE = 1,
- parameter S1_CLKOUT3_PHASE = 0,
- parameter S1_CLKOUT3_DUTY = 50000,
- //
- parameter S1_CLKOUT4_DIVIDE = 1,
- parameter S1_CLKOUT4_PHASE = 0,
- parameter S1_CLKOUT4_DUTY = 50000,
- //
- parameter S1_CLKOUT5_DIVIDE = 1,
- parameter S1_CLKOUT5_PHASE = 0,
- parameter S1_CLKOUT5_DUTY = 50000,
- //
- parameter S1_CLKOUT6_DIVIDE = 1,
- parameter S1_CLKOUT6_PHASE = 0,
- parameter S1_CLKOUT6_DUTY = 50000,
- //
- //***********************************************************************
- // State 2 Parameters - These are for the second reconfiguration state.
- //***********************************************************************
- //
- // These parameters have an effect on the feedback path. A change on
- // these parameters will effect all of the clock outputs.
- //
- // The parameters are composed of:
- // _MULT: This can be from 2 to 64. It has an effect on the VCO
- // frequency which consequently, effects all of the clock
- // outputs.
- // _PHASE: This is the phase multiplied by 1000. For example if
- // a phase of 24.567 deg was desired the input value would be
- // 24567. The range for the phase is from -360000 to 360000.
- // _FRAC: This can be from 0 to 875. This represents the fractional
- // divide multiplied by 1000.
- // M = _MULT + _FRAC / 1000
- // e.g. M=8.125
- // _MULT = 8
- // _FRAC = 125
- // _FRAC_EN: This indicates fractional divide has been enabled. If 1
- // then the fractional divide algorithm will be used to calculate
- // register settings. If 0 then default calculation to be used.
- parameter S2_CLKFBOUT_MULT = 1,
- parameter S2_CLKFBOUT_PHASE = 0,
- parameter S2_CLKFBOUT_FRAC = 125,
- parameter S2_CLKFBOUT_FRAC_EN = 1,
- //
- // The bandwidth parameter effects the phase error and the jitter filter
- // capability of the MMCM. For more information on this parameter see the
- // Device user guide.
- // Possible values are: "LOW", "LOW_SS", "HIGH" and "OPTIMIZED"
- parameter S2_BANDWIDTH = "LOW",
- //
- // The divclk parameter allows the input clock to be divided before it
- // reaches the phase and frequency comparator. This can be set between
- // 1 and 128.
- parameter S2_DIVCLK_DIVIDE = 1,
- //
- // The following parameters describe the configuration that each clock
- // output should have once the reconfiguration for state one has
- // completed.
- //
- // The parameters are composed of:
- // _DIVIDE: This can be from 1 to 128
- // _PHASE: This is the phase multiplied by 1000. For example if
- // a phase of 24.567 deg was desired the input value would be
- // 24567. The range for the phase is from -360000 to 360000
- // _DUTY: This is the duty cycle multiplied by 100,000. For example if
- // a duty cycle of .24567 was desired the input would be
- // 24567.
- //
- parameter S2_CLKOUT0_DIVIDE = 1,
- parameter S2_CLKOUT0_PHASE = 0,
- parameter S2_CLKOUT0_DUTY = 50000,
- parameter S2_CLKOUT0_FRAC = 125,
- parameter S2_CLKOUT0_FRAC_EN = 1,
- //
- parameter S2_CLKOUT1_DIVIDE = 2,
- parameter S2_CLKOUT1_PHASE = 0,
- parameter S2_CLKOUT1_DUTY = 50000,
- //
- parameter S2_CLKOUT2_DIVIDE = 3,
- parameter S2_CLKOUT2_PHASE = 0,
- parameter S2_CLKOUT2_DUTY = 50000,
- //
- parameter S2_CLKOUT3_DIVIDE = 4,
- parameter S2_CLKOUT3_PHASE = 0,
- parameter S2_CLKOUT3_DUTY = 50000,
- //
- parameter S2_CLKOUT4_DIVIDE = 5,
- parameter S2_CLKOUT4_PHASE = 0,
- parameter S2_CLKOUT4_DUTY = 50000,
- //
- parameter S2_CLKOUT5_DIVIDE = 5,
- parameter S2_CLKOUT5_PHASE = 0,
- parameter S2_CLKOUT5_DUTY = 50000,
- //
- parameter S2_CLKOUT6_DIVIDE = 5,
- parameter S2_CLKOUT6_PHASE = -90,
- parameter S2_CLKOUT6_DUTY = 50000
- ) (
- // These signals are controlled by user logic interface and are covered
- // in more detail within the XAPP.
- input SADDR,
- input SEN,
- input SCLK,
- input RST,
- output reg SRDY,
- //
- // These signals are to be connected to the MMCM_ADV by port name.
- // Their use matches the MMCM port description in the Device User Guide.
- input [15:0] DO,
- input DRDY,
- input LOCK_REG_CLK_IN,
- input LOCKED_IN,
- output reg DWE,
- output reg DEN,
- output reg [6:0] DADDR,
- output reg [15:0] DI,
- output DCLK,
- output reg RST_MMCM,
- output LOCKED_OUT
- );
- //----------------------------------------------------------------------------------------
- //
- wire IntLocked;
- wire IntRstMmcm;
- //
- // 100 ps delay for behavioral simulations
- localparam TCQ = 100;
- // Make sure the memory is implemented as distributed
- (* rom_style = "distributed" *)
- //
- // ROM of: 39 bit word 64 words deep
- reg [38:0] rom [63:0];
- reg [5:0] rom_addr;
- reg [38:0] rom_do;
- reg next_srdy;
- reg [5:0] next_rom_addr;
- reg [6:0] next_daddr;
- reg next_dwe;
- reg next_den;
- reg next_rst_mmcm;
- reg [15:0] next_di;
- //
- // Insert a register in LOCKED or not depending on the value given to the parameters
- // REGISTER_LOCKED. When REGISTER_LOCKED is set to "Reg" insert a register, when set
- // to "NoReg" don't insert a register but just pass the LOCKED signal from input to
- // output.
- // Use or not, under USE_REG_LOCKED parameter control, the registered version of the
- // LOCKED signal for the DRP state machine.
- // Possible/allowed combinations of the two LOCKED related parameters:
- //
- // | REGISTER_LOCKED | USE_REG_LOCKED | |
- // |-----------------|----------------|--------------------------------------------|
- // | "NoReg" | "No" | LOCKED is just passed through mmcme3_drp |
- // | | | and is used as is with the state machine |
- // | "NoReg" | "Yes" | NOT ALLOWED |
- // | "Reg" | "No" | LOCKED is registered but the unregistered |
- // | | | version is used for the state machine. |
- // | "Reg" | "Yes" | LOCKED is registered and the registered |
- // | | | version is also used by the state machine. |
- //
- generate
- if (REGISTER_LOCKED == "NoReg" && USE_REG_LOCKED == "No") begin
- assign LOCKED_OUT = LOCKED_IN;
- assign IntLocked = LOCKED_IN;
- end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "No") begin
- FDRE #(
- .INIT (0),
- .IS_C_INVERTED (0),
- .IS_D_INVERTED (0),
- .IS_R_INVERTED (0)
- ) mmcme3_drp_I_Fdrp (
- .D (LOCKED_IN),
- .CE (1'b1),
- .R (IntRstMmcm),
- .C (LOCK_REG_CLK_IN),
- .Q (LOCKED_OUT)
- );
- //
- assign IntLocked = LOCKED_IN;
- end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "Yes") begin
- FDRE #(
- .INIT (0),
- .IS_C_INVERTED (0),
- .IS_D_INVERTED (0),
- .IS_R_INVERTED (0)
- ) mmcme3_drp_I_Fdrp (
- .D (LOCKED_IN),
- .CE (1'b1),
- .R (IntRstMmcm),
- .C (LOCK_REG_CLK_IN),
- .Q (LOCKED_OUT)
- );
- //
- assign IntLocked = LOCKED_OUT;
- end
- endgenerate
- // Integer used to initialize remainder of unused ROM
- integer ii;
- // Pass SCLK to DCLK for the MMCM
- assign DCLK = SCLK;
- assign IntRstMmcm = RST_MMCM;
- // Include the MMCM reconfiguration functions. This contains the constant
- // functions that are used in the calculations below. This file is
- // required.
- `include "mmcme2_drp_func.h"
- //**************************************************************************
- // State 1 Calculations
- //**************************************************************************
- // Please see header for information.
- localparam [37:0] S1_CLKFBOUT =
- mmcm_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000);
- localparam [37:0] S1_CLKFBOUT_FRAC_CALC =
- mmcm_frac_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000, S1_CLKFBOUT_FRAC);
- localparam [9:0] S1_DIGITAL_FILT =
- mmcm_filter_lookup(S1_CLKFBOUT_MULT, S1_BANDWIDTH);
- localparam [39:0] S1_LOCK =
- mmcm_lock_lookup(S1_CLKFBOUT_MULT);
- localparam [37:0] S1_DIVCLK =
- mmcm_count_calc(S1_DIVCLK_DIVIDE, 0, 50000);
- localparam [37:0] S1_CLKOUT0 =
- mmcm_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, S1_CLKOUT0_DUTY);
- localparam [15:0] S1_CLKOUT0_REG1 = S1_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT0_REG2 = S1_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT0_FRAC_CALC =
- mmcm_frac_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, 50000, S1_CLKOUT0_FRAC);
- localparam [15:0] S1_CLKOUT0_FRAC_REG1 = S1_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT0_FRAC_REG2 = S1_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
- localparam [5:0] S1_CLKOUT0_FRAC_REGSHARED = S1_CLKOUT0_FRAC_CALC[37:32]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT1 =
- mmcm_count_calc(S1_CLKOUT1_DIVIDE, S1_CLKOUT1_PHASE, S1_CLKOUT1_DUTY);
- localparam [15:0] S1_CLKOUT1_REG1 = S1_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT1_REG2 = S1_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT2 =
- mmcm_count_calc(S1_CLKOUT2_DIVIDE, S1_CLKOUT2_PHASE, S1_CLKOUT2_DUTY);
- localparam [15:0] S1_CLKOUT2_REG1 = S1_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT2_REG2 = S1_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT3 =
- mmcm_count_calc(S1_CLKOUT3_DIVIDE, S1_CLKOUT3_PHASE, S1_CLKOUT3_DUTY);
- localparam [15:0] S1_CLKOUT3_REG1 = S1_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT3_REG2 = S1_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT4 =
- mmcm_count_calc(S1_CLKOUT4_DIVIDE, S1_CLKOUT4_PHASE, S1_CLKOUT4_DUTY);
- localparam [15:0] S1_CLKOUT4_REG1 = S1_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT4_REG2 = S1_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT5 =
- mmcm_count_calc(S1_CLKOUT5_DIVIDE, S1_CLKOUT5_PHASE, S1_CLKOUT5_DUTY);
- localparam [15:0] S1_CLKOUT5_REG1 = S1_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT5_REG2 = S1_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S1_CLKOUT6 =
- mmcm_count_calc(S1_CLKOUT6_DIVIDE, S1_CLKOUT6_PHASE, S1_CLKOUT6_DUTY);
- localparam [15:0] S1_CLKOUT6_REG1 = S1_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S1_CLKOUT6_REG2 = S1_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
- //**************************************************************************
- // State 2 Calculations
- //**************************************************************************
- localparam [37:0] S2_CLKFBOUT =
- mmcm_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000);
- localparam [37:0] S2_CLKFBOUT_FRAC_CALC =
- mmcm_frac_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000, S2_CLKFBOUT_FRAC);
- localparam [9:0] S2_DIGITAL_FILT =
- mmcm_filter_lookup(S2_CLKFBOUT_MULT, S2_BANDWIDTH);
- localparam [39:0] S2_LOCK =
- mmcm_lock_lookup(S2_CLKFBOUT_MULT);
- localparam [37:0] S2_DIVCLK =
- mmcm_count_calc(S2_DIVCLK_DIVIDE, 0, 50000);
- localparam [37:0] S2_CLKOUT0 =
- mmcm_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, S2_CLKOUT0_DUTY);
- localparam [15:0] S2_CLKOUT0_REG1 = S2_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT0_REG2 = S2_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT0_FRAC_CALC =
- mmcm_frac_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, 50000, S2_CLKOUT0_FRAC);
- localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG1 = S2_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG2 = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT0_FRAC_CALC_REGSHARED = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT1 =
- mmcm_count_calc(S2_CLKOUT1_DIVIDE, S2_CLKOUT1_PHASE, S2_CLKOUT1_DUTY);
- localparam [15:0] S2_CLKOUT1_REG1 = S2_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT1_REG2 = S2_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT2 =
- mmcm_count_calc(S2_CLKOUT2_DIVIDE, S2_CLKOUT2_PHASE, S2_CLKOUT2_DUTY);
- localparam [15:0] S2_CLKOUT2_REG1 = S2_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT2_REG2 = S2_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT3 =
- mmcm_count_calc(S2_CLKOUT3_DIVIDE, S2_CLKOUT3_PHASE, S2_CLKOUT3_DUTY);
- localparam [15:0] S2_CLKOUT3_REG1 = S2_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT3_REG2 = S2_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT4 =
- mmcm_count_calc(S2_CLKOUT4_DIVIDE, S2_CLKOUT4_PHASE, S2_CLKOUT4_DUTY);
- localparam [15:0] S2_CLKOUT4_REG1 = S2_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT4_REG2 = S2_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT5 =
- mmcm_count_calc(S2_CLKOUT5_DIVIDE, S2_CLKOUT5_PHASE, S2_CLKOUT5_DUTY);
- localparam [15:0] S2_CLKOUT5_REG1 = S2_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT5_REG2 = S2_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
- localparam [37:0] S2_CLKOUT6 =
- mmcm_count_calc(S2_CLKOUT6_DIVIDE, S2_CLKOUT6_PHASE, S2_CLKOUT6_DUTY);
- localparam [15:0] S2_CLKOUT6_REG1 = S2_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
- localparam [15:0] S2_CLKOUT6_REG2 = S2_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
- initial begin
- // rom entries contain (in order) the address, a bitmask, and a bitset
- //***********************************************************************
- // State 1 Initialization
- //***********************************************************************
- // Store the power bits
- rom[0] = {7'h28, 16'h0000, 16'hFFFF};
- // Store CLKOUT0 divide and phase
- rom[1] = (S1_CLKOUT0_FRAC_EN == 0) ?
- {7'h09, 16'h8000, S1_CLKOUT0[31:16]}:
- {7'h09, 16'h8000, S1_CLKOUT0_FRAC_CALC[31:16]};
- rom[2] = (S1_CLKOUT0_FRAC_EN == 0) ?
- {7'h08, 16'h1000, S1_CLKOUT0[15:0]}:
- {7'h08, 16'h1000, S1_CLKOUT0_FRAC_CALC[15:0]};
- // Store CLKOUT1 divide and phase
- rom[3] = {7'h0A, 16'h1000, S1_CLKOUT1[15:0]};
- rom[4] = {7'h0B, 16'hFC00, S1_CLKOUT1[31:16]};
- // Store CLKOUT2 divide and phase
- rom[5] = {7'h0C, 16'h1000, S1_CLKOUT2[15:0]};
- rom[6] = {7'h0D, 16'hFC00, S1_CLKOUT2[31:16]};
- // Store CLKOUT3 divide and phase
- rom[7] = {7'h0E, 16'h1000, S1_CLKOUT3[15:0]};
- rom[8] = {7'h0F, 16'hFC00, S1_CLKOUT3[31:16]};
- // Store CLKOUT4 divide and phase
- rom[9] = {7'h10, 16'h1000, S1_CLKOUT4[15:0]};
- rom[10] = {7'h11, 16'hFC00, S1_CLKOUT4[31:16]};
- // Store CLKOUT5 divide and phase
- rom[11] = {7'h06, 16'h1000, S1_CLKOUT5[15:0]};
- rom[12] = (S1_CLKOUT0_FRAC_EN == 0) ?
- {7'h07, 16'hC000, S1_CLKOUT5[31:16]}:
- {7'h07, 16'hC000, S1_CLKOUT5[31:30], S1_CLKOUT0_FRAC_CALC[35:32],S1_CLKOUT5[25:16]};
- // Store CLKOUT6 divide and phase
- rom[13] = {7'h12, 16'h1000, S1_CLKOUT6[15:0]};
- rom[14] = (S1_CLKFBOUT_FRAC_EN == 0) ?
- {7'h13, 16'hC000, S1_CLKOUT6[31:16]}:
- {7'h13, 16'hC000, S1_CLKOUT6[31:30], S1_CLKFBOUT_FRAC_CALC[35:32],S1_CLKOUT6[25:16]};
- // Store the input divider
- rom[15] = {7'h16, 16'hC000, {2'h0, S1_DIVCLK[23:22], S1_DIVCLK[11:0]} };
- // Store the feedback divide and phase
- rom[16] = (S1_CLKFBOUT_FRAC_EN == 0) ?
- {7'h14, 16'h1000, S1_CLKFBOUT[15:0]}:
- {7'h14, 16'h1000, S1_CLKFBOUT_FRAC_CALC[15:0]};
- rom[17] = (S1_CLKFBOUT_FRAC_EN == 0) ?
- {7'h15, 16'h8000, S1_CLKFBOUT[31:16]}:
- {7'h15, 16'h8000, S1_CLKFBOUT_FRAC_CALC[31:16]};
- // Store the lock settings
- rom[18] = {7'h18, 16'hFC00, {6'h00, S1_LOCK[29:20]} };
- rom[19] = {7'h19, 16'h8000, {1'b0 , S1_LOCK[34:30], S1_LOCK[9:0]} };
- rom[20] = {7'h1A, 16'h8000, {1'b0 , S1_LOCK[39:35], S1_LOCK[19:10]} };
- // Store the filter settings
- rom[21] = {7'h4E, 16'h66FF,
- S1_DIGITAL_FILT[9], 2'h0, S1_DIGITAL_FILT[8:7], 2'h0,
- S1_DIGITAL_FILT[6], 8'h00 };
- rom[22] = {7'h4F, 16'h666F,
- S1_DIGITAL_FILT[5], 2'h0, S1_DIGITAL_FILT[4:3], 2'h0,
- S1_DIGITAL_FILT[2:1], 2'h0, S1_DIGITAL_FILT[0], 4'h0 };
- //***********************************************************************
- // State 2 Initialization
- //***********************************************************************
- // Store the power bits
- rom[23] = {7'h28, 16'h0000, 16'hFFFF};
- // Store CLKOUT0 divide and phase
- rom[24] = (S2_CLKOUT0_FRAC_EN == 0) ?
- {7'h09, 16'h8000, S2_CLKOUT0[31:16]}:
- {7'h09, 16'h8000, S2_CLKOUT0_FRAC_CALC[31:16]};
- rom[25] = (S2_CLKOUT0_FRAC_EN == 0) ?
- {7'h08, 16'h1000, S2_CLKOUT0[15:0]}:
- {7'h08, 16'h1000, S2_CLKOUT0_FRAC_CALC[15:0]};
- // Store CLKOUT1 divide and phase
- rom[26] = {7'h0A, 16'h1000, S2_CLKOUT1[15:0]};
- rom[27] = {7'h0B, 16'hFC00, S2_CLKOUT1[31:16]};
- // Store CLKOUT2 divide and phase
- rom[28] = {7'h0C, 16'h1000, S2_CLKOUT2[15:0]};
- rom[29] = {7'h0D, 16'hFC00, S2_CLKOUT2[31:16]};
- // Store CLKOUT3 divide and phase
- rom[30] = {7'h0E, 16'h1000, S2_CLKOUT3[15:0]};
- rom[31] = {7'h0F, 16'hFC00, S2_CLKOUT3[31:16]};
- // Store CLKOUT4 divide and phase
- rom[32] = {7'h10, 16'h1000, S2_CLKOUT4[15:0]};
- rom[33] = {7'h11, 16'hFC00, S2_CLKOUT4[31:16]};
- // Store CLKOUT5 divide and phase
- rom[34] = {7'h06, 16'h1000, S2_CLKOUT5[15:0]};
- rom[35] = (S2_CLKOUT0_FRAC_EN == 0) ?
- {7'h07, 16'hC000, S2_CLKOUT5[31:16]}:
- {7'h07, 16'hC000, S2_CLKOUT5[31:30], S2_CLKOUT0_FRAC_CALC[35:32],S2_CLKOUT5[25:16]};
- // Store CLKOUT6 divide and phase
- rom[36] = {7'h12, 16'h1000, S2_CLKOUT6[15:0]};
- rom[37] = (S2_CLKFBOUT_FRAC_EN == 0) ?
- {7'h13, 16'hC000, S2_CLKOUT6[31:16]}:
- {7'h13, 16'hC000, S2_CLKOUT6[31:30], S2_CLKFBOUT_FRAC_CALC[35:32],S2_CLKOUT6[25:16]};
- // Store the input divider
- rom[38] = {7'h16, 16'hC000, {2'h0, S2_DIVCLK[23:22], S2_DIVCLK[11:0]} };
- // Store the feedback divide and phase
- rom[39] = (S2_CLKFBOUT_FRAC_EN == 0) ?
- {7'h14, 16'h1000, S2_CLKFBOUT[15:0]}:
- {7'h14, 16'h1000, S2_CLKFBOUT_FRAC_CALC[15:0]};
- rom[40] = (S2_CLKFBOUT_FRAC_EN == 0) ?
- {7'h15, 16'h8000, S2_CLKFBOUT[31:16]}:
- {7'h15, 16'h8000, S2_CLKFBOUT_FRAC_CALC[31:16]};
- // Store the lock settings
- rom[41] = {7'h18, 16'hFC00, {6'h00, S2_LOCK[29:20]} };
- rom[42] = {7'h19, 16'h8000, {1'b0 , S2_LOCK[34:30], S2_LOCK[9:0]} };
- rom[43] = {7'h1A, 16'h8000, {1'b0 , S2_LOCK[39:35], S2_LOCK[19:10]} };
- // Store the filter settings
- rom[44] = {7'h4E, 16'h66FF,
- S2_DIGITAL_FILT[9], 2'h0, S2_DIGITAL_FILT[8:7], 2'h0,
- S2_DIGITAL_FILT[6], 8'h00 };
- rom[45] = {7'h4F, 16'h666F,
- S2_DIGITAL_FILT[5], 2'h0, S2_DIGITAL_FILT[4:3], 2'h0,
- S2_DIGITAL_FILT[2:1], 2'h0, S2_DIGITAL_FILT[0], 4'h0 };
- // Initialize the rest of the ROM
- rom[46] = {7'h28,32'h0000_0000};
- for(ii = 47; ii < 64; ii = ii +1) begin
- rom[ii] = 0;
- end
- end
- // Output the initialized rom value based on rom_addr each clock cycle
- always @(posedge SCLK) begin
- rom_do<= #TCQ rom[rom_addr];
- end
- //**************************************************************************
- // Everything below is associated whith the state machine that is used to
- // Read/Modify/Write to the MMCM.
- //**************************************************************************
- // State Definitions
- localparam RESTART = 4'h1;
- localparam WAIT_LOCK = 4'h2;
- localparam WAIT_SEN = 4'h3;
- localparam ADDRESS = 4'h4;
- localparam WAIT_A_DRDY = 4'h5;
- localparam BITMASK = 4'h6;
- localparam BITSET = 4'h7;
- localparam WRITE = 4'h8;
- localparam WAIT_DRDY = 4'h9;
- // State sync
- reg [3:0] current_state = RESTART;
- reg [3:0] next_state = RESTART;
- // These variables are used to keep track of the number of iterations that
- // each state takes to reconfigure.
- // STATE_COUNT_CONST is used to reset the counters and should match the
- // number of registers necessary to reconfigure each state.
- localparam STATE_COUNT_CONST = 23;
- reg [4:0] state_count = STATE_COUNT_CONST;
- reg [4:0] next_state_count = STATE_COUNT_CONST;
- // This block assigns the next register value from the state machine below
- always @(posedge SCLK) begin
- DADDR <= #TCQ next_daddr;
- DWE <= #TCQ next_dwe;
- DEN <= #TCQ next_den;
- RST_MMCM <= #TCQ next_rst_mmcm;
- DI <= #TCQ next_di;
- SRDY <= #TCQ next_srdy;
- rom_addr <= #TCQ next_rom_addr;
- state_count <= #TCQ next_state_count;
- end
- // This block assigns the next state, reset is syncronous.
- always @(posedge SCLK) begin
- if(RST) begin
- current_state <= #TCQ RESTART;
- end else begin
- current_state <= #TCQ next_state;
- end
- end
- always @* begin
- // Setup the default values
- next_srdy = 1'b0;
- next_daddr = DADDR;
- next_dwe = 1'b0;
- next_den = 1'b0;
- next_rst_mmcm = RST_MMCM;
- next_di = DI;
- next_rom_addr = rom_addr;
- next_state_count = state_count;
- case (current_state)
- // If RST is asserted reset the machine
- RESTART: begin
- next_daddr = 7'h00;
- next_di = 16'h0000;
- next_rom_addr = 6'h00;
- next_rst_mmcm = 1'b1;
- next_state = WAIT_LOCK;
- end
- // Waits for the MMCM to assert IntLocked - once it does asserts SRDY
- WAIT_LOCK: begin
- // Make sure reset is de-asserted
- next_rst_mmcm = 1'b0;
- // Reset the number of registers left to write for the next
- // reconfiguration event.
- next_state_count = STATE_COUNT_CONST ;
- next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
- if(IntLocked) begin
- // MMCM is IntLocked, go on to wait for the SEN signal
- next_state = WAIT_SEN;
- // Assert SRDY to indicate that the reconfiguration module is
- // ready
- next_srdy = 1'b1;
- end else begin
- // Keep waiting, IntLocked has not asserted yet
- next_state = WAIT_LOCK;
- end
- end
- // Wait for the next SEN pulse and set the ROM addr appropriately
- // based on SADDR
- WAIT_SEN: begin
- next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
- if (SEN) begin
- next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
- // Go on to address the MMCM
- next_state = ADDRESS;
- end else begin
- // Keep waiting for SEN to be asserted
- next_state = WAIT_SEN;
- end
- end
- // Set the address on the MMCM and assert DEN to read the value
- ADDRESS: begin
- // Reset the DCM through the reconfiguration
- next_rst_mmcm = 1'b1;
- // Enable a read from the MMCM and set the MMCM address
- next_den = 1'b1;
- next_daddr = rom_do[38:32];
- // Wait for the data to be ready
- next_state = WAIT_A_DRDY;
- end
- // Wait for DRDY to assert after addressing the MMCM
- WAIT_A_DRDY: begin
- if (DRDY) begin
- // Data is ready, mask out the bits to save
- next_state = BITMASK;
- end else begin
- // Keep waiting till data is ready
- next_state = WAIT_A_DRDY;
- end
- end
- // Zero out the bits that are not set in the mask stored in rom
- BITMASK: begin
- // Do the mask
- next_di = rom_do[31:16] & DO;
- // Go on to set the bits
- next_state = BITSET;
- end
- // After the input is masked, OR the bits with calculated value in rom
- BITSET: begin
- // Set the bits that need to be assigned
- next_di = rom_do[15:0] | DI;
- // Set the next address to read from ROM
- next_rom_addr = rom_addr + 1'b1;
- // Go on to write the data to the MMCM
- next_state = WRITE;
- end
- // DI is setup so assert DWE, DEN, and RST_MMCM. Subtract one from the
- // state count and go to wait for DRDY.
- WRITE: begin
- // Set WE and EN on MMCM
- next_dwe = 1'b1;
- next_den = 1'b1;
- // Decrement the number of registers left to write
- next_state_count = state_count - 1'b1;
- // Wait for the write to complete
- next_state = WAIT_DRDY;
- end
- // Wait for DRDY to assert from the MMCM. If the state count is not 0
- // jump to ADDRESS (continue reconfiguration). If state count is
- // 0 wait for lock.
- WAIT_DRDY: begin
- if(DRDY) begin
- // Write is complete
- if(state_count > 0) begin
- // If there are more registers to write keep going
- next_state = ADDRESS;
- end else begin
- // There are no more registers to write so wait for the MMCM
- // to lock
- next_state = WAIT_LOCK;
- end
- end else begin
- // Keep waiting for write to complete
- next_state = WAIT_DRDY;
- end
- end
- // If in an unknown state reset the machine
- default: begin
- next_state = RESTART;
- end
- endcase
- end
- endmodule
|