所以分為三個模塊進行介紹
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
第二個代碼的講解如下( 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復位。
首先介紹一下基礎知識
翻譯如下:
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 字節的內部數據路徑。
`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核里面,是一個黑匣子。所以補充了一點資料:
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接收。