Commit 85a39483 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

mmcm/pll warppers

parent 407c39ca
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -140,7 +140,7 @@ module phy_top #(
    .rst             (rst),
    .rst             (rst),
    .dci_disable_dqs (dci_disable_dqs),  // disable DCI termination during writes and idle for dqs
    .dci_disable_dqs (dci_disable_dqs),  // disable DCI termination during writes and idle for dqs
    .dci_disable_dq  (dci_disable_dq),   // disable DCI termination during writes and idle for dq and dm signals
    .dci_disable_dq  (dci_disable_dq),   // disable DCI termination during writes and idle for dq and dm signals
    .din             (din[31:0]),        // parallel data to be sent out (4 bits per DG I/))
    .din             (din[31:0]),        // parallel data to be sent out (4 bits per DQ I/O))
    .din_dm          (din_dm[3:0]),      // parallel data to be sent out over DM
    .din_dm          (din_dm[3:0]),      // parallel data to be sent out over DM
    .tin_dq          (tin_dq[3:0]),      // tristate for data out (sent out earlier than data!) and dm 
    .tin_dq          (tin_dq[3:0]),      // tristate for data out (sent out earlier than data!) and dm 
    .din_dqs         (din_dqs[3:0]),     // parallel data to be sent out over DQS
    .din_dqs         (din_dqs[3:0]),     // parallel data to be sent out over DQS
@@ -148,7 +148,7 @@ module phy_top #(
    .dout            (dout[31:0]),       // parallel data received from DDR3 memory, 4 bits per DQ I/O
    .dout            (dout[31:0]),       // parallel data received from DDR3 memory, 4 bits per DQ I/O
    .dly_data        (dly_data[7:0]),    // delay value (3 LSB - fine delay)
    .dly_data        (dly_data[7:0]),    // delay value (3 LSB - fine delay)
    .dly_addr        (dly_addr[4:0]),    // select which delay to program
    .dly_addr        (dly_addr[4:0]),    // select which delay to program
    .ld_delay        (ld_data_l),        // load delay data to selected iodelayl (clk_iv synchronous)
    .ld_delay        (ld_data_l),        // load delay data to selected iodelayl (clk_div synchronous)
    .set             (set)               // clk_div synchronous set all delays from previously loaded values
    .set             (set)               // clk_div synchronous set all delays from previously loaded values
);
);


@@ -172,7 +172,7 @@ module phy_top #(
    .rst             (rst),
    .rst             (rst),
    .dci_disable_dqs (dci_disable_dqs),  // disable DCI termination during writes and idle for dqs
    .dci_disable_dqs (dci_disable_dqs),  // disable DCI termination during writes and idle for dqs
    .dci_disable_dq  (dci_disable_dq),   // disable DCI termination during writes and idle for dq and dm signals
    .dci_disable_dq  (dci_disable_dq),   // disable DCI termination during writes and idle for dq and dm signals
    .din             (din[63:32]),       // parallel data to be sent out (4 bits per DG I/))
    .din             (din[63:32]),       // parallel data to be sent out (4 bits per DQ I/O))
    .din_dm          (din_dm[7:4]),      // parallel data to be sent out over DM
    .din_dm          (din_dm[7:4]),      // parallel data to be sent out over DM
    .tin_dq          (tin_dq[7:4]),      // tristate for data out (sent out earlier than data!) and dm 
    .tin_dq          (tin_dq[7:4]),      // tristate for data out (sent out earlier than data!) and dm 
    .din_dqs         (din_dqs[7:4]),     // parallel data to be sent out over DQS
    .din_dqs         (din_dqs[7:4]),     // parallel data to be sent out over DQS
@@ -180,7 +180,7 @@ module phy_top #(
    .dout            (dout[63:32]),      // parallel data received from DDR3 memory, 4 bits per DQ I/O
    .dout            (dout[63:32]),      // parallel data received from DDR3 memory, 4 bits per DQ I/O
    .dly_data        (dly_data[7:0]),    // delay value (3 LSB - fine delay)
    .dly_data        (dly_data[7:0]),    // delay value (3 LSB - fine delay)
    .dly_addr        (dly_addr[4:0]),    // select which delay to program
    .dly_addr        (dly_addr[4:0]),    // select which delay to program
    .ld_delay        (ld_data_h),        // load delay data to selected iodelayl (clk_iv synchronous)
    .ld_delay        (ld_data_h),        // load delay data to selected iodelayl (clk_div synchronous)
    .set             (set)               // clk_div synchronous set all delays from previously loaded values
    .set             (set)               // clk_div synchronous set all delays from previously loaded values
);
);


+157 −83
Original line number Original line Diff line number Diff line
@@ -20,94 +20,168 @@
 *******************************************************************************/
 *******************************************************************************/
`timescale 1ns/1ps
`timescale 1ns/1ps


module  mmcm_adv(
module  mmcm_adv#(
    parameter CLKIN1_PERIOD =         0.000,  // input period in ns, 0..100.000 - MANDATORY, resolution down to 1 ps
    parameter CLKIN2_PERIOD =         0.000,  // input period in ns, 0..100.000 - MANDATORY, resolution down to 1 ps
    parameter BANDWIDTH =       "OPTIMIZED",  //"OPTIMIZED", "HIGH","LOW"
    parameter CLKFBOUT_MULT_F =       5.000,  // 2.0 to 64.0 . Together with CLKOUT#_DIVIDE and DIVCLK_DIVIDE
    parameter CLKFBOUT_PHASE =        0.000,  // CLOCK FEEDBACK phase in degrees (3 significant digits, -360.000...+360.000)
    parameter CLKOUT0_PHASE =         0.000,  // CLOCK0 phase in degrees (3 significant digits, -360.000...+360.000)
    parameter CLKOUT1_PHASE =         0.000,  // Initial/static fine phase shift, 1/(56*Fvco) actual step 
    parameter CLKOUT2_PHASE =         0.000,
    parameter CLKOUT3_PHASE =         0.000,
    parameter CLKOUT4_PHASE =         0.000,
    parameter CLKOUT5_PHASE =         0.000,
    parameter CLKOUT6_PHASE =         0.000,
    parameter CLKOUT0_DUTY_CYCLE=     0.5,    // CLOCK 0 output duty factor, 3 significant digits      
    parameter CLKOUT1_DUTY_CYCLE=     0.5,      
    parameter CLKOUT2_DUTY_CYCLE=     0.5,      
    parameter CLKOUT3_DUTY_CYCLE=     0.5,      
    parameter CLKOUT4_DUTY_CYCLE=     0.5,      
    parameter CLKOUT5_DUTY_CYCLE=     0.5,      
    parameter CLKOUT6_DUTY_CYCLE=     0.5,
    parameter CLKOUT4_CASCADE=       "FALSE", // cascades the output6 divider to the input for output 4     
    parameter CLKFBOUT_USE_FINE_PS = "FALSE", // Enable variable fine pase shift. Enable 1/(56*Fvco) phase inceremnts, round-robin
    parameter CLKOUT0_USE_FINE_PS =  "FALSE", // Same fine phase shift for all outputs where this attribute is "TRUE" 
    parameter CLKOUT1_USE_FINE_PS =  "FALSE", // Not compatible with fractional divide
    parameter CLKOUT2_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT3_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT4_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT5_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT6_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT0_DIVIDE_F =      1.000,  // CLK0 outout divide, floating 1.000..128.000
    parameter CLKOUT1_DIVIDE =        1,        // CLK1 outout divide, integer 1..128 (determins a phase step as a fraction of pi/4)
    parameter CLKOUT2_DIVIDE =        1,
    parameter CLKOUT3_DIVIDE =        1,
    parameter CLKOUT4_DIVIDE =        1,
    parameter CLKOUT5_DIVIDE =        1,
    parameter CLKOUT6_DIVIDE =        1,
    parameter COMPENSATION=           "ZHOLD", // "ZHOLD",BUF_IN","EXTERNAL","INTERNAL
                                               // ZHOLD - provide negative hold time on I/O registers
                                               // INTERNAL - using internal compensation no deley is compensated
                                               // EXTERNAL - external to the FPGA network is being compensated
                                               // BUF_IN - no compensation when clock input is driveen by BUFG/BUFH/BUFR or GT
    parameter DIVCLK_DIVIDE =         1,            // Integer 1..106. Divides all outputs with respect to CLKIN
    parameter REF_JITTER1   =         0.010,        // Expectet jitter on CLKIN1 (0.000..0.999)
    parameter REF_JITTER2   =         0.010,
    parameter SS_EN         =         "FALSE",      // Enables Spread Spectrum mode
    parameter SS_MODE       =         "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW"
    parameter SS_MOD_PERIOD =         10000,        // integer 4000-40000 - SS modulation period in ns
    parameter STARTUP_WAIT  =         "FALSE"       // Delays "DONE" signal until MMCM is locked
    
)
(
    input clkin1,   // General clock input
    input clkin2,   // Secondary clock input
    input clkfbin,  // Feedback clock input
    input clkinsel, // Clock select input : 1 - clkin1, 0 - clkin2
    input rst,      // asynchronous reset input
    input pwrdwn,   // power down input    
    input psclk,    // phase shift clock input
    input psen,     // phase shift enable input
    input psincdec, // phase shift direction input (1 - increment, 0 - decrement)
    output psdone,   // phase shift done (12 clocks after psen
    output clkout0,  // output 0, HPC BUFR/BUFIO capable
    output clkout1,  // output 1, HPC BUFR/BUFIO capable
    output clkout2,  // output 2, HPC BUFR/BUFIO capable
    output clkout3,  // output 3, HPC BUFR/BUFIO capable
    output clkout4,  // output 4, HPC BUFR/BUFIO not capable
    output clkout5,  // output 5, HPC BUFR/BUFIO not capable
    output clkout6,  // output 6, HPC BUFR/BUFIO not capable
    output clkout0b, // output 0, inverted 
    output clkout1b, // output 1, inverted 
    output clkout2b, // output 2, inverted 
    output clkout3b, // output 3, inverted
    output clkfbout, // dedicate feedback output    
    output clkfboutb,// inverted feedback output
    output locked   // PLL locked output
);
);
    /* Instance template for module MMCME2_ADV */
    MMCME2_ADV #(
    MMCME2_ADV #(
        .BANDWIDTH("OPTIMIZED"),
        .BANDWIDTH           (BANDWIDTH),
        .CLKFBOUT_MULT_F(5.000),
        .CLKFBOUT_MULT_F     (CLKFBOUT_MULT_F),
        .CLKFBOUT_PHASE(0.000),
        .CLKFBOUT_PHASE      (CLKFBOUT_PHASE),
        .CLKFBOUT_USE_FINE_PS("FALSE"),
        .CLKFBOUT_USE_FINE_PS(CLKFBOUT_USE_FINE_PS),
        .CLKIN1_PERIOD(0.000),
        .CLKIN1_PERIOD       (CLKIN1_PERIOD), 
        .CLKIN2_PERIOD(0.000),
        .CLKIN2_PERIOD       (CLKIN2_PERIOD),
        .CLKOUT0_DIVIDE_F(1.000),
        .CLKOUT0_DIVIDE_F    (CLKOUT0_DIVIDE_F),
        .CLKOUT0_DUTY_CYCLE(0.500),
        .CLKOUT0_DUTY_CYCLE  (CLKOUT0_DUTY_CYCLE),
        .CLKOUT0_PHASE(0.000),
        .CLKOUT0_PHASE       (CLKOUT0_PHASE),
        .CLKOUT0_USE_FINE_PS("FALSE"),
        .CLKOUT0_USE_FINE_PS (CLKOUT0_USE_FINE_PS),
        .CLKOUT1_DIVIDE(1),
        .CLKOUT1_DIVIDE      (CLKOUT1_DIVIDE),
        .CLKOUT1_DUTY_CYCLE(0.500),
        .CLKOUT1_DUTY_CYCLE  (CLKOUT1_DUTY_CYCLE),
        .CLKOUT1_PHASE(0.000),
        .CLKOUT1_PHASE       (CLKOUT1_PHASE),
        .CLKOUT1_USE_FINE_PS("FALSE"),
        .CLKOUT1_USE_FINE_PS (CLKOUT1_USE_FINE_PS),
        .CLKOUT2_DIVIDE(1),
        .CLKOUT2_DIVIDE      (CLKOUT2_DIVIDE),
        .CLKOUT2_DUTY_CYCLE(0.500),
        .CLKOUT2_DUTY_CYCLE  (CLKOUT2_DUTY_CYCLE),
        .CLKOUT2_PHASE(0.000),
        .CLKOUT2_PHASE       (CLKOUT2_PHASE),
        .CLKOUT2_USE_FINE_PS("FALSE"),
        .CLKOUT2_USE_FINE_PS (CLKOUT2_USE_FINE_PS),
        .CLKOUT3_DIVIDE(1),
        .CLKOUT3_DIVIDE      (CLKOUT3_DIVIDE),
        .CLKOUT3_DUTY_CYCLE(0.500),
        .CLKOUT3_DUTY_CYCLE  (CLKOUT3_DUTY_CYCLE),
        .CLKOUT3_PHASE(0.000),
        .CLKOUT3_PHASE       (CLKOUT3_PHASE),
        .CLKOUT3_USE_FINE_PS("FALSE"),
        .CLKOUT3_USE_FINE_PS (CLKOUT3_USE_FINE_PS),
        .CLKOUT4_CASCADE("FALSE"),
        .CLKOUT4_CASCADE     (CLKOUT4_CASCADE),
        .CLKOUT4_DIVIDE(1),
        .CLKOUT4_DIVIDE      (CLKOUT4_DIVIDE),
        .CLKOUT4_DUTY_CYCLE(0.500),
        .CLKOUT4_DUTY_CYCLE  (CLKOUT4_DUTY_CYCLE),
        .CLKOUT4_PHASE(0.000),
        .CLKOUT4_PHASE       (CLKOUT4_PHASE),
        .CLKOUT4_USE_FINE_PS("FALSE"),
        .CLKOUT4_USE_FINE_PS (CLKOUT4_USE_FINE_PS),
        .CLKOUT5_DIVIDE(1),
        .CLKOUT5_DIVIDE      (CLKOUT5_DIVIDE),
        .CLKOUT5_DUTY_CYCLE(0.500),
        .CLKOUT5_DUTY_CYCLE  (CLKOUT5_DUTY_CYCLE),
        .CLKOUT5_PHASE(0.000),
        .CLKOUT5_PHASE       (CLKOUT5_PHASE),
        .CLKOUT5_USE_FINE_PS("FALSE"),
        .CLKOUT5_USE_FINE_PS (CLKOUT5_USE_FINE_PS),
        .CLKOUT6_DIVIDE(1),
        .CLKOUT6_DIVIDE      (CLKOUT6_DIVIDE),
        .CLKOUT6_DUTY_CYCLE(0.500),
        .CLKOUT6_DUTY_CYCLE  (CLKOUT6_DUTY_CYCLE),
        .CLKOUT6_PHASE(0.000),
        .CLKOUT6_PHASE       (CLKOUT6_PHASE),
        .CLKOUT6_USE_FINE_PS("FALSE"),
        .CLKOUT6_USE_FINE_PS (CLKOUT6_USE_FINE_PS),
        .COMPENSATION("ZHOLD"),
        .COMPENSATION        (COMPENSATION),
        .DIVCLK_DIVIDE(1),
        .DIVCLK_DIVIDE       (DIVCLK_DIVIDE),
        .IS_CLKINSEL_INVERTED  (1'b0),
        .IS_CLKINSEL_INVERTED  (1'b0),
        .IS_PSEN_INVERTED      (1'b0),
        .IS_PSEN_INVERTED      (1'b0),
        .IS_PSINCDEC_INVERTED  (1'b0),
        .IS_PSINCDEC_INVERTED  (1'b0),
        .IS_PWRDWN_INVERTED    (1'b0),
        .IS_PWRDWN_INVERTED    (1'b0),
        .IS_RST_INVERTED       (1'b0),
        .IS_RST_INVERTED       (1'b0),
        .REF_JITTER1(0.010),
        .REF_JITTER1         (REF_JITTER1),
        .REF_JITTER2(0.010),
        .REF_JITTER2         (REF_JITTER2),
        .SS_EN("FALSE"),
        .SS_EN               (SS_EN),
        .SS_MODE("CENTER_HIGH"),
        .SS_MODE             (SS_MODE),
        .SS_MOD_PERIOD(10000),
        .SS_MOD_PERIOD       (SS_MOD_PERIOD),
        .STARTUP_WAIT("FALSE")
        .STARTUP_WAIT        (STARTUP_WAIT)
    ) MMCME2_ADV_i (
    ) MMCME2_ADV_i (
        .CLKFBOUT(), // output
        .CLKFBOUT       (clkfbout), // output
        .CLKFBOUTB(), // output
        .CLKFBOUTB      (clkfboutb), // output
        .CLKFBSTOPPED      (), // output
        .CLKFBSTOPPED      (), // output
        .CLKINSTOPPED      (), // output
        .CLKINSTOPPED      (), // output
        .CLKOUT0(), // output
        .CLKOUT0        (clkout0), // output
        .CLKOUT0B(), // output
        .CLKOUT0B       (clkout0b), // output
        .CLKOUT1(), // output
        .CLKOUT1        (clkout1), // output
        .CLKOUT1B(), // output
        .CLKOUT1B       (clkout1b), // output
        .CLKOUT2(), // output
        .CLKOUT2        (clkout2), // output
        .CLKOUT2B(), // output
        .CLKOUT2B       (clkout2b), // output
        .CLKOUT3(), // output
        .CLKOUT3        (clkout3), // output
        .CLKOUT3B(), // output
        .CLKOUT3B       (clkout3b), // output
        .CLKOUT4(), // output
        .CLKOUT4        (clkout4), // output
        .CLKOUT5(), // output
        .CLKOUT5        (clkout5), // output
        .CLKOUT6(), // output
        .CLKOUT6        (clkout6), // output
        .DO(), // output[15:0]
        .DO                 (), // Dynamic reconfiguration output[15:0] 
        .DRDY(), // output
        .DRDY               (), // Dynamic reconfiguration output
        .LOCKED(), // output
        .LOCKED         (locked), // output
        .PSDONE(), // output
        .PSDONE         (psdone), // output
        .CLKFBIN(), // input
        .CLKFBIN        (clkfbin), // input
        .CLKIN1(), // input
        .CLKIN1         (clkin1), // input
        .CLKIN2(), // input
        .CLKIN2         (clkin2), // input
        .CLKINSEL(), // input
        .CLKINSEL       (clkinsel), // input
        .DADDR(), // input[6:0]
        .DADDR             (7'b0), // Dynamic reconfiguration address (input[6:0])
        .DCLK(), // input
        .DCLK              (1'b0), // Dynamic reconfiguration clock input
        .DEN(), // input
        .DEN               (1'b0), // Dynamic reconfiguration enable input
        .DI(), // input[15:0]
        .DI                (16'b0), // Dynamic reconfiguration data (input[15:0])
        .DWE(), // input
        .DWE               (1'b0), // Dynamic reconfiguration Write Enable input
        .PSCLK(), // input
        .PSCLK          (psclk), // input
        .PSEN(), // input
        .PSEN           (psen), // input
        .PSINCDEC(), // input
        .PSINCDEC       (psincdec), // input
        .PWRDWN(), // input
        .PWRDWN         (pwrdwn), // input
        .RST() // input
        .RST            (rst) // input
    );
    );




endmodule
endmodule


+217 −0
Original line number Original line Diff line number Diff line
/*******************************************************************************
 * Module: mmcm_phase_cntr
 * Date:2014-05-01  
 * Author: Andrey Filippov
 * Description: MMCME2_ADV with phase counter, supporting absolute phase setting
 *
 * Copyright (c) 2014 Elphel, Inc.
 * mmcm_phase_cntr.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  mmcm_phase_cntr.v is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

// all counters are two-clock cycle nets
module  mmcm_phase_cntr#(
    parameter PHASE_WIDTH=            8,      // number of bits for te phase counter (depends on divisors)
    parameter CLKIN_PERIOD =         0.000,  // input period in ns, 0..100.000 - MANDATORY, resolution down to 1 ps
    parameter BANDWIDTH =       "OPTIMIZED",  //"OPTIMIZED", "HIGH","LOW"
    parameter CLKFBOUT_MULT_F =       5.000,  // 2.0 to 64.0 . Together with CLKOUT#_DIVIDE and DIVCLK_DIVIDE
    parameter CLKFBOUT_PHASE =        0.000,  // CLOCK FEEDBACK phase in degrees (3 significant digits, -360.000...+360.000)
    parameter CLKOUT0_PHASE =         0.000,  // CLOCK0 phase in degrees (3 significant digits, -360.000...+360.000)
    parameter CLKOUT1_PHASE =         0.000,  // Initial/static fine phase shift, 1/(56*Fvco) actual step 
    parameter CLKOUT2_PHASE =         0.000,
    parameter CLKOUT3_PHASE =         0.000,
    parameter CLKOUT4_PHASE =         0.000,
    parameter CLKOUT5_PHASE =         0.000,
    parameter CLKOUT6_PHASE =         0.000,
    parameter CLKOUT0_DUTY_CYCLE=     0.5,    // CLOCK 0 output duty factor, 3 significant digits      
    parameter CLKOUT1_DUTY_CYCLE=     0.5,      
    parameter CLKOUT2_DUTY_CYCLE=     0.5,      
    parameter CLKOUT3_DUTY_CYCLE=     0.5,      
    parameter CLKOUT4_DUTY_CYCLE=     0.5,      
    parameter CLKOUT5_DUTY_CYCLE=     0.5,      
    parameter CLKOUT6_DUTY_CYCLE=     0.5,
    parameter CLKOUT4_CASCADE=       "FALSE", // cascades the output6 divider to the input for output 4     
    parameter CLKFBOUT_USE_FINE_PS = "FALSE", // Enable variable fine pase shift. Enable 1/(56*Fvco) phase inceremnts, round-robin
    parameter CLKOUT0_USE_FINE_PS =  "FALSE", // Same fine phase shift for all outputs where this attribute is "TRUE" 
    parameter CLKOUT1_USE_FINE_PS =  "FALSE", // Not compatible with fractional divide
    parameter CLKOUT2_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT3_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT4_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT5_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT6_USE_FINE_PS =  "FALSE", 
    parameter CLKOUT0_DIVIDE_F =      1.000,  // CLK0 outout divide, floating 1.000..128.000
    parameter CLKOUT1_DIVIDE =        1,        // CLK1 outout divide, integer 1..128 (determins a phase step as a fraction of pi/4)
    parameter CLKOUT2_DIVIDE =        1,
    parameter CLKOUT3_DIVIDE =        1,
    parameter CLKOUT4_DIVIDE =        1,
    parameter CLKOUT5_DIVIDE =        1,
    parameter CLKOUT6_DIVIDE =        1,
    parameter COMPENSATION=           "ZHOLD", // "ZHOLD",BUF_IN","EXTERNAL","INTERNAL
                                               // ZHOLD - provide negative hold time on I/O registers
                                               // INTERNAL - using internal compensation no deley is compensated
                                               // EXTERNAL - external to the FPGA network is being compensated
                                               // BUF_IN - no compensation when clock input is driveen by BUFG/BUFH/BUFR or GT
    parameter DIVCLK_DIVIDE =         1,            // Integer 1..106. Divides all outputs with respect to CLKIN
    parameter REF_JITTER1   =         0.010,        // Expectet jitter on CLKIN1 (0.000..0.999)
    parameter REF_JITTER2   =         0.010,
    parameter SS_EN         =         "FALSE",      // Enables Spread Spectrum mode
    parameter SS_MODE       =         "CENTER_HIGH",//"CENTER_HIGH","CENTER_LOW","DOWN_HIGH","DOWN_LOW"
    parameter SS_MOD_PERIOD =         10000,        // integer 4000-40000 - SS modulation period in ns
    parameter STARTUP_WAIT  =         "FALSE"       // Delays "DONE" signal until MMCM is locked
)
(
    input clkin,   // General clock input
    input clkfbin,  // Feedback clock input
    input rst,      // asynchronous reset input
    input pwrdwn,   // power down input    
    input psclk,    // phase shift clock input
    
    input ps_we,     // phase shift write eneble
    input [PHASE_WIDTH-1:0] ps_din, // phase shift data input (2-s complement)
    output ps_ready,  // phase shift change finished
    output reg [PHASE_WIDTH-1:0] ps_dout, // current phase shift value
     
    output clkout0,  // output 0, HPC BUFR/BUFIO capable
    output clkout1,  // output 1, HPC BUFR/BUFIO capable
    output clkout2,  // output 2, HPC BUFR/BUFIO capable
    output clkout3,  // output 3, HPC BUFR/BUFIO capable
    output clkout4,  // output 4, HPC BUFR/BUFIO not capable
    output clkout5,  // output 5, HPC BUFR/BUFIO not capable
    output clkout6,  // output 6, HPC BUFR/BUFIO not capable
    output clkout0b, // output 0, inverted 
    output clkout1b, // output 1, inverted 
    output clkout2b, // output 2, inverted 
    output clkout3b, // output 3, inverted
    output clkfbout, // dedicate feedback output    
    output clkfboutb,// inverted feedback output
    output locked   // PLL locked output
);
    wire psen;       // phase shift enable input
    reg psincdec;    // phase shift direction input (1 - increment, 0 - decrement)
    wire psdone;     // phase shift done (12 clocks after psen
    reg [PHASE_WIDTH-1:0] ps_target;
    reg ps_busy=0;
    reg ps_start0, ps_start;
    assign ps_ready=!ps_busy && locked && ps_start0 && ps_start;
    assign psen=ps_start && (diff != 0);
    wire [PHASE_WIDTH:0] diff= ps_target-ps_dout;
    always @ (posedge psclk or posedge rst) begin
        if (rst) ps_start0 <= 0;
        else ps_start0 <= ps_we && ps_ready;
        
        if (rst) ps_dout <= 0;
        else if (psen &&  psincdec) ps_dout <= ps_dout +1; 
        else if (psen && !psincdec) ps_dout <= ps_dout -1;
        
        if (rst) ps_target <= 0;
        else if (ps_we && ps_ready) ps_target <= ps_din;

        if (rst)           ps_busy <= 1'b0;
        else if (ps_start) ps_busy <= (diff!=0);
        
        
    end
    always @ (posedge psclk) begin
        ps_start <= ps_start0 || psdone;
        psincdec <= !diff[PHASE_WIDTH];
    end

    MMCME2_ADV #(
        .BANDWIDTH           (BANDWIDTH),
        .CLKFBOUT_MULT_F     (CLKFBOUT_MULT_F),
        .CLKFBOUT_PHASE      (CLKFBOUT_PHASE),
        .CLKFBOUT_USE_FINE_PS(CLKFBOUT_USE_FINE_PS),
        .CLKIN1_PERIOD       (CLKIN_PERIOD), 
        .CLKIN2_PERIOD        (0),
        .CLKOUT0_DIVIDE_F    (CLKOUT0_DIVIDE_F),
        .CLKOUT0_DUTY_CYCLE  (CLKOUT0_DUTY_CYCLE),
        .CLKOUT0_PHASE       (CLKOUT0_PHASE),
        .CLKOUT0_USE_FINE_PS (CLKOUT0_USE_FINE_PS),
        .CLKOUT1_DIVIDE      (CLKOUT1_DIVIDE),
        .CLKOUT1_DUTY_CYCLE  (CLKOUT1_DUTY_CYCLE),
        .CLKOUT1_PHASE       (CLKOUT1_PHASE),
        .CLKOUT1_USE_FINE_PS (CLKOUT1_USE_FINE_PS),
        .CLKOUT2_DIVIDE      (CLKOUT2_DIVIDE),
        .CLKOUT2_DUTY_CYCLE  (CLKOUT2_DUTY_CYCLE),
        .CLKOUT2_PHASE       (CLKOUT2_PHASE),
        .CLKOUT2_USE_FINE_PS (CLKOUT2_USE_FINE_PS),
        .CLKOUT3_DIVIDE      (CLKOUT3_DIVIDE),
        .CLKOUT3_DUTY_CYCLE  (CLKOUT3_DUTY_CYCLE),
        .CLKOUT3_PHASE       (CLKOUT3_PHASE),
        .CLKOUT3_USE_FINE_PS (CLKOUT3_USE_FINE_PS),
        .CLKOUT4_CASCADE     (CLKOUT4_CASCADE),
        .CLKOUT4_DIVIDE      (CLKOUT4_DIVIDE),
        .CLKOUT4_DUTY_CYCLE  (CLKOUT4_DUTY_CYCLE),
        .CLKOUT4_PHASE       (CLKOUT4_PHASE),
        .CLKOUT4_USE_FINE_PS (CLKOUT4_USE_FINE_PS),
        .CLKOUT5_DIVIDE      (CLKOUT5_DIVIDE),
        .CLKOUT5_DUTY_CYCLE  (CLKOUT5_DUTY_CYCLE),
        .CLKOUT5_PHASE       (CLKOUT5_PHASE),
        .CLKOUT5_USE_FINE_PS (CLKOUT5_USE_FINE_PS),
        .CLKOUT6_DIVIDE      (CLKOUT6_DIVIDE),
        .CLKOUT6_DUTY_CYCLE  (CLKOUT6_DUTY_CYCLE),
        .CLKOUT6_PHASE       (CLKOUT6_PHASE),
        .CLKOUT6_USE_FINE_PS (CLKOUT6_USE_FINE_PS),
        .COMPENSATION        (COMPENSATION),
        .DIVCLK_DIVIDE       (DIVCLK_DIVIDE),
        .IS_CLKINSEL_INVERTED  (1'b0),
        .IS_PSEN_INVERTED      (1'b0),
        .IS_PSINCDEC_INVERTED  (1'b0),
        .IS_PWRDWN_INVERTED    (1'b0),
        .IS_RST_INVERTED       (1'b0),
        .REF_JITTER1         (REF_JITTER1),
        .REF_JITTER2         (REF_JITTER2),
        .SS_EN               (SS_EN),
        .SS_MODE             (SS_MODE),
        .SS_MOD_PERIOD       (SS_MOD_PERIOD),
        .STARTUP_WAIT        (STARTUP_WAIT)
    ) MMCME2_ADV_i (
        .CLKFBOUT       (clkfbout), // output
        .CLKFBOUTB      (clkfboutb), // output
        .CLKFBSTOPPED      (), // output
        .CLKINSTOPPED      (), // output
        .CLKOUT0        (clkout0), // output
        .CLKOUT0B       (clkout0b), // output
        .CLKOUT1        (clkout1), // output
        .CLKOUT1B       (clkout1b), // output
        .CLKOUT2        (clkout2), // output
        .CLKOUT2B       (clkout2b), // output
        .CLKOUT3        (clkout3), // output
        .CLKOUT3B       (clkout3b), // output
        .CLKOUT4        (clkout4), // output
        .CLKOUT5        (clkout5), // output
        .CLKOUT6        (clkout6), // output
        .DO                 (), // Dynamic reconfiguration output[15:0] 
        .DRDY               (), // Dynamic reconfiguration output
        .LOCKED         (locked), // output
        .PSDONE         (psdone), // output
        .CLKFBIN        (clkfbin), // input
        .CLKIN1         (clkin), // input
        .CLKIN2            (1'b0), // input
        .CLKINSEL          (1'b1), // input Select CLKIN1
        .DADDR             (7'b0), // Dynamic reconfiguration address (input[6:0])
        .DCLK              (1'b0), // Dynamic reconfiguration clock input
        .DEN               (1'b0), // Dynamic reconfiguration enable input
        .DI                (16'b0), // Dynamic reconfiguration data (input[15:0])
        .DWE               (1'b0), // Dynamic reconfiguration Write Enable input
        .PSCLK          (psclk), // input
        .PSEN           (psen), // input
        .PSINCDEC       (psincdec), // input
        .PWRDWN         (pwrdwn), // input
        .RST            (rst) // input
    );


endmodule