Commit 886f1771 authored by Alexey Grebenkin's avatar Alexey Grebenkin
Browse files

initial v0.1 files

parent 10d25413
Loading
Loading
Loading
Loading
+752 −0

File added.

Preview size limit exceeded, changes collapsed.

+41 −0
Original line number Diff line number Diff line
`ifndef CLOCK_DIVIDER_V
`define CLOCK_DIVIDER_V
// non synthesisable!
module clock_divider(
    input   wire    clk_in,
    output  reg     clk_out,

    input   wire    [31:0]  div
);
parameter divide_by = 1;
parameter divide_by_param = 1;

reg     [31:0]  cnt = 0;

reg [31:0]  div_r;
initial
begin
    cnt = 0;
    clk_out = 1'b1;
    forever
    begin
        if (divide_by_param == 0)
        begin
            if (div > 32'h0) 
                div_r = div;
            else    
                div_r = 1;
            repeat (div_r)
                @ (clk_in);
        end
        else
        begin
            repeat (divide_by)
                @ (clk_in);
        end
        clk_out = ~clk_out;
    end
end

endmodule
`endif
+310 −0
Original line number Diff line number Diff line
`include "gtxe2_chnl_clocking.v"
`include "gtxe2_chnl_tx.v"
`include "gtxe2_chnl_rx.v"
module gtxe2_chnl(
    input   wire            reset,
/*
 * TX
 */
    output  wire            TXP,
    output  wire            TXN,

    input   wire    [63:0]  TXDATA,
    input   wire            TXUSRCLK,
    input   wire            TXUSRCLK2,

// 8/10 encoder
    input   wire    [7:0]   TX8B10BBYPASS,
    input   wire            TX8B10BEN,
    input   wire    [7:0]   TXCHARDISPMODE,
    input   wire    [7:0]   TXCHARDISPVAL,
    input   wire    [7:0]   TXCHARISK,

// TX Buffer
    output  wire    [1:0]   TXBUFSTATUS,

// TX Polarity
    input   wire            TXPOLARITY,

// TX Fabric Clock Control
    input   wire    [2:0]   TXRATE,
    output  wire            TXRATEDONE,

// TX OOB
    input   wire            TXCOMINIT,
    input   wire            TXCOMWAKE,
    output  wire            TXCOMFINISH,

// TX Driver Control
    input   wire            TXELECIDLE,

/*
 * RX
 */ 
    input   wire            RXP,
    input   wire            RXN,
    
    input   wire            RXUSRCLK,
    input   wire            RXUSRCLK2,

    output  wire    [63:0]  RXDATA,

    input   wire    [2:0]   RXRATE,

// oob
    input   wire    [1:0]   RXELECIDLEMODE,
    output  wire            RXELECIDLE,

    output  wire            RXCOMINITDET,
    output  wire            RXCOMWAKEDET,

// polarity
    input   wire            RXPOLARITY,

// aligner
    output  wire            RXBYTEISALIGNED,
    output  wire            RXBYTEREALIGN,
    output  wire            RXCOMMADET,

    input   wire            RXCOMMADETEN,
    input   wire            RXPCOMMAALIGNEN,
    input   wire            RXMCOMMAALIGNEN,

// 10/8 decoder
    input   wire            RX8B10BEN,

    output  wire    [7:0]   RXCHARISCOMMA,
    output  wire    [7:0]   RXCHARISK,
    output  wire    [7:0]   RXDISPERR,
    output  wire    [7:0]   RXNOTINTABLE,

/*
 * Clocking
 */
// top-level interfaces
    input   wire    [2:0]   CPLLREFCLKSEL,
    input   wire            GTREFCLK0,
    input   wire            GTREFCLK1,
    input   wire            GTNORTHREFCLK0,
    input   wire            GTNORTHREFCLK1,
    input   wire            GTSOUTHREFCLK0,
    input   wire            GTSOUTHREFCLK1,
    input   wire            GTGREFCLK,
    input   wire            QPLLCLK,
    input   wire            QPLLREFCLK, 
    input   wire    [1:0]   RXSYSCLKSEL,
    input   wire    [1:0]   TXSYSCLKSEL,
    input   wire    [2:0]   TXOUTCLKSEL,
    input   wire    [2:0]   RXOUTCLKSEL,
    input   wire            TXDLYBYPASS,
    output  wire            GTREFCLKMONITOR,

    input   wire            CPLLLOCKDETCLK, 
    input   wire            CPLLLOCKEN,
    input   wire            CPLLPD,
    input   wire            CPLLRESET,
    output  wire            CPLLFBCLKLOST,
    output  wire            CPLLLOCK,
    output  wire            CPLLREFCLKLOST,

// phy-level interfaces
    output  wire            TXOUTCLKPMA,
    output  wire            TXOUTCLKPCS,
    output  wire            TXOUTCLK,
    output  wire            TXOUTCLKFABRIC,
    output  wire            tx_serial_clk,

    output  wire            RXOUTCLKPMA,
    output  wire            RXOUTCLKPCS,
    output  wire            RXOUTCLK,
    output  wire            RXOUTCLKFABRIC,
    output  wire            rx_serial_clk
);
parameter   [23:0]  CPLL_CFG        = 29'h00BC07DC;
parameter   integer CPLL_FBDIV      = 4;
parameter   integer CPLL_FBDIV_45   = 5;
parameter   [23:0]  CPLL_INIT_CFG   = 24'h00001E;
parameter   [15:0]  CPLL_LOCK_CFG   = 16'h01E8;
parameter   integer CPLL_REFCLK_DIV = 1;
parameter   [1:0]   PMA_RSV3        = 1;

parameter   TXOUT_DIV   = 2;
//parameter   TXRATE      = 3'b000;
parameter   RXOUT_DIV   = 2;
//parameter   RXRATE      = 3'b000;

parameter   integer TX_INT_DATAWIDTH    = 0;
parameter   integer TX_DATA_WIDTH       = 20;
parameter   integer PTX8B10BEN           = 1;

parameter   integer RX_DATA_WIDTH       = 20;
parameter   integer RX_INT_DATAWIDTH    = 0;
parameter   integer PRX8B10BEN           = 1;

parameter   DEC_MCOMMA_DETECT = "TRUE";
parameter   DEC_PCOMMA_DETECT = "TRUE";

parameter   [9:0]   ALIGN_MCOMMA_VALUE  = 10'b1010000011;
parameter           ALIGN_MCOMMA_DET    = "TRUE";
parameter   [9:0]   ALIGN_PCOMMA_VALUE  = 10'b0101111100;
parameter           ALIGN_PCOMMA_DET    = "TRUE";
parameter   [9:0]   ALIGN_COMMA_ENABLE  = 10'b1111111111;
parameter           ALIGN_COMMA_DOUBLE  = "FALSE";


parameter   [3:0]   SATA_BURST_SEQ_LEN = 4'b1111;
parameter           SATA_CPLL_CFG = "VCO_3000MHZ";

gtxe2_chnl_tx #(
    .TX_DATA_WIDTH      (TX_DATA_WIDTH),
    .TX_INT_DATAWIDTH   (TX_INT_DATAWIDTH),
    .PTX8B10BEN         (PTX8B10BEN),
    .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN),
    .SATA_CPLL_CFG      (SATA_CPLL_CFG)
)
tx(
    .reset              (reset),
    .TXP                (TXP),
    .TXN                (TXN),

    .TXDATA             (TXDATA),
    .TXUSRCLK           (TXUSRCLK),
    .TXUSRCLK2          (TXUSRCLK2),

    .TX8B10BBYPASS      (TX8B10BBYPASS),
    .TX8B10BEN          (TX8B10BEN),
    .TXCHARDISPMODE     (TXCHARDISPMODE),
    .TXCHARDISPVAL      (TXCHARDISPVAL),
    .TXCHARISK          (TXCHARISK),

    .TXBUFSTATUS        (TXBUFSTATUS),

    .TXPOLARITY         (TXPOLARITY),

    .TXRATE             (TXRATE),
    .TXRATEDONE         (TXRATEDONE),

    .TXCOMINIT          (TXCOMINIT),
    .TXCOMWAKE          (TXCOMWAKE),
    .TXCOMFINISH        (TXCOMFINISH),

    .TXELECIDLE         (TXELECIDLE),

    .serial_clk         (tx_serial_clk)
);

