GTX IP配置完了,你不得搞個回環測試一番?
前言
理解一個IP的用法,最好的辦法就是打開官方的Example Design。
所以本文首先介紹Example Design,然后再替換成我們自己的收發測試模塊,對比印證學習,差不多就能勉強把GTX給玩起來了。
一、示例工程Example Design
接上一講(四)GTX IP核的配置:
我們配置GTX為:3.125G , 參考時鐘156.25Mhz ,然后生成了GTX的IP。
首先,右鍵IP打開Example Design。
打開示例工程后,看到如下圖所示的工程結構:
先簡單概括下,示例工程的組成結構,如下圖所示的拓撲圖:
OK,接下來我們對每個子模塊進行分別介紹。
1.1 gtx_support模塊
support子模塊為GTX主要模塊。包含GTX的時鐘、復位以及對原語/IP的例化使用。
Xilinx為了IP核的通用性,將每個IP的端口設置非常完善也意味著非常復雜。端口信號眾多,導致我們一陣頭大,不知從何下手,所以這里直接上干貨,簡要解析各個端口信號,哪些是使用的,哪些是不用的。
PS:很多端口都沒有使用,要么置0,要么置1 。
所以,引用B站名言:“消除恐懼的最好辦法就是面對恐懼,奧利給!”
直接上代碼: 詳見后面注釋內容!
注:很多功能我們沒有用上,所以給的0,實際使用根據具體需求而定。
ip_gtx ip_gtx_init_i
(
.sysclk_in (sysclk_in_i), //系統時鐘
.soft_reset_tx_in (soft_reset_tx_in), //0
.soft_reset_rx_in (soft_reset_rx_in), //0
.dont_reset_on_data_error_in (dont_reset_on_data_error_in), //0
.gt0_tx_fsm_reset_done_out (gt0_tx_fsm_reset_done_out), //output
.gt0_rx_fsm_reset_done_out (gt0_rx_fsm_reset_done_out), //output
.gt0_data_valid_in (gt0_data_valid_in), //1
//GT0 (X1Y0)
//------------------------------- CPLL Ports -------------------------------
.gt0_cpllfbclklost_out (gt0_cpllfbclklost_out),
.gt0_cplllock_out (gt0_cplllock_out),
.gt0_cplllockdetclk_in (sysclk_in_i), //系統時鐘
.gt0_cpllreset_in (gt0_cpllreset_in), //0
//------------------------ Channel - Clocking Ports ------------------------
.gt0_gtrefclk0_in (tied_to_ground_i), //0
.gt0_gtrefclk1_in (q0_clk1_refclk_i), //參考時鐘
//-------------------------- Channel - DRP Ports --------------------------
.gt0_drpaddr_in (gt0_drpaddr_in), //0
.gt0_drpclk_in (sysclk_in_i), //系統時鐘
.gt0_drpdi_in (gt0_drpdi_in), //0
.gt0_drpdo_out (gt0_drpdo_out), //0
.gt0_drpen_in (gt0_drpen_in), //0
.gt0_drprdy_out (gt0_drprdy_out), //0
.gt0_drpwe_in (gt0_drpwe_in), //0
//------------------------- Digital Monitor Ports --------------------------
.gt0_dmonitorout_out (gt0_dmonitorout_out), // output
//----------------------------- Loopback Ports -----------------------------
.gt0_loopback_in (gt0_loopback_in), //0
//---------------------------- Power-Down Ports ----------------------------
.gt0_rxpd_in (gt0_rxpd_in), //0
.gt0_txpd_in (gt0_txpd_in), //0
//------------------- RX Initialization and Reset Ports --------------------
.gt0_eyescanreset_in (gt0_eyescanreset_in), //0
.gt0_rxuserrdy_in (gt0_rxuserrdy_in), //1
//------------------------ RX Margin Analysis Ports ------------------------
.gt0_eyescandataerror_out (gt0_eyescandataerror_out), // output
.gt0_eyescantrigger_in (gt0_eyescantrigger_in), //0
//----------------------- Receive Ports - CDR Ports ------------------------
.gt0_rxcdrhold_in (gt0_rxcdrhold_in), //0
//----------------- Receive Ports - Clock Correction Ports -----------------
.gt0_rxclkcorcnt_out (gt0_rxclkcorcnt_out), // output
//---------------- Receive Ports - FPGA RX Interface Ports -----------------
.gt0_rxusrclk_in (gt0_rxusrclk_i), // rxusrclk
.gt0_rxusrclk2_in (gt0_rxusrclk2_i), // rxusrclk2
//---------------- Receive Ports - FPGA RX interface Ports -----------------
.gt0_rxdata_out (gt0_rxdata_out), // 接收數據
//----------------- Receive Ports - Pattern Checker Ports ------------------
.gt0_rxprbserr_out (gt0_rxprbserr_out), // output
.gt0_rxprbssel_in (gt0_rxprbssel_in), // 0
//----------------- Receive Ports - Pattern Checker ports ------------------
.gt0_rxprbscntreset_in (gt0_rxprbscntreset_in), // 0
//---------------- Receive Ports - RX 8B/10B Decoder Ports -----------------
.gt0_rxdisperr_out (gt0_rxdisperr_out), // output
.gt0_rxnotintable_out (gt0_rxnotintable_out), // output
//------------------------- Receive Ports - RX AFE -------------------------
.gt0_gtxrxp_in (gt0_gtxrxp_in), // 管腳RXP
//---------------------- Receive Ports - RX AFE Ports ----------------------
.gt0_gtxrxn_in (gt0_gtxrxn_in), // 管腳RXN
//------------------- Receive Ports - RX Equalizer Ports -------------------
.gt0_rxdfelpmreset_in (gt0_rxdfelpmreset_in), // 0
.gt0_rxmonitorout_out (gt0_rxmonitorout_out), // 0
.gt0_rxmonitorsel_in (gt0_rxmonitorsel_in), // 0
//------------- Receive Ports - RX Fabric Output Control Ports -------------
.gt0_rxoutclkfabric_out (gt0_rxoutclkfabric_out), // output
//----------- Receive Ports - RX Initialization and Reset Ports ------------
.gt0_gtrxreset_in (gt0_gtrxreset_in), // 0
.gt0_rxpmareset_in (gt0_rxpmareset_in), // 0
//----------------- Receive Ports - RX8B/10B Decoder Ports -----------------
.gt0_rxchariscomma_out (gt0_rxchariscomma_out), // output
.gt0_rxcharisk_out (gt0_rxcharisk_out), // rxcharisk
//------------ Receive Ports -RX Initialization and Reset Ports ------------
.gt0_rxresetdone_out (gt0_rxresetdone_out), // output
//------------------- TX Initialization and Reset Ports --------------------
.gt0_gttxreset_in (gt0_gttxreset_in), // 0
.gt0_txuserrdy_in (gt0_txuserrdy_in), // 1
//-------------- Transmit Ports - 8b10b Encoder Control Ports --------------
.gt0_txchardispmode_in (gt0_txchardispmode_in), // 0
.gt0_txchardispval_in (gt0_txchardispval_in), // 0
//---------------- Transmit Ports - FPGA TX Interface Ports ----------------
.gt0_txusrclk_in (gt0_txusrclk_i), // txusrclk
.gt0_txusrclk2_in (gt0_txusrclk2_i), // txusrclk2
//---------------- Transmit Ports - Pattern Generator Ports ----------------
.gt0_txprbsforceerr_in (gt0_txprbsforceerr_in), // 0
//-------------------- Transmit Ports - TX Buffer Ports --------------------
.gt0_txbufstatus_out (gt0_txbufstatus_out), // output
//---------------- Transmit Ports - TX Data Path interface -----------------
.gt0_txdata_in (gt0_txdata_in), // 發生數據
//-------------- Transmit Ports - TX Driver and OOB signaling --------------
.gt0_gtxtxn_out (gt0_gtxtxn_out), // 管腳TXN
.gt0_gtxtxp_out (gt0_gtxtxp_out), // 管腳TXP
//--------- Transmit Ports - TX Fabric Clock Output Control Ports ----------
.gt0_txoutclk_out (gt0_txoutclk_i), // output
.gt0_txoutclkfabric_out (gt0_txoutclkfabric_out), // output
.gt0_txoutclkpcs_out (gt0_txoutclkpcs_out), // output
//------------------- Transmit Ports - TX Gearbox Ports --------------------
.gt0_txcharisk_in (gt0_txcharisk_in), // txcharisk
//----------- Transmit Ports - TX Initialization and Reset Ports -----------
.gt0_txresetdone_out (gt0_txresetdone_out), // output
//---------------- Transmit Ports - pattern Generator Ports ----------------
.gt0_txprbssel_in (gt0_txprbssel_in), // 0
.gt0_qplloutclk_in (gt0_qplloutclk_i), // from common
.gt0_qplloutrefclk_in (gt0_qplloutrefclk_i) // from common
);
1.1.1 gt_usrclk_source
GTX的時鐘子模塊。
學習官方例程除了學習IP的用法外,另外一點就是學習官方大佬的代碼,學習優秀的代碼!包括代碼規范、實現方式以及模塊劃分。
我們自己做項目的時候也要注意這一點,時鐘最好單獨設計為一個時鐘子模塊,提供整個工程所需的全部邏輯內部時鐘。
用個框圖來表示這個模塊的功能:
至于具體實現方式,也很簡單,用了兩個原語:IBUFDS 、BUFG。
后面空了會詳細出一個系列專講Xilinx原語。
想要更多了解GTX的時鐘,歡迎翻閱本系列第二篇(二)GTX時鐘篇。
Xilinx FPGA平臺GTX簡易使用教程(二)GTX時鐘篇
???????1.1.2 gt_common
這個模塊主要是對GTXE2_COMMON原語的例化。
原語內容較多,這里不進行介紹。保持默認就好。
???????1.1.3 gt_common_reset
顧名思義,這個模塊是對common的復位,也就是對QPLL的復位。保持默認就好。
實際上,我們進一步研究示例就會發現,該復位根本沒有使用!為什么呢?不復位也能正常工作?對復位有興趣的歡迎翻閱系列第三篇(三)GTX復位與初始化。
Xilinx FPGA平臺GTX簡易使用教程(三)GTX復位與初始化?????
1.2 frame_gen
開門見山的說,這就是一個數據產生模塊。只用于仿真測試,仔細研究你就發現它數據產生的方式比較有意思:從文件中讀取!我們再回到工程結構目錄,會看到有兩個Data Files:
gt_rom_init_rx.dat、gt_rom_init_tx.dat
一個發送數據的文件,一個接收數據的文件。
再打開發送這個文件,如下圖所示:
至于具體怎么實現文件數據讀取,后面空了筆者也會出一篇文章,介紹在仿真中,對文件的讀和寫。
???????1.3 frame_check
數據檢查模塊,將接收到的數據和發送的數據進行比對,如果有誤,就給error信號。可以學習這種設計思路,保障數據收發的準確性。
二、GTX收發測試
GTX的示例工程基本介紹完畢,但是那畢竟是別人的。如果我們自己想把GTX跑起來呢?很簡單,把示例工程的frame_gen數據產生模塊刪掉,換上我們自己的發送數據模塊packet_send;將frame_check數據檢查模塊刪掉,換上我們自己的接收數據模塊packet_recv。最后加個TOP頂層,將packet_send、packet_recv、gt_support三個模塊連起來就好。
注:測試工程為回環,發送端口直接懟到接收端口。
2.1 對support模塊的整合
support模塊前面已經介紹過,是使用GTX的核心。所以我們對GTX的使用也是基于該模塊。
直接上干貨吧,需要做以下改動:
將發送/接收數據端口開放到外層,TOP才能模塊連接;包含數據總線tx/rx_data和控制總線tx/rx_charisk;
將gt0_data_valid_in信號直接置1;
2.2發送模塊
添加我們需要發送的數據,可以加上幀頭(sof)、幀尾(eof)信號便于接收模塊判斷。
發送模塊需要輸出兩個信號(這里的位寬由GTX IP配置決定):
tx_data[31:0] :需要發送的數據
tx_char[3:0] :K碼指示,每1bit對應1個字節的數據;0:表示發送的是數據;1:表示發送的是K碼。
需要注意的是,在發送數據之前要先發一個K碼,以便接收數據對齊。
2.3接收模塊
對GTX接收到的數據進一步處理,可通過檢測幀頭(sof)、幀尾(eof)信號,來接收一個完整的幀數據。也可以對接收的數據與發送數據比對,檢查是否有誤。
沒什么好講的,略過吧。
2.4仿真驗證
仿真tb文件主要產生時鐘激勵,和產生需要發送的數據。
因為我們是回環,所以記得tb里面將TX / RX進行短接,注意_N對_N,_P對_P。
另外值得一提的是,我們參考時候為差分輸入,這里簡單提供一種差分時鐘的testbench寫法:
wire Q0_CLK1_GTREFCLK_PAD_N_IN;
reg Q0_CLK1_GTREFCLK_PAD_P_IN;
wire DRP_CLK_IN_N;
reg DRP_CLK_IN_P;
initial begin
Q0_CLK1_GTREFCLK_PAD_P_IN = 0;
DRP_CLK_IN_P = 0;
end
always #3.2 Q0_CLK1_GTREFCLK_PAD_P_IN = ~Q0_CLK1_GTREFCLK_PAD_P_IN;
always #5 DRP_CLK_IN_P = ~DRP_CLK_IN_P;
assign Q0_CLK1_GTREFCLK_PAD_N_IN = ~Q0_CLK1_GTREFCLK_PAD_P_IN;
assign DRP_CLK_IN_N = ~DRP_CLK_IN_P;
最后,我們來看一下仿真結果:
輸入: 0-100的累加數(只截取了0-7)
輸出:0-100的累加數(只截取了0-7)
OK,回環完成。
后記
整個GTX的介紹到這里暫告一段落,待筆者對齊有進一步更深的理解時再做補充。補充內容可能包括具體項目應用、GT高速接口的底層原理等。
按照筆者的習慣,基本以原理介紹、系統組成、方案設計為主,而對于具體的代碼,筆者是不會在文章中具體寫出來的。所以,這些測試工程我后面會以文件的形式放上來。
下一個系列,我們將開始SRIO。
隨筆者一起,將接口擼個遍吧!
審核編輯:湯梓紅
-
FPGA
+關注
關注
1629文章
21729瀏覽量
603059 -
GTX
+關注
關注
0文章
35瀏覽量
10913
發布評論請先 登錄
相關推薦
評論