GTX_IP核實現SMA口發送數據(3)GTX例程代碼詳細介紹


配置IP核生產的example文件代碼如下
各個代碼模塊的功能如下:

所以分為三個模塊進行介紹
gt_frame_gen通過讀取FPGA內部的ROM的數據來產生偽隨機碼
gt_frame_gen通過測驗相關的數據來觀察數據的正確
然后是support配置的介紹,主要代碼如下圖所示
時鍾端的基本知識介紹

以7系列的GTX來說,每個Quad有兩個外部差分參考時鍾源,其中一個Quad的時鍾結構如圖所示:

紅色方框部分是兩個差分參考時鍾輸入,每個外部參考時鍾的輸入必須經過IBUFDS_GTE2源語之后才能使用。綠色方框是來自其他Quad的參考時鍾輸入,7系列FPGA支持使用相鄰(南北方向)Quad的參考時鍾作為當前Quad的參考時鍾,多路參考時鍾源經過一個選擇器之后,分兩路進入QPLL和CPLL,其中藍色方框是QPLL,黃色方框是CPLL,對於一個GTX Channel來說,可以獨立選擇參考時鍾,可以選擇QPLL,也可以選擇CPLL,QPLL和CPLL的區別在於兩者支持的線速率不同,QPLL支持的線速率高於CPLL,圖是外部參考時鍾模型的詳細結構,紅色箭頭表示QPLL通路,黃色箭頭表示CPLL通路。
QPLL的內部多路選擇器如上圖,通過QPLLREFCLKSEL來控制輸入的時鍾,各個參數的具體的定義如下圖所示,
輸入端的定義:

輸出端的定義


代碼在gtx.common里面