gtxe2_chnl_rx #(
    .RX_DATA_WIDTH          (RX_DATA_WIDTH),
    .RX_INT_DATAWIDTH       (RX_INT_DATAWIDTH),
    .PRX8B10BEN             (PRX8B10BEN),

    .DEC_MCOMMA_DETECT      (DEC_MCOMMA_DETECT),
    .DEC_PCOMMA_DETECT      (DEC_PCOMMA_DETECT),

    .ALIGN_MCOMMA_VALUE     (ALIGN_MCOMMA_VALUE),
    .ALIGN_MCOMMA_DET       (ALIGN_MCOMMA_DET),
    .ALIGN_PCOMMA_VALUE     (ALIGN_PCOMMA_VALUE),
    .ALIGN_PCOMMA_DET       (ALIGN_PCOMMA_DET),
    .ALIGN_COMMA_ENABLE     (ALIGN_COMMA_ENABLE),
    .ALIGN_COMMA_DOUBLE     (ALIGN_COMMA_DOUBLE)
)
rx(
    .reset              (reset),
    .RXP                (RXP),
    .RXN                (RXN),

    .RXUSRCLK           (RXUSRCLK),
    .RXUSRCLK2          (RXUSRCLK2),

    .RXDATA             (RXDATA),

    .RXELECIDLEMODE     (RXELECIDLEMODE),
    .RXELECIDLE         (RXELECIDLE),
    .RXCOMINITDET       (RXCOMINITDET),
    .RXCOMWAKEDET       (RXCOMWAKEDET),

    .RXPOLARITY         (RXPOLARITY),

    .RXBYTEISALIGNED    (RXBYTEISALIGNED),
    .RXBYTEREALIGN      (RXBYTEREALIGN),
    .RXCOMMADET         (RXCOMMADET),

    .RXCOMMADETEN       (RXCOMMADETEN),
    .RXPCOMMAALIGNEN    (RXPCOMMAALIGNEN),
    .RXMCOMMAALIGNEN    (RXMCOMMAALIGNEN),

    .RX8B10BEN          (RX8B10BEN),

    .RXCHARISCOMMA      (RXCHARISCOMMA),
    .RXCHARISK          (RXCHARISK),
    .RXDISPERR          (RXDISPERR),
    .RXNOTINTABLE       (RXNOTINTABLE),

    .serial_clk         (rx_serial_clk)
);

