OpenCores
URL https://opencores.org/ocsvn/pcie_sg_dma/pcie_sg_dma/trunk

Subversion Repositories pcie_sg_dma

[/] [pcie_sg_dma/] [branches/] [Virtex6/] [ML605_ISE12.3/] [pcie_sg_dma/] [Virtex6/] [ML605/] [v6_pcie_v1_3/] [source/] [gtx_tx_sync_rate_v6.v] - Rev 11

Compare with Previous | Blame | View Log

 
//-----------------------------------------------------------------------------
//
// (c) Copyright 2009 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.
//
// 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.
//
//-----------------------------------------------------------------------------
// Project    : Virtex-6 Integrated Block for PCI Express
// File       : gtx_tx_sync_rate_v6.v
//////////////////////////////////////////////////////////////////////////////
 
`timescale 1ns / 1ps
`define DLY #1
 
module GTX_TX_SYNC_RATE_V6
#(
    parameter           C_SIMULATION    = 0 // Set to 1 for simulation
)
(
    output              ENPMAPHASEALIGN,
    output              PMASETPHASE,
    output              SYNC_DONE,
    output              OUT_DIV_RESET,
    output              PCS_RESET,
    output              USER_PHYSTATUS,
    output              RATE_CLK_SEL,
    input               USER_CLK,
    input               RESET,
    input               RATE,
    input               RATEDONE,
    input               GT_PHYSTATUS,
    input               RESETDONE,
 
    // Test bits / status
    output      [53:0]  DEBUG_STATUS,
    input       [2:0]   ENPMA_STATE_MASK,
    input       [2:0]   OUTDIV_STATE_MASK
 
);
 
// synthesis attribute X_CORE_INFO of TX_SYNC is "v6_gtxwizard_v1_0, Coregen v11.1_ip1";
 
//*******************************Register Declarations************************
 
    reg           begin_r;
    reg           phase_align_r;
    reg           ready_r;
    reg   [15:0]  sync_counter_r;
    reg   [5:0]   count_32_cycles_r;
    reg           wait_stable_r;
    reg           phase_align_reset_r;
    reg           out_div_reset_r;
    reg           wait_phase_align_reset_r;
    reg           pcs_reset_r;
    reg           wait_reset_done_r;
    reg           gen_phystatus_r;
    reg           rate_r;
    reg           guard_r;
    reg           resetdone_r;
    reg           resetdone_r2;
    reg           ratedone_r;
    reg           ratedone_r2;
    reg           rate_sel_r;
 
    reg           enpmaphasealign_r;
    reg           reg_out_div_reset_r;
    reg   [24:0]  rate_duration_count_r;
 
 
//*******************************Wire Declarations****************************
 
    wire          count_setphase_complete_i;
    wire          count_32_complete_i;
    wire          next_phase_align_c;
    wire          next_ready_c;
    wire          next_wait_stable_c;
    wire          next_phase_align_reset_c;
    wire          next_out_div_reset_c;
    wire          next_wait_phase_align_reset_c;
    wire          next_pcs_reset_c;
    wire          next_wait_reset_done_c;
    wire          next_gen_phystatus_c;
    wire          ratedone_pulse_i;
 
    wire          enpmaphasealign_i;
    wire          out_div_reset_i;
 
//*******************************Main Body of Code****************************
 
 
 
 
    //________________________________ State machine __________________________
    // This state machine manages the phase alingment procedure of the GTX.
    // The module is held in reset till the usrclk source is stable.  In the 
    // case of buffer bypass where the refclkout is used to clock the usrclks,
    // the usrclk stable indication is given the pll_locked signal.
    // Once the pll_lock is asserted, state machine goes into the
    // wait_stable_r for 32 clock cycles to allow some time to ensure the pll
    // is stable. After this, it goes into the phase_align_r state where the
    // phase alignment procedure is executed. This involves asserting the
    // ENPMAPHASEALIGN and PMASETPHASE for 32768 clock cycles.
    //
    // If there is a line rate change, the module resets the output divider by
    // asserting the signal for 16 clock cycles and resets the phase alignment
    // block by de-asserting ENPMAPHASEALIGN signal for 16 clock cycles.  The
    // phase alignment procedure as stated above is repeated.  Afterwards, the
    // PCS is reset and a user PHYSTATUS is generated to notify the completion
    // of a line rate change procedure.
 
    // State registers
    always @(posedge USER_CLK)
        if(RESET)
            {begin_r, wait_stable_r, phase_align_r, ready_r,
             phase_align_reset_r, out_div_reset_r, wait_phase_align_reset_r,
             pcs_reset_r, wait_reset_done_r,
             gen_phystatus_r}  <=  `DLY 10'b10_0000_0000;
        else
        begin
            begin_r                   <=  `DLY  1'b0;
            wait_stable_r             <=  `DLY  next_wait_stable_c;
            phase_align_r             <=  `DLY  next_phase_align_c;
            ready_r                   <=  `DLY  next_ready_c;
            phase_align_reset_r       <=  `DLY  next_phase_align_reset_c;
            out_div_reset_r           <=  `DLY  next_out_div_reset_c;
            wait_phase_align_reset_r  <=  `DLY  next_wait_phase_align_reset_c;
            pcs_reset_r               <=  `DLY  next_pcs_reset_c;
            wait_reset_done_r         <=  `DLY  next_wait_reset_done_c;
            gen_phystatus_r           <=  `DLY  next_gen_phystatus_c;
        end
 
    // Next state logic
    assign next_ready_c              = (((phase_align_r & count_setphase_complete_i) & !guard_r) | gen_phystatus_r) |
                                      (!ratedone_pulse_i & ready_r);
 
    assign next_phase_align_reset_c = (ratedone_pulse_i & ready_r) | 
                                      (phase_align_reset_r & !count_32_complete_i);
 
    assign next_out_div_reset_c     = (phase_align_reset_r & count_32_complete_i)|
                                      (out_div_reset_r & !count_32_complete_i);
 
    assign next_wait_phase_align_reset_c = (out_div_reset_r & count_32_complete_i) | 
                                           (wait_phase_align_reset_r & !count_32_complete_i);
 
    assign next_wait_stable_c       = begin_r | (wait_phase_align_reset_r & count_32_complete_i) |
                                      (wait_stable_r & !count_32_complete_i);
 
    assign next_phase_align_c       = (wait_stable_r & count_32_complete_i) |
                                      (phase_align_r & !count_setphase_complete_i);
 
    assign next_pcs_reset_c         = ((phase_align_r & count_setphase_complete_i) & guard_r);
 
    assign next_wait_reset_done_c   = pcs_reset_r |
                                      (!resetdone_r2 & wait_reset_done_r);
 
    assign next_gen_phystatus_c     = resetdone_r2 & wait_reset_done_r;
 
 
        //_________ Counter for to wait for pll to be stable before sync __________
    always @(posedge USER_CLK)
    begin
        if (RESET || count_32_complete_i)
            count_32_cycles_r <= `DLY  6'b000000;
        else if (wait_stable_r || out_div_reset_r || phase_align_reset_r || wait_phase_align_reset_r)
            count_32_cycles_r <= `DLY  count_32_cycles_r + 1'b1;
    end
 
    assign count_32_complete_i = count_32_cycles_r[5];
 
    //_______________ Counter for holding SYNC for SYNC_CYCLES ________________
    always @(posedge USER_CLK)
    begin
        if (!phase_align_r)
            sync_counter_r <= `DLY  16'h0000;
        else
            sync_counter_r <= `DLY  sync_counter_r + 1'b1;
    end
 
    generate
        if (C_SIMULATION) begin: for_simulation
            // Shorten the cycle to 32 clock cycles for simulation
            assign count_setphase_complete_i = sync_counter_r[5];
        end
        else begin: for_hardware
            // For TXPMASETPHASE:
            //  - If RATE[0] = 0, PLL_DIVSEL_OUT = 2 => 16,384 USRCLK2 cycles
            //  - If RATE[0] = 1, PLL_DIVSEL_OUT = 1 => 8,192 USRCLK2 cycles
            assign count_setphase_complete_i = (rate_r) ? sync_counter_r[13] :
                                                          sync_counter_r[14];
        end
    endgenerate
 
 
    //_______________ Assign the phase align ports into the GTX _______________
 
    // Assert the ENPMAPHASEALIGN signal when the reset of this module
    // gets de-asserted and after a reset of the output dividers.  Disabling
    // this signal after reset of the output dividers will reset the phase
    // alignment module.
    //assign ENPMAPHASEALIGN = !(begin_r | phase_align_reset_r | out_div_reset_r | wait_phase_align_reset_r);
 
    // Masking the bits of each state to play around with the pulse of the
    // TXENPMAPHASEALIGN reset (active low signal)
    assign enpmaphasealign_i = ~((begin_r ||
                               (phase_align_reset_r && ENPMA_STATE_MASK[2]) ||
                               (out_div_reset_r && ENPMA_STATE_MASK[1]) || 
                               (wait_phase_align_reset_r && ENPMA_STATE_MASK[0])));
 
    always @(posedge USER_CLK)
        if (RESET)
            enpmaphasealign_r <= `DLY 1'b0;
        else
            enpmaphasealign_r <= enpmaphasealign_i;
 
    assign ENPMAPHASEALIGN = enpmaphasealign_r; 
 
    assign PMASETPHASE     = phase_align_r;
 
 
    //_______________________ Assign the sync_done port _______________________
 
    // Assert the SYNC_DONE signal when the phase alignment procedure is
    // complete after initialization and when line rate change procedure
    // is complete.
    assign SYNC_DONE = ready_r & !guard_r;
 
 
    //_______________________ Assign the rest of the ports ____________________
    // Assert the output divider reset for 32 USRCLK2 clock cycles
    //assign OUT_DIV_RESET = out_div_reset_r;
 
    // Masking the bits of each state to play around with the pulse of the
    // output divider reset
    assign out_div_reset_i= (phase_align_reset_r && OUTDIV_STATE_MASK[2]) ||
                           (out_div_reset_r && OUTDIV_STATE_MASK[1]) || 
                           (wait_phase_align_reset_r && OUTDIV_STATE_MASK[0]);
 
    always @(posedge USER_CLK)
        if (RESET)
            reg_out_div_reset_r <= `DLY 1'b0;
        else
            reg_out_div_reset_r <= out_div_reset_i;
 
    assign OUT_DIV_RESET = reg_out_div_reset_r;
 
    // Assert the PCS reset for 1 USRCLK2 clock cycle
    assign PCS_RESET = pcs_reset_r;
 
 
    // Assert user phystatus at the end of the line rate change.  It is also
    // a pass through signal from the GTX when the pulse is not associated
    // with a line rate change (in this module this signal is gated by
    // guard_r signal)
    assign USER_PHYSTATUS = gen_phystatus_r | (GT_PHYSTATUS & !guard_r);
 
 
    //////////////////////////////////////////////////////////////////////////
    // Register the RESETDONE input
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
 
    begin
        if (RESET | pcs_reset_r)
        begin
            resetdone_r   <= `DLY 1'b0;
            resetdone_r2  <= `DLY 1'b0;
        end
        else
        begin
            resetdone_r   <= `DLY RESETDONE;
            resetdone_r2  <= `DLY resetdone_r;
        end
    end
 
    //////////////////////////////////////////////////////////////////////////
    // Detect an edge on the RATEDONE signal and generate a pulse from it.
    // The RATEDONE signal by default is initialized to 1'b1.
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
 
    begin
        if (RESET)
        begin
            ratedone_r  <= `DLY 1'b0;
            ratedone_r2 <= `DLY 1'b0;
        end
        else
        begin
            ratedone_r  <= `DLY RATEDONE;
            ratedone_r2 <= `DLY ratedone_r;
        end
    end
 
    assign ratedone_pulse_i = ratedone_r & !ratedone_r2;
 
    //////////////////////////////////////////////////////////////////////////
    // Detect a line rate change.  Since this is targeted for PCIe, we only
    // need to detect a change on TXRATE[0]/RXRATE[0]:
    // TXRATE[1:0] / RXRATE[1:0] = 10 for output divider /2
    // TXRATE[1:0] / RXRATE[1:0] = 11 for output divider /1
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
    begin
        rate_r <= `DLY RATE;
    end
 
    assign rate_change_i = rate_r ^ RATE;
 
 
    //////////////////////////////////////////////////////////////////////////
    // Generate an internal "guard" signal to denote that the line rate
    // sequence of operation initiated.  This signal is driven High when the
    // there is a rate change trigger by a change in TXRATE or RXRATE ports.
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
    begin
        if (RESET | gen_phystatus_r)
            guard_r <= `DLY 1'b0;
        else if (rate_change_i == 1'b1)
            guard_r <= `DLY 1'b1;
    end
 
 
    //////////////////////////////////////////////////////////////////////////
    // Generate the BUFGMUX select signal that selects the correct clock to
    // used based on a rate change.  For PCIe:
    //  - RATE[0] = 0 => Use 125 MHz USRCLK2 with RATE_CLK_SEL = 0
    //  - RATE[0] = 1 => Use 250 MHz USRCLK2 with RATE_CLK_SEL = 1
    // The RATE_CLK_SEL changes based on the RATEDONE signal from the GTX.
    // The default of this pin is set to 1'b0.  Someone can change it to grab
    // the value from a parameter if the reset value has to be another value
    // other than 1'b0.
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
    begin
        if (RESET)
            rate_sel_r <= `DLY 1'b0;
        else if (ratedone_pulse_i == 1'b1)
            rate_sel_r <= `DLY rate_r;
    end
 
    assign RATE_CLK_SEL = rate_sel_r;
 
    //////////////////////////////////////////////////////////////////////////
    // Create a counter that starts when guard_r is High.  After
    // guard_r gets de-asserted, the counter stops counting.  The counter gets
    // reset when there is a rate change applied from the user; this rate
    // change pulse occurs one USER_CLK cycle earlier than guard_r.  
    //////////////////////////////////////////////////////////////////////////
    always @(posedge USER_CLK)
    begin
        if (RESET | rate_change_i)
            rate_duration_count_r <= `DLY 25'b0_0000_0000_0000_0000_0000_0000;
        else if (guard_r)
            rate_duration_count_r <= `DLY rate_duration_count_r + 1'b1;
        else
            rate_duration_count_r <= `DLY rate_duration_count_r;
    end
 
 
    //Monitoring the signals on ILa
    assign DEBUG_STATUS= {sync_counter_r[15:0],       //[53:38]
                          rate_r,                     //[37]
                          rate_duration_count_r[24:0],//[36:12]
                          begin_r,                    //[11]
                          wait_stable_r,              //[10]
                          phase_align_r,              //[9]
                          ready_r,                    //[8]
                          phase_align_reset_r,        //[7]
                          out_div_reset_r,            //[6]
                          wait_phase_align_reset_r,   //[5]
                          pcs_reset_r,                //[4]
                          wait_reset_done_r,          //[3]
                          gen_phystatus_r,            //[2]
                          guard_r,                    //[1]
                          rate_change_i};             //[0]
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.