同理,CPLL的配置不做詳細介紹,看手冊就好了。
關於進入TX或者RX端的時鍾是QPLL還是CPLL,交給TXSYSCLKSEL寄存器來實現,當其選擇為1的時候,QPLL進入,如下圖所示。
動態改變方式:
下面進行代碼及各個參數的詳細講解:
第一個講解的代碼如下(gtx_common.v):
`default_nettype wire

`timescale 1ns / 1ps
`define DLY #1
//***************************** Entity Declaration ****************************
module gtx_common #
(
    // Simulation attributes
    parameter   WRAPPER_SIM_GTRESET_SPEEDUP    =   "TRUE",     // Set to "true" to speed up sim reset
    parameter   SIM_QPLLREFCLK_SEL             =   3'b001     
)
(
    input   [2:0]   QPLLREFCLKSEL_IN,
    input           GTREFCLK0_IN,
    input           GTREFCLK1_IN,
    output          QPLLLOCK_OUT,
    input           QPLLLOCKDETCLK_IN,
    output          QPLLOUTCLK_OUT,
    output          QPLLOUTREFCLK_OUT,
    output          QPLLREFCLKLOST_OUT,   
    input           QPLLRESET_IN
);



//***************************** Parameter Declarations ************************
    localparam QPLL_FBDIV_TOP =  40;

    localparam QPLL_FBDIV_IN  =  (QPLL_FBDIV_TOP == 16)  ? 10'b0000100000 : 
				(QPLL_FBDIV_TOP == 20)  ? 10'b0000110000 :
				(QPLL_FBDIV_TOP == 32)  ? 10'b0001100000 :
				(QPLL_FBDIV_TOP == 40)  ? 10'b0010000000 :
				(QPLL_FBDIV_TOP == 64)  ? 10'b0011100000 :
				(QPLL_FBDIV_TOP == 66)  ? 10'b0101000000 :
				(QPLL_FBDIV_TOP == 80)  ? 10'b0100100000 :
				(QPLL_FBDIV_TOP == 100) ? 10'b0101110000 : 10'b0000000000;

   localparam QPLL_FBDIV_RATIO = (QPLL_FBDIV_TOP == 16)  ? 1'b1 : 
				(QPLL_FBDIV_TOP == 20)  ? 1'b1 :
				(QPLL_FBDIV_TOP == 32)  ? 1'b1 :
				(QPLL_FBDIV_TOP == 40)  ? 1'b1 :
				(QPLL_FBDIV_TOP == 64)  ? 1'b1 :
				(QPLL_FBDIV_TOP == 66)  ? 1'b0 :
				(QPLL_FBDIV_TOP == 80)  ? 1'b1 :
				(QPLL_FBDIV_TOP == 100) ? 1'b1 : 1'b1;

    // ground and vcc signals
wire            tied_to_ground_i;
wire    [63:0]  tied_to_ground_vec_i;
wire            tied_to_vcc_i;
wire    [63:0]  tied_to_vcc_vec_i;

    assign tied_to_ground_i             = 1'b0;
    assign tied_to_ground_vec_i         = 64'h0000000000000000;
    assign tied_to_vcc_i                = 1'b1;
    assign tied_to_vcc_vec_i            = 64'hffffffffffffffff;//高低電平

    //_________________________________________________________________________
    //_________________________________________________________________________
    //_________________________GTXE2_COMMON____________________________________

    GTXE2_COMMON #
    (
            // Simulation attributes
            .SIM_RESET_SPEEDUP   (WRAPPER_SIM_GTRESET_SPEEDUP),
            .SIM_QPLLREFCLK_SEL  (SIM_QPLLREFCLK_SEL),
            .SIM_VERSION         ("4.0"),


           //----------------COMMON BLOCK Attributes---------------
            .BIAS_CFG                               (64'h0000040000001000),
            .COMMON_CFG                             (32'h00000000),
            .QPLL_CFG                               (27'h06801C1),
            .QPLL_CLKOUT_CFG                        (4'b0000),
            .QPLL_COARSE_FREQ_OVRD                  (6'b010000),
            .QPLL_COARSE_FREQ_OVRD_EN               (1'b0),
            .QPLL_CP                                (10'b0000011111),
            .QPLL_CP_MONITOR_EN                     (1'b0),
            .QPLL_DMONITOR_SEL                      (1'b0),
            .QPLL_FBDIV                             (QPLL_FBDIV_IN),
            .QPLL_FBDIV_MONITOR_EN                  (1'b0),
            .QPLL_FBDIV_RATIO                       (QPLL_FBDIV_RATIO),
            .QPLL_INIT_CFG                          (24'h000006),
            .QPLL_LOCK_CFG                          (16'h21E8),
            .QPLL_LPF                               (4'b1111),
            .QPLL_REFCLK_DIV                        (1)

    )
    gtxe2_common_i
    (
        //----------- Common Block  - Dynamic Reconfiguration Port (DRP) -----------
        .DRPADDR                        (tied_to_ground_vec_i[7:0]),
        .DRPCLK                         (tied_to_ground_i),
        .DRPDI                          (tied_to_ground_vec_i[15:0]),
        .DRPDO                          (),
        .DRPEN                          (tied_to_ground_i),
        .DRPRDY                         (),
        .DRPWE                          (tied_to_ground_i),
        //-------------------- Common Block  - Ref Clock Ports ---------------------
        .GTGREFCLK                      (tied_to_ground_i),
        .GTNORTHREFCLK0                 (tied_to_ground_i),
        .GTNORTHREFCLK1                 (tied_to_ground_i),
        .GTREFCLK0                      (GTREFCLK0_IN),
        .GTREFCLK1                      (GTREFCLK1_IN),
        .GTSOUTHREFCLK0                 (tied_to_ground_i),
        .GTSOUTHREFCLK1                 (tied_to_ground_i),
        //----------------------- Common Block -  QPLL Ports -----------------------
        .QPLLDMONITOR                   (),
        //--------------------- Common Block - Clocking Ports ----------------------
        .QPLLOUTCLK                     (QPLLOUTCLK_OUT),
        .QPLLOUTREFCLK                  (QPLLOUTREFCLK_OUT),
        .REFCLKOUTMONITOR               (),
        //----------------------- Common Block - QPLL Ports ------------------------
        .QPLLFBCLKLOST                  (),
        .QPLLLOCK                       (QPLLLOCK_OUT),
        .QPLLLOCKDETCLK                 (QPLLLOCKDETCLK_IN),
        .QPLLLOCKEN                     (tied_to_vcc_i),
        .QPLLOUTRESET                   (tied_to_ground_i),
        .QPLLPD                         (tied_to_vcc_i),
        .QPLLREFCLKLOST                 (QPLLREFCLKLOST_OUT),
        .QPLLREFCLKSEL                  (QPLLREFCLKSEL_IN),
        .QPLLRESET                      (QPLLRESET_IN),
        .QPLLRSVD1                      (16'b0000000000000000),
        .QPLLRSVD2                      (5'b11111),
        //------------------------------- QPLL Ports -------------------------------
        .BGBYPASSB                      (tied_to_vcc_i),
        .BGMONITORENB                   (tied_to_vcc_i),
        .BGPDB                          (tied_to_vcc_i),
        .BGRCALOVRD                     (5'b11111),
        .PMARSVD                        (8'b00000000),
        .RCALENB                        (tied_to_vcc_i)

    );
endmodule
第十行開始講解:第十行為SIM_QPLLREFCLK_SEL ,其主要是用來仿真的,並且要與 QPLLREFCLK_SEL保持一致
輸入輸出在上面的表介紹過了,其他的補充在下圖。
QPLLLOCKDETCLK
QPLLFBCLKLOST
QPLLREFCLKLOST
QPLLRESET
QPLL_FBDIV_IN和  QPLL_FBDIV_RATIO



DRP的用法

DRP的英文應該是dynamic reconfiguration port,意思是動態可重配置端口,那么drp clk到底是個什么呢?在IP核中用來干嘛的?

你聽說過在線配置屬性嗎?(例如:GTX可以工作在不同線速率,用戶可能需要通過更改內部屬性來實現,這就需要DRP時鍾了。)也許做過GTX/GTH的朋友,有意無意都聽說過,那這個drp clk就是用於此的。

它還可以用來復位:

關於復位的代碼的提示:GTRXRESET先為高電平就可以復位了
綜上第一個代碼的參數的講解完畢。
第二個代碼的講解如下( gtx_common_reset.v)
`timescale 1ns / 1ps
`define DLY #1


module gtx_common_reset  #
   (
      parameter     STABLE_CLOCK_PERIOD      = 8        // Period of the stable clock driving this state-machine, unit is [ns]
   )
   (    
      input  wire      STABLE_CLOCK,             //Stable Clock, either a stable clock from the PCB
      input  wire      SOFT_RESET,               //User Reset, can be pulled any time
      output reg      COMMON_RESET = 1'b0             //Reset QPLL
   );


  localparam integer  STARTUP_DELAY    = 500;//AR43482: Transceiver needs to wait for 500 ns after configuration
  localparam integer WAIT_CYCLES      = STARTUP_DELAY / STABLE_CLOCK_PERIOD; // Number of Clock-Cycles to wait after configuration
  localparam integer WAIT_MAX         = WAIT_CYCLES + 10;                    // 500 ns plus some additional margin

  reg [7:0] init_wait_count = 0;
  reg       init_wait_done = 1'b0;
  wire      common_reset_i;
  reg       common_reset_asserted = 1'b0;

  localparam INIT = 1'b0;
  localparam ASSERT_COMMON_RESET = 1'b1;
    
  reg state = INIT;

  always @(posedge STABLE_CLOCK)
  begin
      // The counter starts running when configuration has finished and 
      // the clock is stable. When its maximum count-value has been reached,
      // the 500 ns from Answer Record 43482 have been passed.
      if (init_wait_count == WAIT_MAX) 
          init_wait_done <= `DLY  1'b1;
      else
        init_wait_count <= `DLY  init_wait_count + 1;
  end


  always @(posedge STABLE_CLOCK)
  begin
      if (SOFT_RESET == 1'b1)
       begin
         state <= INIT;
         COMMON_RESET <= 1'b0;
         common_reset_asserted <= 1'b0;
       end
      else
       begin
        case (state)
         INIT :
          begin
            if (init_wait_done == 1'b1) state <= ASSERT_COMMON_RESET;
          end
         ASSERT_COMMON_RESET :
          begin
            if(common_reset_asserted == 1'b0)
              begin
                COMMON_RESET <= 1'b1;
                common_reset_asserted <= 1'b1;
              end
            else
                COMMON_RESET <= 1'b0;
          end
          default:
              state <=  INIT; 
        endcase
       end
   end 


endmodule 
看名字就知道是復位用的,不做詳細講解:看一下輸入輸出就好了,連接到GTX收發器的sysclk引腳,和 soft_reset引腳,主要是用來讓GTX復位。
第三個代碼比較重要(gtx_gt_usrclk_source.v)
首先介紹一下基礎知識
翻譯如下:

FPGA TX 接口包括兩個並行時鍾:TXUSRCLK 和 TXUSRCLK2。 TXUSRCLK 是 GTX/GTH 發送器中 PCS 邏輯的內部時鍾。 TXUSRCLK 所需的速率取決於 GTXE2_CHANNEL/GTHE2_CHANNEL 原語的內部數據路徑寬度和 GTX/GTH 發送器的 TX 線路速率。公式 3-1 顯示了如何計算 TXUSRCLK 所需的速率。

翻譯如下:

TXUSRCLK2 是進入 GTX/GTH 收發器 TX 側的所有信號的主同步時鍾。大多數進入 GTX/GTH 收發器 TX 側的信號在 TXUSRCLK2 的正沿采樣。 TXUSRCLK2 和 TXUSRCLK 具有基於 TX_DATA_WIDTH 和 TX_INT_DATAWIDTH 設置的固定速率關系。表 3-3 顯示了每個 TX_DATA_WIDTH 和 TX_INT_DATAWIDTH 值的 TXUSRCLK2 和 TXUSRCLK 之間的關系。通過將 TX_INT_DATAWIDTH 設置為 1,大於 6.6 Gb/s 的線速需要 4 字節的內部數據路徑。

根據 GTX_IP核實現SMA口發送數據(一)IP核配置的配置,得到的具體參數如下:
TXUSRCLK 和 TXUSRCLK2的作用如下圖:通過自鎖發出TXOUTCLK和位寬來限制傳輸的線速率。

代碼如下(gtx_gt_usrclk_source.v)
`timescale 1ns / 1ps