gtxe2_chnl_clocking #(
    .CPLL_CFG           (CPLL_CFG),
    .CPLL_FBDIV         (CPLL_FBDIV),
    .CPLL_FBDIV_45      (CPLL_FBDIV_45),
    .CPLL_INIT_CFG      (CPLL_INIT_CFG),
    .CPLL_LOCK_CFG      (CPLL_LOCK_CFG),
    .CPLL_REFCLK_DIV    (CPLL_REFCLK_DIV),
    .RXOUT_DIV          (RXOUT_DIV),
    .TXOUT_DIV          (TXOUT_DIV),
    .SATA_CPLL_CFG      (SATA_CPLL_CFG),
    .PMA_RSV3           (PMA_RSV3),

    .TXOUT_DIV          (TXOUT_DIV),
//    .TXRATE             (TXRATE),
    .RXOUT_DIV          (RXOUT_DIV),
//    .RXRATE             (RXRATE),

    .TX_INT_DATAWIDTH   (TX_INT_DATAWIDTH),
    .TX_DATA_WIDTH      (TX_DATA_WIDTH),
    .RX_INT_DATAWIDTH   (RX_INT_DATAWIDTH),
    .RX_DATA_WIDTH      (RX_DATA_WIDTH)
)
clocking(
    .CPLLREFCLKSEL      (CPLLREFCLKSEL),
    .GTREFCLK0          (GTREFCLK0),
    .GTREFCLK1          (GTREFCLK1),
    .GTNORTHREFCLK0     (GTNORTHREFCLK0),
    .GTNORTHREFCLK1     (GTNORTHREFCLK1),
    .GTSOUTHREFCLK0     (GTSOUTHREFCLK0),
    .GTSOUTHREFCLK1     (GTSOUTHREFCLK1),
    .GTGREFCLK          (GTGREFCLK),
    .QPLLCLK            (QPLLCLK),
    .QPLLREFCLK         (QPLLREFCLK ),
    .RXSYSCLKSEL        (RXSYSCLKSEL),
    .TXSYSCLKSEL        (TXSYSCLKSEL),
    .TXOUTCLKSEL        (TXOUTCLKSEL),
    .RXOUTCLKSEL        (RXOUTCLKSEL),
    .TXDLYBYPASS        (TXDLYBYPASS),
    .GTREFCLKMONITOR    (GTREFCLKMONITOR),

    .CPLLLOCKDETCLK     (CPLLLOCKDETCLK),
    .CPLLLOCKEN         (CPLLLOCKEN),
    .CPLLPD             (CPLLPD),
    .CPLLRESET          (CPLLRESET),
    .CPLLFBCLKLOST      (CPLLFBCLKLOST),
    .CPLLLOCK           (CPLLLOCK),
    .CPLLREFCLKLOST     (CPLLREFCLKLOST),

    .TXRATE             (TXRATE),
    .RXRATE             (RXRATE),

    .TXOUTCLKPMA        (TXOUTCLKPMA),
    .TXOUTCLKPCS        (TXOUTCLKPCS),
    .TXOUTCLK           (TXOUTCLK),
    .TXOUTCLKFABRIC     (TXOUTCLKFABRIC),
    .tx_serial_clk      (tx_serial_clk),

    .RXOUTCLKPMA        (RXOUTCLKPMA),
    .RXOUTCLKPCS        (RXOUTCLKPCS),
    .RXOUTCLK           (RXOUTCLK),
    .RXOUTCLKFABRIC     (RXOUTCLKFABRIC),
    .rx_serial_clk      (rx_serial_clk)
);

endmodule
+257 −0
Original line number Diff line number Diff line
`include "gtxe2_chnl_cpll_inmux.v"
`include "gtxe2_chnl_outclk_mux.v"
`include "gtxe2_chnl_cpll.v"
`include "clock_divider.v"
module gtxe2_chnl_clocking(
// top-level interfaces
    input   wire    [2:0]   CPLLREFCLKSEL,
    input   wire            GTREFCLK0,
    input   wire            GTREFCLK1,
    input   wire            GTNORTHREFCLK0,
    input   wire            GTNORTHREFCLK1,
    input   wire            GTSOUTHREFCLK0,
    input   wire            GTSOUTHREFCLK1,
    input   wire            GTGREFCLK,
    input   wire            QPLLCLK,
    input   wire            QPLLREFCLK, 
    input   wire    [1:0]   RXSYSCLKSEL,
    input   wire    [1:0]   TXSYSCLKSEL,
    input   wire    [2:0]   TXOUTCLKSEL,
    input   wire    [2:0]   RXOUTCLKSEL,
    input   wire            TXDLYBYPASS,
    output  wire            GTREFCLKMONITOR,

    input   wire            CPLLLOCKDETCLK, 
    input   wire            CPLLLOCKEN,
    input   wire            CPLLPD,
    input   wire            CPLLRESET,
    output  wire            CPLLFBCLKLOST,
    output  wire            CPLLLOCK,
    output  wire            CPLLREFCLKLOST,

    input   wire    [2:0]   TXRATE,
    input   wire    [2:0]   RXRATE,

// phy-level interfaces
    output  wire            TXOUTCLKPMA,
    output  wire            TXOUTCLKPCS,
    output  wire            TXOUTCLK,
    output  wire            TXOUTCLKFABRIC,
    output  wire            tx_serial_clk,
    output  wire            tx_piso_clk,

    output  wire            RXOUTCLKPMA,
    output  wire            RXOUTCLKPCS,
    output  wire            RXOUTCLK,
    output  wire            RXOUTCLKFABRIC,
    output  wire            rx_serial_clk,
    output  wire            tx_sipo_clk
);
// CPLL
parameter   [23:0]  CPLL_CFG        = 29'h00BC07DC;
parameter   integer CPLL_FBDIV      = 4;
parameter   integer CPLL_FBDIV_45   = 5;
parameter   [23:0]  CPLL_INIT_CFG   = 24'h00001E;
parameter   [15:0]  CPLL_LOCK_CFG   = 16'h01E8;
parameter   integer CPLL_REFCLK_DIV = 1;
parameter           SATA_CPLL_CFG = "VCO_3000MHZ";
parameter   [1:0]   PMA_RSV3        = 1;

