We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 55479

CPRI v6.1, 7 Series - Required GT updates for production GTP transceiver reset logic and TX buffer bypass on GTP/GTX and GTH transceivers


Version 6.1 of the CPRI core is released with the latest transceiver settings. However, please ensure that any updates detailed in the Design Advisory Master Answer Record for Artix-7 FPGA (Xilinx Answer 51456) have been applied.


TX Sync Controller Change

(Xilinx Answer 55009) describes a required change to the phase alignment implementation that is not present in version 6.1 of the CPRI core. As a result of this, the following steps must be followed for designs using GTP transceivers.

Step 1

The user should first open version 2.5 of the 7 series FPGAs Transceiver Wizard core in the CORE Generator tool and generate the core with the protocol template set to CPRI. After generation, the user should copy the gtwizard_v2_5_tx_manual_phase_align.vhd file from the gtwizard_v2_5/example_design directory into the example_design/gtp_and_clocks/gtp directory of the CPRI core. This file, and the entity and architecture present in it, should be renamed <component_name>_tx_sync.vhd. In addition, the gtwizard_v2_5_sync_block.vhd and gtwizard_v2_5_sync_pulse files should be copied and added to the ISE project or implementation and simulation script files.

Step 2

The user should then include the manual TX phase alignment block in the CPRI core wrapper files. To do this, edit the CPRI core file example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd to make the following changes:

Remove the cpri_v6_1_tx_sync component and replace it with the component declaration for the manual phase alignment file:

component <component_name>_tx_sync
  Generic( NUMBER_OF_LANES          : integer range 1 to 32:= 4; 
           MASTER_LANE_ID           : integer range 0 to 31:= 0  
    Port ( STABLE_CLOCK             : in  STD_LOGIC;             
           RESET_PHALIGNMENT        : in  STD_LOGIC;
           RUN_PHALIGNMENT          : in  STD_LOGIC;
           PHASE_ALIGNMENT_DONE     : out STD_LOGIC := '0';
           TXDLYSRESET              : out STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0) := (others=> '0');
           TXDLYSRESETDONE          : in  STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0);
           TXPHINIT                 : out STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0) := (others=> '0');
           TXPHINITDONE             : in  STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0);
           TXPHALIGN                : out STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0) := (others=> '0');
           TXPHALIGNDONE            : in  STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0);
           TXDLYEN                  : out STD_LOGIC_VECTOR(NUMBER_OF_LANES-1 downto 0) := (others=> '0')
end component;

Step 3

The instantiation of the phase alignment block (tx_sync_i) should also be changed. To do this, the section of the <component_name>_gt_and_clocks.vhd file entitled "TX Buffer Bypass Logic" should be changed to:

--------------------------- TX Buffer Bypass Logic --------------------
    -- The TX SYNC Module drives the ports needed to Bypass the TX Buffer.
    -- Include the TX SYNC module in your own design if TX Buffer is bypassed.
    txphdlyreset        <=  '0';
    txphalignen         <=  '1';
    txsyncallin         <=  txphaligndone;
    txsyncin            <=  txsyncout;
    txsyncmode          <=  '1';
    tx_sync_i : <component_name>_tx_sync
    generic map
    ( NUMBER_OF_LANES        =>  1,
      MASTER_LANE_ID       =>  0
    port map
        STABLE_CLOCK                    =>      aux_clk,
        RESET_PHALIGNMENT               =>      reset_phalignment,
        RUN_PHALIGNMENT                 =>      '1',
        PHASE_ALIGNMENT_DONE            =>      phase_alignment_done,
        TXDLYSRESET                     =>      txdlysreset_vec,
        TXDLYSRESETDONE                 =>      txdlysresetdone_vec,
        TXPHINIT                        =>      txphinit_vec,
        TXPHINITDONE                    =>      txphinitdone_vec,
        TXPHALIGN                       =>      txphalign_vec,
        TXPHALIGNDONE                   =>      txphaligndone_vec,
        TXDLYEN                         =>      txdlyen_vec
   txdlysreset            <= txdlysreset_vec(0);
   txdlysresetdone_vec(0) <= txdlysresetdone;
   txphinit               <= txphinit_vec(0);
   txphalign              <= txphalign_vec(0);
   txphaligndone_vec(0)   <= txphaligndone;
   txdlyen                <= txdlyen_vec(0);
   txphinitdone_vec(0)    <= txphinitdone;
   reset_phalignment <= not (tx_clk_ok and txresetdone);

The changes end at the section entitled "RX Buffer Bypass Logic".

Step 4

The following signals should be declared in the file:

  signal txdlysreset_vec          : std_logic_vector(0 downto 0);
  signal txdlysresetdone_vec      : std_logic_vector(0 downto 0);
  signal txphinit_vec             : std_logic_vector(0 downto 0);
  signal txphinitdone_vec         : std_logic_vector(0 downto 0);
  signal txphalign_vec            : std_logic_vector(0 downto 0);
  signal txphaligndone_vec        : std_logic_vector(0 downto 0);
  signal txdlyen_vec              : std_logic_vector(0 downto 0);
  signal phase_alignment_done     : std_logic;
  signal reset_phalignment        : std_logic;

Step 5

Finally, in this file, the DONE output of the phase alignment block should be added into the generation of the tx_sync_rst signal:

tx_sync_rst <= not (tx_clk_ok and txresetdone and phase_alignment_done);

Step 6

To complete the changes for (Xilinx Answer 55009), the TXSYNC_OVRD transceiver parameter should be set to 1. This is set in the example_design/gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd file:

TXSYNC_OVRD_IN         => ('1'),

RX Reset Sequence Change

(Xilinx Answer 53561) describes changes to the receiver reset process for designs using GTP transceivers. These changes are not present in version 6.1 of the CPRI core. It is recommended that customers upgrade to version 7.0 of the CPRI core released in 2013.1.
If it is not possible to upgrade to version 7.0 the required changes can be added into version 6.1 GTP designs by adding the suggested state machine described in the following steps into the example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd file.

Step 1

First, the following lines in the example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd file:

  gtxtxreset <= (rst_count_done and (reset or gt_reset_req or not(rxplllkdet))) or watchdog_reset;
  gtxrxreset <= (rst_count_done and (reset or gt_reset_req or not(rxplllkdet))) or watchdog_reset;

should be replaced with the following code:

  gtxtxreset <= (rst_count_done and (reset or gt_reset_req_i or not(rxplllkdet))) or watchdog_reset;
  gtxrxreset_i <= (rst_count_done and (reset or gt_reset_req_i or not(rxplllkdet))) or watchdog_reset;
  -- Synchronize reset signal to state machine clock
  rx_sync_reset_sync_rsm_i : <component_name>_reset_synchronizer
  port map (
    reset_in  => gtxrxreset_i,
    clk       => aux_clk,
    reset_out => gtxrxreset_r
  -- Synchronize the rxpmaresetdone signal into the state machine clock
  -- domain
  rxpmaresetdone_sync_rsm_i : <component_name>_synchronizer
  port map (
      q     => rxpmaresetdone_r,
      clk   => aux_clk,
      reset => reset,
      d     => rxpmaresetdone);
  -- State machine to perform internal data width change in response to
  -- a user reset
  reset_change_sm : process(aux_clk)
    if rising_edge(aux_clk) then
      if (reset = '1') then
        reset_sm_state <= idle;
        case reset_sm_state is
          when idle =>
            gtxrxreset    <= '0';
            reset_sm_busy <= '0';
            reset_daddr(7 downto 0) <= (others => '0');
            reset_den               <= '0';
            reset_dwe               <= '0';
            reset_di                <= (others => '0');
            if (gtxrxreset_r = '1') then
              reset_sm_state <= wait_for_speed_sm;
            end if;
          when wait_for_speed_sm =>
            if (sm_busy = '0') then
              reset_sm_state <= read_11;
              reset_sm_busy <= '1';
            end if;
          when read_11 =>
            gtxrxreset    <= '1';
            reset_daddr(7 downto 0) <= x"11";
            reset_den        <= '1';
            reset_dwe        <= '0';
            reset_sm_state <= wait_for_11r_rdy;
          when wait_for_11r_rdy =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gt_drdy_channel = '1') then
              reset_rdata <= gt_do_channel;
              reset_sm_state <= write_11;
            end if;
          when write_11 =>
            reset_den        <= '1';
            reset_dwe        <= '1';
            -- 11 holds RX_DATA_WIDTH
            reset_di <= gt_do_channel(15 downto 14) & "010" & gt_do_channel(10 downto 0);
            reset_sm_state <= wait_for_11_rdy;
          when wait_for_11_rdy =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gt_drdy_channel = '1') then
              reset_sm_state <= wait_for_gtxrxreset_i_low;
            end if;
          when wait_for_gtxrxreset_i_low =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gtxrxreset_r = '0') then
              gtxrxreset <= '0';
              reset_sm_state <= wait_for_pmaresetdone_high;
            end if;
          when wait_for_pmaresetdone_high =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (rxpmaresetdone_r = '1') then
              reset_sm_state <= wait_for_pmaresetdone_low;
            end if;
          when wait_for_pmaresetdone_low =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (rxpmaresetdone_r = '0') then
              reset_sm_state <= read_11_2;
            end if;
          when read_11_2 =>
            reset_daddr(7 downto 0) <= x"11";
            reset_den        <= '1';
            reset_dwe        <= '0';
            reset_sm_state <= wait_for_11r_rdy_2;
          when wait_for_11r_rdy_2 =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gt_drdy_channel = '1') then
              reset_rdata <= gt_do_channel;
              reset_sm_state <= write_11_2;
            end if;
          when write_11_2 =>
            reset_den        <= '1';
            reset_dwe        <= '1';
            -- 11 holds RX_DATA_WIDTH
            reset_di <= gt_do_channel(15 downto 14) & "011" & gt_do_channel(10 downto 0);
            reset_sm_state <= wait_for_11_rdy_2;
                   when wait_for_11_rdy_2 =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gt_drdy_channel = '1') then
              reset_sm_state <= idle;
            end if;
        end case;
      end if;
    end if;
  end process;
  -- Mux together the DRP input signals
  gt_den_channel_gtp       <= reset_den when reset_sm_busy = '1' else gt_den_channel;
  gt_dwe_channel_gtp       <= reset_dwe when reset_sm_busy = '1' else gt_dwe_channel;
  gt_di_gtp                <= reset_di when reset_sm_busy = '1' else gt_di;
  gt_daddr_gtp(7 downto 0) <= reset_daddr(7 downto 0) when reset_sm_busy = '1' else gt_daddr(7 downto 0);
  gt_daddr_gtp(8)          <= gt_daddr(8);

Step 2

The following signals and components need to be declared in the file:

  signal gtxrxreset_i           : std_logic;
  signal gtxrxreset_r           : std_logic;
  signal rxpmaresetdone         : std_logic;
  signal rxpmaresetdone_r       : std_logic;
  type t_state_reset is (idle, wait_for_speed_sm,
                         read_11, wait_for_11r_rdy, write_11, wait_for_11_rdy,
                         read_11_2, wait_for_11r_rdy_2, write_11_2,
  signal reset_sm_state     : t_state_reset := idle;
  signal reset_sm_busy      : std_logic;
  signal reset_daddr        : std_logic_vector(7 downto 0);
  signal reset_den          : std_logic;
  signal reset_dwe          : std_logic;
  signal reset_di           : std_logic_vector(15 downto 0);
  signal reset_rdata        : std_logic_vector(15 downto 0);
  signal gt_den_channel_gtp : std_logic;
  signal gt_dwe_channel_gtp : std_logic;
  signal gt_di_gtp          : std_logic_vector(15 downto 0);
  signal gt_daddr_gtp       : std_logic_vector(8 downto 0);
  signal gt_reset_req_i     : std_logic;
  component <component_name>_synchronizer is
    port (
      q     : out std_logic;
      clk   : in  std_logic;
      reset : in  std_logic;
      d     : in  std_logic);
  end component;

Step 3

The new state machine requires the use of the RXPMARESETDONE signal from the transceiver. This should be routed out of the transceiver wrapper files.

The RXPMARESETDONE signal is an output of the transceiver in the gtp_and_clocks/gtp/<component_name>_v7_gtwizard_gt.vhd file. This should be routed out of this file and through the gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd file. This output from the gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd file should then be connected to the rxpmaresetdone signal in  the gtp_and_clocks/<component_name>_gt_and_clocks.vhd file.

Step 4

The state machine uses the DRP bus to set the transceiver during a reset sequence. This conflicts with the state machine to vary the transceiver settings during a speed change operation. To properly arbitrate between the 2 state machines, the following change is required to be made.
Search for the speed_change_det state machine in the gtp_and_clocks/<component_name>_gt_and_clocks.vhd file. Change the speed_select_r signal so that it is reset by the reset state machine:

  -- Small state machine to set the RXCDR_CFG setting in the transceiver
  -- This depends on the line rate that the link is operating at.
  -- Firstly detect a speed change.
  speed_change_det : process(aux_clk)
    if rising_edge(aux_clk) then
      if reset_sm_busy = '0' then - Reset changed
        speed_select_r <= speed_select;
      end if;
    end if;
  end process speed_change_det;

Step 5

The speed_change_sm state machine should be changed so that it is reset when the new reset state machine is busy. Search for the speed_change_sm process and change the reset from:

if (reset = '1') then


if (reset = '1' or reset_sm_busy = '1') then

Step 6

A new gt_reset_i signal should be generated. Add the following code into the gtp_and_clocks/<component_name>_gt_and_clocks.vhd file:

  gt_reset_req_sm :  process(aux_clk)
    if rising_edge(aux_clk) then
      if (reset = '1' or reset_sm_busy = '1') then
        gt_reset_req_i <= '0';
        case speed_sm_state is
          when idle => gt_reset_req_i <= '0';
          when wait_for_mmcm_divclk_rdy =>
            if (mmcm_drp_drdy = '1') then
              gt_reset_req_i <= '1';
            end if;
          when others =>
            gt_reset_req_i <= '0';
        end case;
      end if;
    end if;
  end process;

Step 7

The multiplexed output signals from the 2 state machines should be routed to the transceiver wrappers. The section of the file entitled "Channel Dynamic Reconfiguration Port (DRP)" should be changed to:

        ---------------- Channel - Dynamic Reconfiguration Port (DRP) --------------
        GT0_DRPADDR_IN                  =>      gt_daddr_gtp,
        GT0_DRPCLK_IN                   =>      aux_clk,
        GT0_DRPDI_IN                    =>      gt_di_gtp,
        GT0_DRPDO_OUT                   =>      gt_do_channel,
        GT0_DRPEN_IN                    =>      gt_den_channel_gtp,
        GT0_DRPRDY_OUT                  =>      gt_drdy_channel,
        GT0_DRPWE_IN                    =>      gt_dwe_channel_gtp,

Step 8

To complete the changes to this file, the BUSY output of the new state machine should be routed to the generation of the CDR lock counter, drp_arb_gnt and gt_daddr signals:

   --------------------------- RX Buffer Bypass Logic --------------------
   -- The RX SYNC Module drives the ports needed to Bypass the RX Buffer.
   -- Include the RX SYNC module in your own design if RX Buffer is bypassed.
   --Wait till CDR is locked to start RX Phase Alignment
   RX_CDRLOCK_TIME    <=   "00010000000000" when (WRAPPER_SIM_GTXRESET_SPEEDUP = 1)  else  "10011100010000";
   process( aux_clk, reset_sm_busy, gtxrxreset)
       if(gtxrxreset = '1' or reset_sm_busy = '1' ) then
           rx_cdrlock_counter    <=  (others => '0');
       elsif(aux_clk'event and aux_clk = '1') then
           if(rx_cdrlock_counter <= RX_CDRLOCK_TIME)  then
              rx_cdrlock_counter    <= rx_cdrlock_counter + 1;
              rx_cdrlock_counter    <= rx_cdrlock_counter;
           end if;
       end if;
   end process;
  -- Send a grant back to the core when the DRP is ready
  drp_arb_gnt <= drp_arb_req and not(sm_busy) and not(reset_sm_busy);
  -- Set top bit of DRP address high when we're accessing the barrel shift
  gt_daddr(8) <= '1' when (gt_drp_daddr(7 downto 0) = x"50"
                           and sm_busy = '0' and reset_sm_busy = '0') else '0';

Step 9

The user should increase the timeout of the CPRI watchdog timer in the example_design/gtx_and_clocks/<component_name>_watchdog.vhd file. As the length of the reset sequence is now longer, it might timeout before completion at low line rates.

The current code presumes a 125MHz auxiliary clock is used to drive the watchdog timer. The timer is a 20-bit counter giving a timeout after approximately 4ms. It is suggested that the counter be increased to 24-bits to give a timeout of 64ms. To do this, change the WDOG_COUNT_SIZE constant to 24.

Step 10

In addition to the required changes above, the following attributes must be set correctly for GTP based cores:

PMA_RSV2 =x00002040 (GTP Channel)
BIAS_CFG =x"0000000000050001" (GTP Common)

It should be noted that the SIM_GTRESET_SPEEDUP parameter must be set to "false" for correct simulation of the modified design.

AR# 55479
Date 04/17/2013
Status Archive
Type General Article
Page Bookmarked