//***********************************Entity Declaration*******************************

module gtx_GT_USRCLK_SOURCE 
(
 
    output          GT0_TXUSRCLK_OUT,
    output          GT0_TXUSRCLK2_OUT,
    input           GT0_TXOUTCLK_IN,
    output          GT0_TXCLK_LOCK_OUT,
    input           GT0_TX_MMCM_RESET_IN,
    output          GT0_RXUSRCLK_OUT,
    output          GT0_RXUSRCLK2_OUT,
    output          GT0_RXCLK_LOCK_OUT,
    input           GT0_RX_MMCM_RESET_IN,
    input  wire  Q2_CLK1_GTREFCLK_PAD_N_IN,
    input  wire  Q2_CLK1_GTREFCLK_PAD_P_IN,
    output wire  Q2_CLK1_GTREFCLK_OUT



);


`define DLY #1

//*********************************Wire Declarations**********************************
    wire            tied_to_ground_i;
    wire            tied_to_vcc_i;
 
    wire            gt0_txoutclk_i; 
    wire  q2_clk1_gtrefclk /*synthesis syn_noclockbuf=1*/;

    wire            gt0_txusrclk_i;
    wire            gt0_txusrclk2_i;
    wire            txoutclk_mmcm0_locked_i;
    wire            txoutclk_mmcm0_reset_i;
    wire            gt0_txoutclk_to_mmcm_i;


//*********************************** Beginning of Code *******************************

    //  Static signal Assigments    
    assign tied_to_ground_i             = 1'b0;
    assign tied_to_vcc_i                = 1'b1;
    assign gt0_txoutclk_i = GT0_TXOUTCLK_IN;
     
    assign Q2_CLK1_GTREFCLK_OUT = q2_clk1_gtrefclk;

    //IBUFDS_GTE2
    IBUFDS_GTE2 ibufds_instQ2_CLK1  
    (
        .O               (q2_clk1_gtrefclk),
        .ODIV2           (),
        .CEB             (tied_to_ground_i),
        .I               (Q2_CLK1_GTREFCLK_PAD_P_IN),
        .IB              (Q2_CLK1_GTREFCLK_PAD_N_IN)
    );



    // Instantiate a MMCM module to divide the reference clock. Uses internal feedback
    // for improved jitter performance, and to avoid consuming an additional BUFG

    assign  txoutclk_mmcm0_reset_i               =  GT0_TX_MMCM_RESET_IN;
    gtx_CLOCK_MODULE #
    (
        .MULT                           (10.0),
        .DIVIDE                         (1),
        .CLK_PERIOD                     (16.0),
        .OUT0_DIVIDE                    (20.0),
        .OUT1_DIVIDE                    (10),
        .OUT2_DIVIDE                    (1),
        .OUT3_DIVIDE                    (1)
    )
    txoutclk_mmcm0_i
    (
        .CLK0_OUT                       (gt0_txusrclk2_i),
        .CLK1_OUT                       (gt0_txusrclk_i),
        .CLK2_OUT                       (),
        .CLK3_OUT                       (),
        .CLK_IN                         (gt0_txoutclk_i),
        .MMCM_LOCKED_OUT                (txoutclk_mmcm0_locked_i),
        .MMCM_RESET_IN                  (txoutclk_mmcm0_reset_i)
    );



 
assign GT0_TXUSRCLK_OUT = gt0_txusrclk_i;
assign GT0_TXUSRCLK2_OUT = gt0_txusrclk2_i;
assign GT0_TXCLK_LOCK_OUT = txoutclk_mmcm0_locked_i;
assign GT0_RXUSRCLK_OUT = gt0_txusrclk_i;
assign GT0_RXUSRCLK2_OUT = gt0_txusrclk2_i;
assign GT0_RXCLK_LOCK_OUT = txoutclk_mmcm0_locked_i;

endmodule
看代碼主要就是例化了兩個相關的IP核來配置TXUSRCLK和TXUSRCLK2
之后的代碼( gtx_support.v)就是GTX的頂層模塊,將上述的三個IP核例化,直接看RTL就好了,由於把三個IP集成了,所以輸入輸出較多,看信號輸入輸出需要從前面的IP看。代碼沒有關於8/10編碼和FIFO,估計仍在了IP核里面,是一個黑匣子。所以補充了一點資料:
最后是頂層模塊(gtx_exdes.v),代碼較長,我們只看輸入輸出模塊,6個輸入3個輸出。
    input wire  Q2_CLK1_GTREFCLK_PAD_N_IN,
    input wire  Q2_CLK1_GTREFCLK_PAD_P_IN,
    input wire  DRP_CLK_IN_P,
    input wire  DRP_CLK_IN_N,
    output wire TRACK_DATA_OUT,
    input  wire         RXN_IN,
    input  wire         RXP_IN,
    output wire         TXN_OUT,
    output wire         TXP_OUT
關於整體的信號的輸入輸出分析如下,看上圖 
輸入分析:
 input wire  Q2_CLK1_GTREFCLK_PAD_N_IN,
 input wire  Q2_CLK1_GTREFCLK_PAD_P_I
這兩個是user_sma_clk 用來控制 gtx_gt_usrclk_source.v文件生成 TXUSRCLK和TXUSRCLK2
input wire  DRP_CLK_IN_P,
input wire  DRP_CLK_IN_N,
這兩個是DRP時鍾,用來 gtx_common生成QPLLOUTCLK_OUT 和 QPLLOUTREFCLK_OUT
 input  wire         RXN_IN,
input  wire         RXP_IN,
這兩個是接受端輸入,用來接受TX發送的數據,然后進行傳輸。
輸出分析:
output wire         TXN_OUT,
output wire         TXP_OUT
這兩個是發射端輸出
TRACK_DATA_OUT  這個是跟追,高電平時候說明發出數據了

仿真結果:
系統通過讀取frame_gen的ROM核數據進行偽隨機碼的發送,通過上述的輸入輸出分析,傳輸到RX接收。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM