Serdes系列总结——Xilinx serdes IP使用(一):3G serdes

本文转载自:十年老鸟的CSDN博客

器件:Xilinx zynq 7035
版本:vivado2019.2
实现:一个线速率为3.072G的,输入为20bit,输出为20bit的无协议无编码的4对serdes例程,参考时钟为153.6MHz
目的:记录从仿真到上板调试的过程,方便回忆

IP核的详细设置
第一个选项卡 GT Selection

第二个选项卡 GT Line Rate,RefClk Selection

设置时钟管脚位置和serdes管脚位置。(如何根据硬件工程师给出的管脚来设置GTX的位置?结尾补充)
第三个选项卡 Encoding and Clocking

第四个选项卡 Comma Alignment and Equalization
Comma Alignment 不用设置

第五个选项卡 PCIe,SATA,PRBS
大部分不选

第六、七个选项卡没有要选的。
最后Summary

最后,生成IP核后,鼠标放到IP核右键,点击open IP example design,生成了一个example的工程

IP example的使用
因为这个IPexample里面自带了数据发送和数据校验的模块,实际应用中,我们需要把需要发送的数据接口和需要接收的接口引出来,需要对这个example进行修改。
这里主要对关键改动点进行说明:

gtwizard_0_exdes.v中

(1)输入输出接口
DRP_CLK 一般为单端输入就可以了,这里要改
TRACK_DATA_OUT 这个不需要
增加serdes收发复位的接口
增加接收和发送数据的接口,每一路收发都包括收发数据、随路时钟、复位

(2)gtwizard_0_support模块,修改如下内容,把输入输出数据接口引出到顶层端口

