Serdes系列总结——Xilinx serdes IP使用(1)-3G serdes
- IP详细设置核
- IP example的使用
- 附件
器件: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中
DRP_CLK 一般来说,单端输入是可以的要改 TRACK_DATA_OUT 这个不需要 增加serdes收发复位接口 增加接收和发送数据的接口,包括收发数据、随行时钟和复位
.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_daa_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),
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要提前配置好库文件) 运行结果如下图所示,即成功
写于2021年10月16日 如需交流,QQ:172146579