AR# 55479

CPRI v6.1、7 シリーズ - プロダクション GTP トランシーバーのリセット ロジックに必要な GT アップデートと GTP/GTX および GTH トランシーバーでの TX バッファーのバイパス

説明

CPRI コアのバージョン 6.1 は、最新のトランシーバー設定でリリースされていますが、Artix-7 FPGA のデザイン アドバイザリのマスター アンサー (ザイリンクス アンサー 51456) に説明されているすべてのアップデートが適用されていることを確認してください。

ソリューション

TX 同期コントローラーの変更

(ザイリンクス アンサー 55009) に、CPRI コアのバージョン 6.1 にはない位相アライメントのインプリメンテーションに必要な変更が説明されています。このため、GTP トランシーバーを使用するデザインでは、次の手順に従います。

手順 1

CORE Generator ツールにある 7 Series FPGAs Transceivers Wizard のバージョン 2.5 を開き、プロトコル テンプレートを CPRI に設定してコアを生成します。生成したら、gtwizard_v2_5_tx_manual_phase_align.vhd ファイルを gtwizard_v2_5/example_design ディレクトリから CPRI コアの example_design/gtp_and_clocks/gtp ディレクトリにコピーします。 このファイルとファイル内にあるエンティティとアーキテクチャの名前を <component_name>_tx_sync.vhd に変更します。 gtwizard_v2_5_sync_block.vhd ファイルと gtwizard_v2_5_sync_pulse ファイルをコピーし、ISE プロジェクトまたはインプリメンテーションおよびシミュレーション スクリプト ファイルに追加します。

手順 2

手動 TX 位相アライメント ブロックを CPRI コア ラッパー ファイルに含めます。これを実行するには、CPRI コア ファイルである example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd に次の変更を加えます。

cpri_v6_1_tx_sync コンポーネントを削除し、手動 TX 位相アライメント ファイルのコンポート宣言に置き換えます。

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;

手順 3

位相アライメント ブロック (tx_sync_i) のインスタンシエーションも変更します。これを実行するには、<component_name>_gt_and_clocks.vhd ファイルの「TX Buffer Bypass Logic」というセクションを次のように変更します。

--------------------------- 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);

変更は、RX Buffer Bypass Logic で始まるセクションで終了です。

手順 4

ファイルで次の信号を宣言します。

  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;

手順 5

このファイルで位相アライメント ブロックの DONE 出力を tx_sync_rst signal の生成に追加します。

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

手順 6

TXSYNC_OVRD トランシーバー パラメーターを 1 に設定して (ザイリンクス アンサー 55009) の変更を完了します。これは example_design/gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd ファイルで設定します。

TXSYNC_OVRD_IN         => ('1'),


RX リセット シーケンスの変更

(ザイリンクス アンサー 53561) に、GTP トランシーバーを使用するデザインのレシーバー リセット プロセスの変更が説明されています。この変更は、CPRI コアのバージョン 6.1 にはありません。2013 年 1 月にリリースされた CPRI コアのバージョン 7.0 にアップグレードすることをお勧めします。
バージョン 7.0 にアップグレードできない場合は、次の手順で説明されているステート マシンを example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd ファイルに追加すると、必要な変更をバージョン 6.1 の GTP デザインに追加できます。

手順 1

example_design/gtp_and_clocks/<component_name>_gt_and_clocks.vhd ファイルで次の行を見つけます。

  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;

これを次のコードに置き換えます。

  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_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);

手順 2

ファイルで、次の信号とコンポーネントを宣言します。

  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_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;

手順 3

新しいステート マシンには、トランシーバーからの RXPMARESETDONE 信号を使用する必要があります。これをトランシーバーのラッパー ファイル外に配線します。

RXPMARESETDONE 信号は、gtp_and_clocks/gtp/<component_name>_v7_gtwizard_gt.vhd ファイルのトランシーバーの出力です。これをこのファイル外に gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd ファイルを介して配線します。 gtp_and_clocks/gtp/<component_name>_v7_gtwizard.vhd ファイルの出力が gtp_and_clocks/<component_name>_gt_and_clocks.vhd ファイル内にある rxpmaresetdone 信号に接続されます。

手順 4

ステート マシンは、リセット シーケンス中に DRP バスを使用してトランシーバーを設定します。これによってステート マシンとの間に競合が生じ、速度変更操作中にトランシーバー設定が変更されます。2 つのステート マシン間を正しくアービトレーションするには、次のように変更します。
gtp_and_clocks/<component_name>_gt_and_clocks.vhd ファイル内で speed_change_det ステート マシンを検索します。リセット ステート マシンでリセットされるように speed_select_r 信号を変更します。

  -- 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;

手順 5

speed_change_sm ステート マシンを、新しいリセット ステート マシンがビジーになったときにリセットされるように変更します。speed_change_sm process を検索し、次のリセットを変更します。

if (reset = '1') then

次のように変更します。

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

手順 6

新規の gt_reset_i 信号が生成されます。gtp_and_clocks/<component_name>_gt_and_clocks.vhd ファイルに次のコードを追加します。

  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_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;

手順 7

2 つのステート マシンからのマルチプレクサーを介する出力信号をトランシーバーのラッパーに配線します。ファイルの Channel Dynamic Reconfiguration Port (DRP) で始まるセクションを、次のように変更します。

        ---------------- 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,

手順 8

このファイルへの変更を完了するには、新規ステート マシンの BUSY 出力を CDR ロック カウンター、drp_arb_gnt および gt_daddr 信号の生成に配線します。

   --------------------------- 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';

手順 9

example_design/gtx_and_clocks/<component_name>_watchdog.vhd ファイルで CPRI ウォッチドッグ タイマーのタイムアウトを増加させます。 リセット シーケンスが長くなっているので、低ライン速度では完了前にタイムアウトする可能性があります。

現在のコードでは、125MHz の補助クロックを使用してウォッチドッグ タイマーを駆動すると想定されています。タイマーは 20 ビットのカウンターで、約 4ms 後にタイムアウトします。カウンターを 24 ビットに増加し、64 ms でタイムアウトするようにすることが推奨されます。これには、WDOG_COUNT_SIZE 定数を 24 に変更します。

手順 10

GTP ベースのコアの場合、上記の変更のほかに、次の属性を正しく設定する必要があります。

PMA_RSV2 =x00002040 (GTP チャネル)
BIAS_CFG =x"0000000000050001" (GTP 共通)

修正したデザインを正しくシミュレーションするためには、SIM_GTRESET_SPEEDUP パラメーターを false に設定する必要があります。

AR# 55479
日付 04/30/2013
ステータス アーカイブ
種類 一般
デバイス
IP