.gt0_data_valid_in (1'b1),
.gt1_data_valid_in (1'b1),
.gt2_data_valid_in (1'b1),
.gt3_data_valid_in (1'b1),

.gt0_rxdata_out (o_rx_data_0),//(gt0_rxdata_i),
.gt0_txdata_in (i_tx_data_0),//(gt0_txdata_i),
.gt1_rxdata_out (o_rx_data_1),//(gt1_rxdata_i),
.gt1_txdata_in (i_tx_data_1),//(gt1_txdata_i),
.gt2_rxdata_out (o_rx_data_2),//(gt2_rxdata_i),
.gt2_txdata_in (i_tx_data_2),//(gt2_txdata_i),
.gt3_rxdata_out (o_rx_data_3),//(gt3_rxdata_i),
.gt3_txdata_in (i_tx_data_3),//(gt3_txdata_i),

(3)把输入输出的随路时钟和复位引出到顶层端口

assign o_tx_serdes_clk_0 = gt0_txusrclk_i;
assign o_tx_serdes_clk_1 = gt1_txusrclk_i;
assign o_tx_serdes_clk_2 = gt2_txusrclk_i;
assign o_tx_serdes_clk_3 = gt3_txusrclk_i;

assign o_rx_serdes_clk_0 = gt0_rxusrclk_i;
assign o_rx_serdes_clk_1 = gt1_rxusrclk_i;
assign o_rx_serdes_clk_2 = gt2_rxusrclk_i;
assign o_rx_serdes_clk_3 = gt3_rxusrclk_i;

assign o_tx_resetdone_0 = gt0_txfsmresetdone_i;
assign o_tx_resetdone_1 = gt1_txfsmresetdone_i;
assign o_tx_resetdone_2 = gt2_txfsmresetdone_i;
assign o_tx_resetdone_3 = gt3_txfsmresetdone_i;

assign o_rx_resetdone_0 = gt0_rxfsmresetdone_i;
assign o_rx_resetdone_1 = gt1_rxfsmresetdone_i;
assign o_rx_resetdone_2 = gt2_rxfsmresetdone_i;
assign o_rx_resetdone_3 = gt3_rxfsmresetdone_i;

除了上面,该例程还有一个大坑需要规避。(干货)
gtwizard_0_GT_USRCLK_SOURCE.v文件中
添加

wire gt1_rxusrclk_i;
wire gt2_rxusrclk_i;
wire gt3_rxusrclk_i;
BUFG rxoutclk_bufg1_i1
(
.I (gt1_rxoutclk_i),
.O (gt1_rxusrclk_i)
);

BUFG rxoutclk_bufg1_i2
(
.I (gt2_rxoutclk_i),
.O (gt2_rxusrclk_i)
);

BUFG rxoutclk_bufg1_i3
(
.I (gt3_rxoutclk_i),
.O (gt3_rxusrclk_i)
);

assign GT1_RXUSRCLK_OUT = gt1_rxusrclk_i; //gt0_rxusrclk_i
assign GT1_RXUSRCLK2_OUT = gt1_rxusrclk_i;// gt0_rxusrclk_i
assign GT2_RXUSRCLK_OUT = gt2_rxusrclk_i;// gt0_rxusrclk_i
assign GT2_RXUSRCLK2_OUT = gt2_rxusrclk_i;// gt0_rxusrclk_i
assign GT3_RXUSRCLK_OUT = gt3_rxusrclk_i;// gt0_rxusrclk_i
assign GT3_RXUSRCLK2_OUT = gt3_rxusrclk_i;// gt0_rxusrclk_i

这里的修改尤其重要,感觉是xilinx的一个BUG,如果这里不改,仿真会没有问题,但上板调试的时候,只要serdes0接口不接的话,其他接口就会不稳定。其中的缘由可通过代码去理解

最后,顶层的例化为:

gtwizard_0_exdes
gtwizard_0_exdes_i
(
.Q3_CLK0_GTREFCLK_PAD_N_IN (tx_refclk_n_r),
.Q3_CLK0_GTREFCLK_PAD_P_IN (tx_refclk_p_r),
.DRP_CLK_IN (drp_clk_r),
.o_tx_serdes_clk_0 (w_tx_serdes_clk_0 ),
.o_tx_resetdone_0 (w_tx_resetdone_0 ),
.i_tx_data_0 (w_tx_fifo_out_0 ),
.o_tx_serdes_clk_1 (w_tx_serdes_clk_1 ),
.o_tx_resetdone_1 (w_tx_resetdone_1 ),
.i_tx_data_1 (w_tx_fifo_out_1 ),
.o_tx_serdes_clk_2 (w_tx_serdes_clk_2 ),
.o_tx_resetdone_2 (w_tx_resetdone_2 ),
.i_tx_data_2 (w_tx_fifo_out_2 ),
.o_tx_serdes_clk_3 (w_tx_serdes_clk_3 ),
.o_tx_resetdone_3 (w_tx_resetdone_3 ),
.i_tx_data_3 (w_tx_fifo_out_3 ),
.o_rx_serdes_clk_0 (w_rx_serdes_clk_0 ),
.o_rx_resetdone_0 (w_rx_resetdone_0 ),
.o_rx_data_0 (w_rx_fifo_in_0 ),
.o_rx_serdes_clk_1 (w_rx_serdes_clk_1 ),
.o_rx_resetdone_1 (w_rx_resetdone_1 ),
.o_rx_data_1 (w_rx_fifo_in_1 ),
.o_rx_serdes_clk_2 (w_rx_serdes_clk_2 ),
.o_rx_resetdone_2 (w_rx_resetdone_2 ),
.o_rx_data_2 (w_rx_fifo_in_2 ),
.o_rx_serdes_clk_3 (w_rx_serdes_clk_3 ),
.o_rx_resetdone_3 (w_rx_resetdone_3 ),
.o_rx_data_3 (w_rx_fifo_in_3 ),
.i_soft_reset (4'h0 ),
.i_rx_reset (4'h0 ),
.RXN_IN (rxn_in_i),
.RXP_IN (rxp_in_i),
.TXN_OUT (txn_out_i),
.TXP_OUT (txp_out_i)
);

时钟输入都是153.6M的,输入数据按最简单的办法,输入一个固定数
reg [19:0] w_tx_fifo_out_0 = 20’haaaaa ;
reg [19:0] w_tx_fifo_out_1 = 20’haaaaa ;
reg [19:0] w_tx_fifo_out_2 = 20’haaaaa ;
reg [19:0] w_tx_fifo_out_3 = 20’haaaaa ;
发射20’haaaaa,将sedes输出管脚直接连入输入管脚(仿真的时候),看接收的数据是什么?
注意,为什么发射20’haaaaa 。因为目前没有任何编码,CDR 恢复时钟,是需要有比特翻转才能对接收时钟进行恢复的。尽管在仿真阶段,可以没有bit翻转。但上板调试之后显然就会出问题。

该工程添加管脚约束后可以直接用于上板调试,直接用光口1和光口2进行光纤对接,通过ILA抓取接收的数据,如果是稳定的20’haaaaa和稳定的20’h55555,则是正常。

实际应用中,还需自己进行66b/64b编解码的添加,而且还需自己用代码来实现帧对齐等等,较为复杂。后面我们在讲一个example中就自带66/64编码的例子

附件

下载地址:
SERDES_3G
SERDES_3G.rar中
gtwizard_0_ex_yuanshi为 IP example直接生成的工程,
gtwizard_0_ex_xiugai 为在上面基础上修改的工程。
在gtwizard_0_ex_xiugai文件夹中 找到啊 tb.tcl,修改tcl中的文件路径后,直接可以modelsim运行(modelsim要提前配置好库文件)
运行结果如下图所示,即成功

最新文章

最新文章