UPGRADE YOUR BROWSER

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# 55478

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

Description

It is recommended that users update to version 7.0 of the CPRI core, released in 2013.1. If this is not possible, the user should follow the steps detailed in this answer record to ensure proper transceiver operation using version 6.1 of the CPRI core.

Version 6.1 of the CPRI core is released with the latest transceiver settings. However, please ensure that any updates detailed in the device advisory master answer record (Xilinx Answer 42944) have been applied.

Solution

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 GTH 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/gtx_and_clocks/gtx 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/gtx_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 headed 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 headed 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/gtx_and_clocks/gtx/component_name_v7_gtwizard.vhd file:

TXSYNC_OVRD_IN         => ('1'),

RX Reset Sequence Change

(Xilinx Answer 53779) describes changes to the receiver reset process for designs using GTH 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 may be added into version 6.1 GTP designs by adding the suggested state machine described in the following steps into the example_design/gtx_and_clocks/component_name_gt_and_clocks.vhd file.

Step 1

First, the following lines in the example_design/gtx_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:

  -- Full GTX Tx/Rx reset initiated by external reset or speed switch
  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)
  begin
    if rising_edge(aux_clk) then
      if (reset = '1') then
        reset_sm_state <= idle;
      else
        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 = '1') then
              reset_rdata <= gt_do;
              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(15 downto 12) & '0' & gt_do(10 downto 0);
            reset_sm_state <= wait_for_11_rdy;
          when wait_for_11_rdy =>
            reset_den        <= '0';
            reset_dwe        <= '0';
            if (gt_drdy = '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 = '1') then
              reset_rdata <= gt_do;
              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(15 downto 12) & '1' & gt_do(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 = '1') then
              reset_sm_state <= idle;
            end if;
        end case;
      end if;
    end if;
  end process;
  -- Mux together the DRP input signals
  gt_den_gth               <= reset_den when reset_sm_busy = '1' else gt_den;
  gt_dwe_gth               <= reset_dwe when reset_sm_busy = '1' else gt_dwe;
  gt_di_gth                <= reset_di when reset_sm_busy = '1' else gt_di;
  gt_daddr_gth(7 downto 0) <= reset_daddr(7 downto 0) when reset_sm_busy = '1' else gt_daddr(7 downto 0);
  gt_daddr_gth(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,
                         wait_for_gtxrxreset_i_low,
                         wait_for_pmaresetdone_high,
                         wait_for_pmaresetdone_low,
                         read_11_2, wait_for_11r_rdy_2, write_11_2,
                         wait_for_11_rdy_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_gth         : std_logic;
  signal gt_dwe_gth         : std_logic;
  signal gt_di_gth          : std_logic_vector(15 downto 0);
  signal gt_daddr_gth       : 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 gtx_and_clocks/gtx/component_name_v7_gtwizard_gt.vhd file. This should be routed out of this file and through the gtx_and_clocks/gtx/component_name_v7_gtwizard.vhd file. The output from the gtx_and_clocks/gtx/component_name_v7_gtwizard.vhd file should then be connected to the rxpmaresetdone signal in  the gtx_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 two state machines, the following change is required:

Search for the speed_change_det state machine in the gtx_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)
  begin
    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

to

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

Step 6

The assignment to gt_addr(7 downto 0) in the IDLE state of the speed_change_sm state machine should be changed to:
if gt_drp_addr = x"4E" then
  gt_daddr(7 downto 0) <= x"50";
else
  gt_daddr(7 downto 0) <= gt_drp_daddr;
end if;
Step 7
A new gt_reset_i signal should be generated. Add the following code into the gtx_and_clocks/component_name_gt_and_clocks.vhd file:
  gt_reset_req_sm :  process(aux_clk)
  begin
    if rising_edge(aux_clk) then
      if (reset = '1' or reset_sm_busy = '1') then
        gt_reset_req_i <= '0';
      else
        case speed_sm_state is
          when idle => gt_reset_req_i <= '0';
          when wait_for_mmcm_upper_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 8

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

        ---------------- Channel - Dynamic Reconfiguration Port (DRP) --------------
        GT0_DRPADDR_IN                  =>      gt_daddr_gth,
        GT0_DRPCLK_IN                   =>      aux_clk,
        GT0_DRPDI_IN                    =>      gt_di_gth,
        GT0_DRPDO_OUT                   =>      gt_do,
        GT0_DRPEN_IN                    =>      gt_den_gth,
        GT0_DRPRDY_OUT                  =>      gt_drdy,
        GT0_DRPWE_IN                    =>      gt_dwe_gth,

Step 9

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)
   begin
       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;
           else
              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 10

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 may timeout before completion at low line rates. The current code presumes a 125 MHz auxiliary clock is used to drive the watchdog timer. The timer is a 20-bit counter giving a timeout after approximately 4 ms. It is suggested that the counter be increased to 24 bits to give a timeout of 64 ms. To do this, change the WDOG_COUNT_SIZE constant to 24.

 It should be noted that the SIM_GTRESET_SPEEDUP parameter must be set to false for correct simulation of the modified design. In addition, the UNIFAST models are not supported.

AR# 55478
Date Created 04/10/2013
Last Updated 05/09/2013
Status Active
Type General Article
Devices
  • Virtex-7
IP
  • CPRI