本文转载自:十年老鸟的CSDN博客
注:本文由作者授权转发,如需转载请联系作者本人
器件:Xilinx zynq 7035
版本:vivado2019.2
实现:10.1376G的serdes,一个输入为64bit,输出为64bit的6664B编码的4对serdes例程,参考时钟为153.6MHz
目的:记录从仿真到上板调试的过程,方便回忆
IP核的详细设置
第一个选项卡 GT Selection
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265443-tu_1.jpg)
第二个选项卡 GT Line Rate,RefClk Selection
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265444-tu_2.jpg)
设置时钟管脚位置和serdes管脚位置。(如何根据硬件工程师给出的管脚来设置GTX的位置?结尾补充)
第三个选项卡 Encoding and Clocking
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265445-tu_3.jpg)
第四个选项卡 Comma Alignment and Equalization
Comma Alignment 不用设置
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265446-tu_4.jpg)
第五个选项卡 PCIe,SATA,PRBS
大部分不选
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265447-tu_5.jpg)
第六、七个选项卡没有要选的。
最后Summary
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265448-tu_6.jpg)
最后,生成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_loopback_in (i_loopback[2:0]),
.gt1_loopback_in (i_loopback[5:3]),
.gt2_loopback_in (i_loopback[8:6]),
.gt3_loopback_in (i_loopback[11:9]),
.gt0_rxdata_out
.gt0_txdata_in 。。。。。。。。。。。。。。。。。。
等这些都要稍微改变,这里不再花篇幅把所有的列出,直接通过对比软件很容易看出
(3)把输入输出的随路时钟和复位引出到顶层端口
(4)注意扰码的初始值是否和对端一致
除了上面,该例程还有一个大坑需要规避。(干货)
gtwizard_0_GT_USRCLK_SOURCE.v文件中
添加
gtwizard_0_CLOCK_MODULE #
(
.MULT (2.0),
.DIVIDE (1),
.CLK_PERIOD (3.156),
.OUT0_DIVIDE (4.0),
.OUT1_DIVIDE (2),
.OUT2_DIVIDE (1),
.OUT3_DIVIDE (1)
)
rxoutclk_mmcm1_i0
(
.CLK0_OUT (GT0_RXUSRCLK2_OUT),
.CLK1_OUT (GT0_RXUSRCLK_OUT),
.CLK2_OUT (),
.CLK3_OUT (),
.CLK_IN (gt0_rxoutclk_i),
.MMCM_LOCKED_OUT (GT0_RXCLK_LOCK_OUT),
.MMCM_RESET_IN (GT0_RX_MMCM_RESET_IN)
);
gtwizard_0_CLOCK_MODULE #
(
.MULT (2.0),
.DIVIDE (1),
.CLK_PERIOD (3.156),
.OUT0_DIVIDE (4.0),
.OUT1_DIVIDE (2),
.OUT2_DIVIDE (1),
.OUT3_DIVIDE (1)
)
rxoutclk_mmcm1_i1
(
.CLK0_OUT (GT1_RXUSRCLK2_OUT),
.CLK1_OUT (GT1_RXUSRCLK_OUT),
.CLK2_OUT (),
.CLK3_OUT (),
.CLK_IN (gt1_rxoutclk_i),
.MMCM_LOCKED_OUT (GT1_RXCLK_LOCK_OUT),
.MMCM_RESET_IN (GT1_RX_MMCM_RESET_IN)
);
gtwizard_0_CLOCK_MODULE #
(
.MULT (2.0),
.DIVIDE (1),
.CLK_PERIOD (3.156),
.OUT0_DIVIDE (4.0),
.OUT1_DIVIDE (2),
.OUT2_DIVIDE (1),
.OUT3_DIVIDE (1)
)
rxoutclk_mmcm1_i2
(
.CLK0_OUT (GT2_RXUSRCLK2_OUT),
.CLK1_OUT (GT2_RXUSRCLK_OUT),
.CLK2_OUT (),
.CLK3_OUT (),
.CLK_IN (gt2_rxoutclk_i),
.MMCM_LOCKED_OUT (GT2_RXCLK_LOCK_OUT),
.MMCM_RESET_IN (GT2_RX_MMCM_RESET_IN)
);
gtwizard_0_CLOCK_MODULE #
(
.MULT (2.0),
.DIVIDE (1),
.CLK_PERIOD (3.156),
.OUT0_DIVIDE (4.0),
.OUT1_DIVIDE (2),
.OUT2_DIVIDE (1),
.OUT3_DIVIDE (1)
)
rxoutclk_mmcm1_i3
(
.CLK0_OUT (GT3_RXUSRCLK2_OUT),
.CLK1_OUT (GT3_RXUSRCLK_OUT),
.CLK2_OUT (),
.CLK3_OUT (),
.CLK_IN (gt3_rxoutclk_i),
.MMCM_LOCKED_OUT (GT3_RXCLK_LOCK_OUT),
.MMCM_RESET_IN (GT3_RX_MMCM_RESET_IN)
);
这里的修改尤其重要,感觉是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),
.RXN_IN (rxn_in_i),
.RXP_IN (rxp_in_i),
.TXN_OUT (txn_out_i),
.TXP_OUT (txp_out_i),
.o_gtwiz_userclk_rx_usrclk2_int ( w_gtwiz_userclk_rx_usrclk2_int ),
.o_gtwiz_userclk_tx_usrclk2_int ( w_gtwiz_userclk_tx_usrclk2_int ),
.o_gt_rxfsmresetdone ( w_gt_rxfsmresetdone ),
.o_gt_txfsmresetdone ( w_gt_txfsmresetdone ),
.o_rx_header ( w_rx_header ),
.o_rx_valid ( w_rx_valid ),
.o_rx_data ( w_rx_data ),
.i_tx_header ( w_tx_header ),
.i_tx_valid ( w_tx_valid ),
.i_tx_sequence ( w_tx_sequence ),
.i_tx_data ( w_tx_data ),
.i_soft_reset (0 ),
.i_loopback (0 )
);
以第一路serdes为例
w_gtwiz_userclk_tx_usrclk2_int[0]为第一路serdes发射时钟,时钟为158.4M
w_tx_sequence0固定为0-32的循环计数
w_tx_valid0,当w_tx_sequence0 =32时w_tx_valid0 = 0,表示当前输入的w_tx_data0是无效的,其他时候有效,且w_tx_valid0 = 1。
接收也类似
输入一个累加数,将sedes输出管脚直接连入输入管脚(仿真的时候),看接收的数据是否也是累加数。
该工程可以直接用于上板调试,直接用光口1和光口2进行光纤对接,通过ILA抓取接收的数据,也是累加数,则是正常。
该工程添加管脚和时钟约束后可直接用于实际应用中。
附件
下载地址:
SERDES_10G.rar中
SERDES_10G
gtwizard_0_ex_yuanshi为 IP example直接生成的工程,
gtwizard_0_ex_xiugai 为在上面基础上修改的工程。
在gtwizard_0_ex_xiugai文件夹中 找到啊 tb.tcl,修改tcl中的文件路径后,直接可以modelsim运行(modelsim要提前配置好库文件)
运行结果如下图所示,即成功
![](http://xilinx.eetrend.com/files/2022-08/%E5%8D%9A%E5%AE%A2/100562912-265449-tu_7.png)