parameter   TXOUT_DIV   = 2;
//parameter   TXRATE      = 3'b000;
parameter   RXOUT_DIV   = 2;
//parameter   RXRATE      = 3'b000;

parameter   TX_INT_DATAWIDTH    = 0;
parameter   TX_DATA_WIDTH       = 20;
parameter   RX_INT_DATAWIDTH    = 0;
parameter   RX_DATA_WIDTH       = 20;
/*
localparam  tx_serial_divider   = TXRATE == 3'b001 ? 1
                                : TXRATE == 3'b010 ? 2
                                : TXRATE == 3'b011 ? 4
                                : TXRATE == 3'b100 ? 8
                                : TXRATE == 3'b101 ? 16 : TXOUT_DIV ;
localparam  rx_serial_divider   = RXRATE == 3'b001 ? 1
                                : RXRATE == 3'b010 ? 2
                                : RXRATE == 3'b011 ? 4
                                : RXRATE == 3'b100 ? 8
                                : RXRATE == 3'b101 ? 16 : RXOUT_DIV ;
*/
localparam  tx_pma_divider1 = TX_INT_DATAWIDTH == 1 ? 4 : 2;
localparam  tx_pcs_divider1 = tx_pma_divider1;
localparam  tx_pma_divider2 = TX_DATA_WIDTH == 20 | TX_DATA_WIDTH == 40 | TX_DATA_WIDTH == 80 ? 5 : 4;
localparam  tx_pcs_divider2 = tx_pma_divider2;
localparam  rx_pma_divider1 = RX_INT_DATAWIDTH == 1 ? 4 : 2;
localparam  rx_pma_divider2 = RX_DATA_WIDTH == 20 | RX_DATA_WIDTH == 40 | RX_DATA_WIDTH == 80 ? 5 : 4;

wire    clk_mux_out;
wire    cpll_clk_out;
wire    tx_phy_clk;
wire    rx_phy_clk;
wire    TXPLLREFCLK_DIV1;
wire    TXPLLREFCLK_DIV2;
wire    RXPLLREFCLK_DIV1;
wire    RXPLLREFCLK_DIV2;

assign  tx_phy_clk          = TXSYSCLKSEL[0] ? QPLLCLK : cpll_clk_out;
assign  TXPLLREFCLK_DIV1    = TXSYSCLKSEL[1] ? QPLLREFCLK : clk_mux_out;
assign  rx_phy_clk          = RXSYSCLKSEL[0] ? QPLLCLK : cpll_clk_out;
assign  RXPLLREFCLK_DIV1    = RXSYSCLKSEL[1] ? QPLLREFCLK : clk_mux_out;

assign  tx_serial_clk = tx_phy_clk;
assign  rx_serial_clk = rx_phy_clk;

// piso and sipo clocks
// are not used in the design - no need to use ddr mode during simulation. much easier just multi serial clk by 2
wire    [31:0]  tx_serial_divider;
wire    [31:0]  rx_serial_divider;
assign  tx_serial_divider = TXRATE == 3'b001 ? 1
                          : TXRATE == 3'b010 ? 2
                          : TXRATE == 3'b011 ? 4
                          : TXRATE == 3'b100 ? 8
                          : TXRATE == 3'b101 ? 16 : TXOUT_DIV ;
assign  rx_serial_divider = RXRATE == 3'b001 ? 1
                          : RXRATE == 3'b010 ? 2
                          : RXRATE == 3'b011 ? 4
                          : RXRATE == 3'b100 ? 8
                          : RXRATE == 3'b101 ? 16 : RXOUT_DIV ;
clock_divider #(
//    .divide_by  (tx_serial_divider),
    .divide_by_param (0)
)
tx_toserialclk_div(
    .clk_in     (tx_phy_clk),
    .clk_out    (tx_piso_clk),

    .div        (tx_serial_divider)
);
clock_divider #(
//    .divide_by  (rx_serial_divider),
    .divide_by_param (0)
)
rx_toserialclk_div(
    .clk_in     (rx_phy_clk),
    .clk_out    (rx_sipo_clk),

    .div        (rx_serial_divider)
);

// TXOUTCLKPCS/TXOUTCLKPMA generation
wire    tx_pma_div1_clk;
assign  TXOUTCLKPCS = TXOUTCLKPMA;

clock_divider #(
    .divide_by (tx_pma_divider1)
)
tx_pma_div1(
    .clk_in     (tx_piso_clk),
    .clk_out    (tx_pma_div1_clk)
);

clock_divider #(
    .divide_by (tx_pma_divider2)
)
tx_pma_div2(
    .clk_in     (tx_pma_div1_clk),
    .clk_out    (TXOUTCLKPMA)
);

// RXOUTCLKPCS/RXOUTCLKPMA generation
wire    rx_pma_div1_clk;
assign  RXOUTCLKPCS = RXOUTCLKPMA;
clock_divider #(
    .divide_by  (rx_pma_divider1)
)
rx_pma_div1(
    .clk_in     (rx_sipo_clk),
    .clk_out    (rx_pma_div1_clk)
);

clock_divider #(
    .divide_by  (rx_pma_divider2)
)
rx_pma_div2(
    .clk_in     (rx_pma_div1_clk),
    .clk_out    (RXOUTCLKPMA)
);

//
clock_divider #(
    .divide_by  (2)
)
txpllrefclk_div2(
    .clk_in     (TXPLLREFCLK_DIV1),
    .clk_out    (TXPLLREFCLK_DIV2)
);
clock_divider #(
    .divide_by  (2)
)
rxpllrefclk_div2(
    .clk_in     (RXPLLREFCLK_DIV1),
    .clk_out    (RXPLLREFCLK_DIV2)
);

gtxe2_chnl_outclk_mux tx_out_mux(
    .TXPLLREFCLK_DIV1  (TXPLLREFCLK_DIV1),
    .TXPLLREFCLK_DIV2  (TXPLLREFCLK_DIV2),
    .TXOUTCLKPMA       (TXOUTCLKPMA),
    .TXOUTCLKPCS       (TXOUTCLKPCS),
    .TXOUTCLKSEL       (TXOUTCLKSEL),
    .TXDLYBYPASS       (TXDLYBYPASS),
    .TXOUTCLK          (TXOUTCLK)
);

gtxe2_chnl_outclk_mux rx_out_mux(
    .TXPLLREFCLK_DIV1  (RXPLLREFCLK_DIV1),
    .TXPLLREFCLK_DIV2  (RXPLLREFCLK_DIV2),
    .TXOUTCLKPMA       (RXOUTCLKPMA),
    .TXOUTCLKPCS       (RXOUTCLKPCS),
    .TXOUTCLKSEL       (RXOUTCLKSEL),
    .TXDLYBYPASS       (RXDLYBYPASS),
    .TXOUTCLK          (RXOUTCLK)
);


gtxe2_chnl_cpll_inmux clk_mux(
    .CPLLREFCLKSEL      (CPLLREFCLKSEL),

    .GTREFCLK0          (GTREFCLK0),
    .GTREFCLK1          (GTREFCLK1),
    .GTNORTHREFCLK0     (GTNORTHREFCLK0),
    .GTNORTHREFCLK1     (GTNORTHREFCLK1),
    .GTSOUTHREFCLK0     (GTSOUTHREFCLK0),
    .GTSOUTHREFCLK1     (GTSOUTHREFCLK1),
    .GTGREFCLK          (GTGREFCLK),

    .CPLL_MUX_CLK_OUT   (clk_mux_out)
);

gtxe2_chnl_cpll #(
    .CPLL_FBDIV      (4),
    .CPLL_FBDIV_45   (5),
    .CPLL_REFCLK_DIV (1)
)
cpll(
    .CPLLLOCKDETCLK     (CPLLLOCKDETCLK),
    .CPLLLOCKEN         (CPLLLOCKEN),
    .CPLLPD             (CPLLPD),
    .CPLLRESET          (CPLLRESET),
    .CPLLFBCLKLOST      (CPLLFBCLKLOST),
    .CPLLLOCK           (CPLLLOCK),
    .CPLLREFCLKLOST     (CPLLREFCLKLOST),
    
    .GTRSVD             (GTRSVD),
    .PCSRSVDIN          (PCSRSVDIN),
    .PCSRSVDIN2         (PCSRSVDIN2),
    .PMARSVDIN          (PMARSVDIN),
    .PMARSVDIN2         (PMARSVDIN2),
    .TSTIN              (TSTIN),
    .TSTOUT             (TSTOUT),
    
    .ref_clk            (clk_mux_out),
    .clk_out            (cpll_clk_out),
    .pll_locked         (pll_locked)
);

endmodule
+122 −0
Original line number Diff line number Diff line
`include "gtxe2_chnl_cpll_def.v"
module gtxe2_chnl_cpll(
// top-level interfaces
    input   wire    CPLLLOCKDETCLK,
    input   wire    CPLLLOCKEN,
    input   wire    CPLLPD,
    input   wire    CPLLRESET,  // active high
    output  wire    CPLLFBCLKLOST,
    output  wire    CPLLLOCK,
    output  wire    CPLLREFCLKLOST,

    input   wire    GTRSVD,
    input   wire    PCSRSVDIN,
    input   wire    PCSRSVDIN2,
    input   wire    PMARSVDIN,
    input   wire    PMARSVDIN2,
    input   wire    TSTIN,
    output  wire    TSTOUT,

// internal
    input   wire    ref_clk,
    output  wire    clk_out,
    output  wire    pll_locked // equals CPLLLOCK
);

parameter   [23:0]  CPLL_CFG        = 29'h00BC07DC;
parameter   integer CPLL_FBDIV      = 4;
parameter   integer CPLL_FBDIV_45   = 5;
parameter   [23:0]  CPLL_INIT_CFG   = 24'h00001E;
parameter   [15:0]  CPLL_LOCK_CFG   = 16'h01E8;
parameter   integer CPLL_REFCLK_DIV = 1;
parameter   integer RXOUT_DIV       = 2;
parameter   integer TXOUT_DIV       = 2;
parameter           SATA_CPLL_CFG = "VCO_3000MHZ";
parameter   [1:0]   PMA_RSV3        = 1;

localparam          multiplier  = CPLL_FBDIV * CPLL_FBDIV_45;
localparam          divider     = CPLL_REFCLK_DIV;

assign  pll_locked = locked;
assign  CPLLLOCK = pll_locked;

wire    fb_clk_out;
wire    reset;
reg     mult_clk;
reg     mult_dev_clk;

assign  clk_out = mult_dev_clk;

// generate internal async reset
assign reset = CPLLPD | CPLLRESET;

// apply multipliers
time    last_edge;  // reference clock edge's absolute time
time    period;     // reference clock's period
integer locked_f;
reg     locked;

initial 
begin
    last_edge = 0;
    period = 0;
    forever @ (posedge ref_clk or posedge reset)
    begin
        period      = reset ? 0 : $time - (last_edge == 0 ? $time : last_edge);
        last_edge   = reset ? 0 : $time;
    end
end
reg tmp = 0;
initial
begin
    @ (posedge reset);
    forever @ (posedge ref_clk)
    begin
        tmp = ~tmp;
        if (period > 0)
        begin
            locked_f = 1;
            mult_clk = 1'b1;
            repeat (multiplier * 2 - 1)
            begin
                #(period/multiplier/2) 
                mult_clk = ~mult_clk;
            end
        end
        else
            locked_f = 0;
    end
end

// apply dividers
initial
begin
    mult_dev_clk = 1'b1;
    forever
    begin
        repeat (divider)
            @ (mult_clk);
        mult_dev_clk = ~mult_dev_clk;
    end
end

// show if 'pll' is locked
reg [31:0]  counter;
always @ (posedge ref_clk or posedge reset)
    counter <= reset | locked_f == 0 ? 0 : counter == `GTXE2_CHNL_CPLL_LOCK_TIME ? counter : counter + 1;

always @ (posedge ref_clk)
    locked <= counter == `GTXE2_CHNL_CPLL_LOCK_TIME;
/*
always @ (posedge ref_clk or posedge reset)
begin
    if (locked_f == 1 && ~reset)
    begin
        repeat (`GTXE2_CHNL_CPLL_LOCK_TIME) @ (posedge ref_clk);
        locked <= 1'b1;
    end
    else
        locked <= 1'b0;
end*/

endmodule
Loading