注意本文的IP整理思路及回环测试思路来自奇哥高速教程,经过奇哥允许后对该工程开源,文末有源工程获取方式
1、整理Aurora 64B/66B的IP
如下图所示,每个高速收发器都可以包含复位逻辑和时钟信号,因此在每个通道内部都会封装复位同步模块和MMCM调用模块,如下图所示。
将Aurora 64B/66B的一些专用信号引出即可。
具体的信号连接方式都是参考的示例工程,整理方式也与前文的高速收发器基本一致,因此本文就不详细讲述了,参考代码如下所示。
//--###############################################################################################
//--#
//--# File Name : aurora_channel
//--# Designer : 数字站
//--# Tool : Vivado 2021.1
//--# Design Date : 2024.4.9
//--# Description : aurora_64b66b通道模块
//--# Version : 0.0
//--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode)
//--#
//--###############################################################################################
module aurora_channel (
input gt_rx_p ,//GT收发器的接收数据差分引脚;
input gt_rx_n ,//GT收发器的接收数据差分引脚;
input gt_refclk ,//GT参考时钟,IP设置为156.25MHZ;
output user_clk ,//用户参考时钟信号;
output user_sys_reset ,//输出给用户的复位信号;
input system_rst ,//系统复位信号;
input [2 : 0] gt_loopback ,//GT收发器的回环模式控制信号;
output gt_tx_p ,//GT收发器的发送数据差分引脚;
output gt_tx_n ,//GT收发器的发送数据差分引脚;
output hard_err ,//硬件错误指示信号;
output soft_err ,//软件错误指示信号;
output channel_up ,//通道初始化完成且通道准备好数据时拉高;
output lane_up ,//单通道初始化成功信号;
input [63 : 0] s_axi_tx_tdata ,//用户发送数据的AXI_STEAM流接口信号;
input [7 : 0] s_axi_tx_tkeep ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tlast ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tvalid ,//用户发送数据的AXI_STEAM流接口信号;
output s_axi_tx_tready ,//用户发送数据的AXI_STEAM流接口信号;
output [63 : 0] m_axi_rx_tdata ,//用户接收数据的AXI_STEAM流接口信号;
output [7 : 0] m_axi_rx_tkeep ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tlast ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tvalid ,//用户接收数据的AXI_STEAM流接口信号;
input init_clk ,//初始化时钟,IP设置为100MHz。
input drp_clk ,//DRP时钟信号,IP设置为100MHz。
input [8 : 0] gt_drpaddr ,//GT收发器的DRP地址信号;
input [15 : 0] gt_drpdi ,//GT收发器的DRP数据输入信号;
output gt_drprdy ,//GT收发器的DRP应答信号;
input gt_drpen ,//GT收发器的DRP使能信号;
input gt_drpwe ,//GT收发器的DRP读写指示信号;
output [15 : 0] gt_drpdo ,//GT收发器的DRP数据输出信号;
input [7 : 0] qpll_drpaddr ,//QPLL的DRP地址信号;
input [15 : 0] qpll_drpdi ,//QPLL的DRP数据输入信号;
input qpll_drpen ,//QPLL的DRP使能信号;
input qpll_drpwe ,//QPLL的DRP读写指示信号;
input gt_qpllclk ,//QPLL的时钟信号;
input gt_qpllrefclk ,//QPLL的参考时钟信号;
output gt_qpllreset ,//QPLL的复位信号;
input gt_qplllock ,//QPLL的锁定信号;
input gt_qpllrefclklost //QPLL的参考时钟失锁信号;
);
wire tx_out_clk ;
wire gt_pll_lock ;
wire sync_clk ;
wire mmcm_not_locked ;
wire reset_pb ;
wire gt_rst ;
//例化复位同步模块;
aurora_64b66b_0_SUPPORT_RESET_LOGIC support_reset_logic(
.RESET ( system_rst ),//系统复位信号;
.USER_CLK ( user_clk ),//用户时钟信号;
.INIT_CLK ( init_clk ),//初始化时钟;
.GT_RESET_IN ( 1'b0 ),//GT收发器复位信号;
.SYSTEM_RESET ( reset_pb ),//IP复位信号;
.GT_RESET_OUT ( gt_rst ) //GT收发器复位信号;
);
//例化MMCM模块,通过tx_out_clk生成用户时钟信号;
aurora_64b66b_0_CLOCK_MODULE clock_module(
.CLK ( tx_out_clk ),//GT收发器输出的用户时钟信号;
.CLK_LOCKED ( gt_pll_lock ),//MMCM锁定信号;
.USER_CLK ( user_clk ),//用户时钟信号;
.SYNC_CLK ( sync_clk ),//同步时钟信号;
.MMCM_NOT_LOCKED ( mmcm_not_locked ) //MMCM没有锁定信号;
);
//例化aurora_64b66b IP;
aurora_64b66b_0 u_aurora_64b66b_0 (
.rxp ( gt_rx_p ),//GT收发器的接收数据差分引脚;
.rxn ( gt_rx_n ),//GT收发器的接收数据差分引脚;
.refclk1_in ( gt_refclk ),//GT参考时钟,IP设置为156.25MHZ
.user_clk ( user_clk ),//用户时钟,由TX_OUT_CLK通过MMCM生成;
.sync_clk ( sync_clk ),//同步时钟信号,由TX_OUT_CLK通过MMCM生成;
.reset_pb ( reset_pb ),//系统复位信号;
.power_down ( 1'b0 ),//掉电模式;
.pma_init ( gt_rst ),//GT收发器复位,初始化;
.loopback ( gt_loopback ),//GT收发器的回环模式控制信号;
.txp ( gt_tx_p ),//GT收发器的发送数据差分引脚;
.txn ( gt_tx_n ),//GT收发器的发送数据差分引脚;
.hard_err ( hard_err ),//硬件错误指示信号;
.soft_err ( soft_err ),//软件错误指示信号;
.channel_up ( channel_up ),//通道初始化完成且通道准备好数据时拉高;
.lane_up ( lane_up ),//单通道初始化成功信号;
.tx_out_clk ( tx_out_clk ),//GT收发器输出参考时钟信号,通过BUFG可以用作用户时钟;
.gt_pll_lock ( gt_pll_lock ),//MMCM锁定信号;
.s_axi_tx_tdata ( s_axi_tx_tdata ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tkeep ( s_axi_tx_tkeep ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tlast ( s_axi_tx_tlast ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tvalid ( s_axi_tx_tvalid ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tready ( s_axi_tx_tready ),//用户发送数据的AXI_STEAM流接口信号;
.m_axi_rx_tdata ( m_axi_rx_tdata ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tkeep ( m_axi_rx_tkeep ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tlast ( m_axi_rx_tlast ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tvalid ( m_axi_rx_tvalid ),//用户接收数据的AXI_STEAM流接口信号;
.mmcm_not_locked ( mmcm_not_locked ),//MMCM没有锁定指示信号;
.drp_clk_in ( drp_clk ),//DRP时钟信号;
.drpaddr_in ( gt_drpaddr ),//GT收发器的DRP地址信号;
.drpdi_in ( gt_drpdi ),//GT收发器的DRP数据输入信号;
.drprdy_out ( gt_drprdy ),//GT收发器的DRP应答信号;
.drpen_in ( gt_drpen ),//GT收发器的DRP使能信号;
.drpwe_in ( gt_drpwe ),//GT收发器的DRP读写指示信号;
.drpdo_out ( gt_drpdo ),//GT收发器的DRP数据输出信号;
.qpll_drpaddr_in ( qpll_drpaddr ),//QPLL的DRP地址信号;
.qpll_drpdi_in ( qpll_drpdi ),//QPLL的DRP数据输入信号;
.qpll_drprdy_out ( ),//QPLL的DRP应答信号;
.qpll_drpen_in ( qpll_drpen ),//QPLL的DRP使能信号;
.qpll_drpwe_in ( qpll_drpwe ),//QPLL的DRP读写指示信号;
.qpll_drpdo_out ( ),//QPLL的DRP数据输出信号;
.init_clk ( init_clk ),//初始化时钟,IP设置为100MHz。
.link_reset_out ( ),//output wire link_reset_out
.gt_qpllclk_quad1_in ( gt_qpllclk ),//QPLL的时钟信号;
.gt_qpllrefclk_quad1_in ( gt_qpllrefclk ),//QPLL的参考时钟信号;
.gt_to_common_qpllreset_out ( gt_qpllreset ),//QPLL的复位信号;
.gt_qplllock_in ( gt_qplllock ),//QPLL的锁定信号;
.gt_qpllrefclklost_in ( gt_qpllrefclklost ),//QPLL的参考时钟失锁信号;
.gt_rxcdrovrden_in ( 1'b0 ),//input wire gt_rxcdrovrden_in
.sys_reset_out ( user_sys_reset ) //输出给用户的复位信号;
);
endmodule
然后封装高速收发器的顶层模块,由于本项目需要上板测试,因此例化两个高速收发器会比较方便,最终得到的RTL视图如下所示,两个高速收发器共用一个QPLL。
该模块的参考代码如下所示,IBUFDS_GTXE2和GT_COMMON与高速收发器的设计一致。
//--###############################################################################################
//--#
//--# File Name : aurora_module
//--# Designer : 数字站
//--# Tool : Vivado 2021.1
//--# Design Date : 2024.4.9
//--# Description : 编写aurora64B66B顶层模块
//--# Version : 0.0
//--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode)
//--#
//--###############################################################################################
module aurora_module (
input gt_refclk_p ,//GT差分参考时钟,IP设置为156.25MHZ;
input gt_refclk_n ,//GT差分参考时钟,IP设置为156.25MHZ;
input system_rst ,//系统复位信号;
input init_clk ,//初始化时钟,IP设置为100MHz。
input drp_clk ,//DRP时钟信号,IP设置为100MHz。
//QPLL的DRP接口;
input [7 : 0] qpll_drpaddr ,//QPLL的DRP地址信号;
input [15 : 0] qpll_drpdi ,//QPLL的DRP数据输入信号;
output qpll_drprdy ,//QPLL的DRP应答信号;
input qpll_drpen ,//QPLL的DRP使能信号;
input qpll_drpwe ,//QPLL的DRP读写指示信号;
output [15 : 0] qpll_drpdo ,//QPLL的DRP数据输出信号;
//GT收发器0的相关信号;
input gt_rx_p_0 ,//GT收发器的接收数据差分引脚;
input gt_rx_n_0 ,//GT收发器的接收数据差分引脚;
output user_clk_0 ,//用户参考时钟信号;
output user_reset_0 ,//输出给用户的复位信号;
input [2 : 0] gt_loopback_0 ,//GT收发器的回环模式控制信号;
output gt_tx_p_0 ,//GT收发器的发送数据差分引脚;
output gt_tx_n_0 ,//GT收发器的发送数据差分引脚;
output hard_err_0 ,//硬件错误指示信号;
output soft_err_0 ,//软件错误指示信号;
output channel_up_0 ,//通道初始化完成且通道准备好数据时拉高;
output lane_up_0 ,//单通道初始化成功信号;
input [63 : 0] s_axi_tx_tdata_0 ,//用户发送数据的AXI_STEAM流接口信号;
input [7 : 0] s_axi_tx_tkeep_0 ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tlast_0 ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tvalid_0 ,//用户发送数据的AXI_STEAM流接口信号;
output s_axi_tx_tready_0 ,//用户发送数据的AXI_STEAM流接口信号;
output [63 : 0] m_axi_rx_tdata_0 ,//用户接收数据的AXI_STEAM流接口信号;
output [7 : 0] m_axi_rx_tkeep_0 ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tlast_0 ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tvalid_0 ,//用户接收数据的AXI_STEAM流接口信号;
input [8 : 0] gt_drpaddr_0 ,//GT收发器的DRP地址信号;
input [15 : 0] gt_drpdi_0 ,//GT收发器的DRP数据输入信号;
output gt_drprdy_0 ,//GT收发器的DRP应答信号;
input gt_drpen_0 ,//GT收发器的DRP使能信号;
input gt_drpwe_0 ,//GT收发器的DRP读写指示信号;
output [15 : 0] gt_drpdo_0 ,//GT收发器的DRP数据输出信号;
//GT收发器1的相关信号;
input gt_rx_p_1 ,//GT收发器的接收数据差分引脚;
input gt_rx_n_1 ,//GT收发器的接收数据差分引脚;
output user_clk_1 ,//用户参考时钟信号;
output user_reset_1 ,//输出给用户的复位信号;
input [2 : 0] gt_loopback_1 ,//GT收发器的回环模式控制信号;
output gt_tx_p_1 ,//GT收发器的发送数据差分引脚;
output gt_tx_n_1 ,//GT收发器的发送数据差分引脚;
output hard_err_1 ,//硬件错误指示信号;
output soft_err_1 ,//软件错误指示信号;
output channel_up_1 ,//通道初始化完成且通道准备好数据时拉高;
output lane_up_1 ,//单通道初始化成功信号;
input [63 : 0] s_axi_tx_tdata_1 ,//用户发送数据的AXI_STEAM流接口信号;
input [7 : 0] s_axi_tx_tkeep_1 ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tlast_1 ,//用户发送数据的AXI_STEAM流接口信号;
input s_axi_tx_tvalid_1 ,//用户发送数据的AXI_STEAM流接口信号;
output s_axi_tx_tready_1 ,//用户发送数据的AXI_STEAM流接口信号;
output [63 : 0] m_axi_rx_tdata_1 ,//用户接收数据的AXI_STEAM流接口信号;
output [7 : 0] m_axi_rx_tkeep_1 ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tlast_1 ,//用户接收数据的AXI_STEAM流接口信号;
output m_axi_rx_tvalid_1 ,//用户接收数据的AXI_STEAM流接口信号;
input [8 : 0] gt_drpaddr_1 ,//GT收发器的DRP地址信号;
input [15 : 0] gt_drpdi_1 ,//GT收发器的DRP数据输入信号;
output gt_drprdy_1 ,//GT收发器的DRP应答信号;
input gt_drpen_1 ,//GT收发器的DRP使能信号;
input gt_drpwe_1 ,//GT收发器的DRP读写指示信号;
output [15 : 0] gt_drpdo_1 //GT收发器的DRP数据输出信号;
);
wire gt_refclk ;//GT收发器的单端时钟信号,频率为156.25MHz。
wire gt_qpllclk ;//QPLL的时钟信号;
wire gt_qpllrefclk ;//QPLL的参考时钟信号;
wire gt_qpllreset ;//QPLL的复位信号;
wire gt_qplllock ;//QPLL的锁定信号;
wire gt_qpllrefclklost ;//QPLL的参考时钟失锁信号;
//例化IBUFGDS_GTE2,将差分时钟转换为单端时钟;
IBUFDS_GTE2 IBUFDS_GTXE2_CLK1 (
.O ( gt_refclk ),//单端时钟输出信号;
.ODIV2 ( ),//单端时钟二分频输出信号;
.CEB ( 1'b0 ),//IBUFDS_GTE2使能信号;
.I ( gt_refclk_p ),//差分时钟输入信号;
.IB ( gt_refclk_n ) //差分时钟输入信号;
);
//例化QPLL模块;
aurora_64b66b_0_gt_common_wrapper gt_common_support (
.gt_qpllclk_quad1_out ( gt_qpllclk ),//QPLL的时钟信号;
.gt_qpllrefclk_quad1_out ( gt_qpllrefclk ),//QPLL的参考时钟信号;
.GT0_GTREFCLK0_COMMON_IN ( gt_refclk ),//单端时钟输出信号;
.GT0_QPLLLOCK_OUT ( gt_qplllock ),//QPLL的锁定信号;
.GT0_QPLLRESET_IN ( gt_qpllreset ),//QPLL的复位信号;
.GT0_QPLLLOCKDETCLK_IN ( init_clk ),//初始化时钟,IP设置为100MHz。
.GT0_QPLLREFCLKLOST_OUT ( gt_qpllrefclklost ),//QPLL的参考时钟失锁信号;
.qpll_drpaddr_in ( qpll_drpaddr ),//QPLL的DRP地址信号;
.qpll_drpdi_in ( qpll_drpdi ),//QPLL的DRP数据输入信号;
.qpll_drpclk_in ( drp_clk ),//DRP时钟信号,IP设置为100MHz。
.qpll_drpdo_out ( qpll_drpdo ),//QPLL的DRP数据输出信号;
.qpll_drprdy_out ( qpll_drprdy ),//QPLL的DRP应答信号;
.qpll_drpen_in ( qpll_drpen ),//QPLL的DRP使能信号;
.qpll_drpwe_in ( qpll_drpwe ) //QPLL的DRP读写指示信号;
);
//例化高速收发器0;
aurora_channel u_aurora_channel_0(
.gt_rx_p ( gt_rx_p_0 ),//GT收发器的接收数据差分引脚;
.gt_rx_n ( gt_rx_n_0 ),//GT收发器的接收数据差分引脚;
.gt_refclk ( gt_refclk ),//GT参考时钟,IP设置为156.25MHZ;
.user_clk ( user_clk_0 ),//用户参考时钟信号;
.user_sys_reset ( user_reset_0 ),//输出给用户的复位信号;
.system_rst ( system_rst ),//系统复位信号;
.gt_loopback ( gt_loopback_0 ),//GT收发器的回环模式控制信号;
.gt_tx_p ( gt_tx_p_0 ),//GT收发器的发送数据差分引脚;
.gt_tx_n ( gt_tx_n_0 ),//GT收发器的发送数据差分引脚;
.hard_err ( hard_err_0 ),//硬件错误指示信号;
.soft_err ( soft_err_0 ),//软件错误指示信号;
.channel_up ( channel_up_0 ),//通道初始化完成且通道准备好数据时拉高;
.lane_up ( lane_up_0 ),//单通道初始化成功信号;
.s_axi_tx_tdata ( s_axi_tx_tdata_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tkeep ( s_axi_tx_tkeep_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tlast ( s_axi_tx_tlast_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tvalid ( s_axi_tx_tvalid_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tready ( s_axi_tx_tready_0 ),//用户发送数据的AXI_STEAM流接口信号;
.m_axi_rx_tdata ( m_axi_rx_tdata_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tkeep ( m_axi_rx_tkeep_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tlast ( m_axi_rx_tlast_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tvalid ( m_axi_rx_tvalid_0 ),//用户接收数据的AXI_STEAM流接口信号;
.init_clk ( init_clk ),//初始化时钟,IP设置为100MHz。
.drp_clk ( drp_clk ),//DRP时钟信号,IP设置为100MHz。
.gt_drpaddr ( gt_drpaddr_0 ),//GT收发器的DRP地址信号;
.gt_drpdi ( gt_drpdi_0 ),//GT收发器的DRP数据输入信号;
.gt_drprdy ( gt_drprdy_0 ),//GT收发器的DRP应答信号;
.gt_drpen ( gt_drpen_0 ),//GT收发器的DRP使能信号;
.gt_drpwe ( gt_drpwe_0 ),//GT收发器的DRP读写指示信号;
.gt_drpdo ( gt_drpdo_0 ),//GT收发器的DRP数据输出信号;
.qpll_drpaddr ( qpll_drpaddr ),//QPLL的DRP地址信号;
.qpll_drpdi ( qpll_drpdi ),//QPLL的DRP数据输入信号;
.qpll_drpen ( qpll_drpen ),//QPLL的DRP使能信号;
.qpll_drpwe ( qpll_drpwe ),//QPLL的DRP读写指示信号;
.gt_qpllclk ( gt_qpllclk ),//QPLL的时钟信号;
.gt_qpllrefclk ( gt_qpllrefclk ),//QPLL的参考时钟信号;
.gt_qpllreset ( gt_qpllreset ),//QPLL的复位信号;
.gt_qplllock ( gt_qplllock ),//QPLL的锁定信号;
.gt_qpllrefclklost ( gt_qpllrefclklost ) //QPLL的参考时钟失锁信号;
);
//例化高速收发器1;
aurora_channel u_aurora_channel_1(
.gt_rx_p ( gt_rx_p_1 ),//GT收发器的接收数据差分引脚;
.gt_rx_n ( gt_rx_n_1 ),//GT收发器的接收数据差分引脚;
.gt_refclk ( gt_refclk ),//GT参考时钟,IP设置为156.25MHZ;
.user_clk ( user_clk_1 ),//用户参考时钟信号;
.user_sys_reset ( user_reset_1 ),//输出给用户的复位信号;
.system_rst ( system_rst ),//系统复位信号;
.gt_loopback ( gt_loopback_1 ),//GT收发器的回环模式控制信号;
.gt_tx_p ( gt_tx_p_1 ),//GT收发器的发送数据差分引脚;
.gt_tx_n ( gt_tx_n_1 ),//GT收发器的发送数据差分引脚;
.hard_err ( hard_err_1 ),//硬件错误指示信号;
.soft_err ( soft_err_1 ),//软件错误指示信号;
.channel_up ( channel_up_1 ),//通道初始化完成且通道准备好数据时拉高;
.lane_up ( lane_up_1 ),//单通道初始化成功信号;
.s_axi_tx_tdata ( s_axi_tx_tdata_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tkeep ( s_axi_tx_tkeep_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tlast ( s_axi_tx_tlast_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tvalid ( s_axi_tx_tvalid_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tready ( s_axi_tx_tready_1 ),//用户发送数据的AXI_STEAM流接口信号;
.m_axi_rx_tdata ( m_axi_rx_tdata_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tkeep ( m_axi_rx_tkeep_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tlast ( m_axi_rx_tlast_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tvalid ( m_axi_rx_tvalid_1 ),//用户接收数据的AXI_STEAM流接口信号;
.init_clk ( init_clk ),//初始化时钟,IP设置为100MHz。
.drp_clk ( drp_clk ),//DRP时钟信号,IP设置为100MHz。
.gt_drpaddr ( gt_drpaddr_1 ),//GT收发器的DRP地址信号;
.gt_drpdi ( gt_drpdi_1 ),//GT收发器的DRP数据输入信号;
.gt_drprdy ( gt_drprdy_1 ),//GT收发器的DRP应答信号;
.gt_drpen ( gt_drpen_1 ),//GT收发器的DRP使能信号;
.gt_drpwe ( gt_drpwe_1 ),//GT收发器的DRP读写指示信号;
.gt_drpdo ( gt_drpdo_1 ),//GT收发器的DRP数据输出信号;
.qpll_drpaddr ( qpll_drpaddr ),//QPLL的DRP地址信号;
.qpll_drpdi ( qpll_drpdi ),//QPLL的DRP数据输入信号;
.qpll_drpen ( qpll_drpen ),//QPLL的DRP使能信号;
.qpll_drpwe ( qpll_drpwe ),//QPLL的DRP读写指示信号;
.gt_qpllclk ( gt_qpllclk ),//QPLL的时钟信号;
.gt_qpllrefclk ( gt_qpllrefclk ),//QPLL的参考时钟信号;
.gt_qpllreset ( ),//QPLL的复位信号;
.gt_qplllock ( gt_qplllock ),//QPLL的锁定信号;
.gt_qpllrefclklost ( gt_qpllrefclklost ) //QPLL的参考时钟失锁信号;
);
endmodule
2、测试数据生成模块及顶层模块
上述整理并且调用了两个高速收发器,下面就生成需要生成用于测试的数据,并且完成各个模块的连接。
产生测试数据只要能够调节数据长度,并且便于控制尾端数据即可,参考代码如下所示。
//--###############################################################################################
//--#
//--# File Name : user_test_data
//--# Designer : 数字站
//--# Tool : Vivado 2021.1
//--# Design Date : 2024.4.9
//--# Description : 用于生成用户的测试数据;
//--# Version : 0.0
//--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode)
//--#
//--###############################################################################################
module user_test_data #(
parameter TX_DATA_LEN = 40 ,//发送一帧数据的长度;
parameter KEEP = 8'hff //最后一个数据的掩码;
)(
input clk ,//系统时钟信号;
input rst ,//系统复位信号,高电平有效;
output reg [63 : 0] m_axi_tx_tdata ,//发送数据的数据信号;
output reg [7 : 0] m_axi_tx_tkeep ,//发送数据的数据掩码信号,低电平有效;
output reg m_axi_tx_tlast ,//发送一帧数据的最后一个数据指示信号;
output reg m_axi_tx_tvalid ,//发送数据的有效指示信号;
input m_axi_tx_tready ,//发送数据的应答信号;
input [63 : 0] s_axi_rx_tdata ,//接收数据的数据信号;
input [7 : 0] s_axi_rx_tkeep ,//接收数据的数据掩码信号;
input s_axi_rx_tlast ,//接收一帧数据的最后一个数据指示信号;
input s_axi_rx_tvalid //接收数据的有效指示信号;
);
reg [6 : 0] cnt ;//
reg [5 : 0] tx_cnt ;//
//用于记录两帧数据之间的时钟个数,初始值为0,之后对时钟计数;
always@(posedge clk)begin
if(rst)begin//初始值为0;
cnt <= 7'd0;
end
else if(m_axi_tx_tvalid)begin//当处于发送数据时清零;
cnt <= 7'd0;
end
else begin//如果不处于发送数据阶段,则计数器清零;
cnt <= cnt + 7'd1;
end
end
//发送数据有效指示信号,初始值为0;
always@(posedge clk)begin
if(rst)begin//初始值为0;
m_axi_tx_tvalid <= 1'b0;
end
else if(m_axi_tx_tlast && m_axi_tx_tready)begin//发送最后一个后拉低;
m_axi_tx_tvalid <= 1'b0;
end
else if(&cnt)begin//当计数器计数到最大值时发送一帧数据,此时拉高;
m_axi_tx_tvalid <= 1'b1;
end
end
//用于生成产生数据个数的计数器,初始值为0,当发送指定个数数据时清零
always@(posedge clk)begin
if(rst)begin//初始值为0;
tx_cnt <= 'd0;
end
else if(m_axi_tx_tvalid && m_axi_tx_tready)begin//当发送端和接收端握手时
if(tx_cnt == TX_DATA_LEN - 1)//如果发完指定数据则清零;
tx_cnt <= 'd0;
else//否则计数器加1;
tx_cnt <= tx_cnt + 'd1;
end
end
//生成测试数据;
always@(posedge clk)begin
if(rst)begin//初始值为0;
m_axi_tx_tdata <= 32'd0;
end
else if(m_axi_tx_tlast && m_axi_tx_tvalid)begin//当发送完最后一个数据时清零;
m_axi_tx_tdata <= 32'd0;
end
else if(m_axi_tx_tvalid && m_axi_tx_tready)begin
m_axi_tx_tdata <= {{tx_cnt[4:0],3'd0},{tx_cnt[4:0],3'd1},{tx_cnt[4:0],3'd2},{tx_cnt[4:0],3'd3},
{tx_cnt[4:0],3'd4},{tx_cnt[4:0],3'd5},{tx_cnt[4:0],3'd6},{tx_cnt[4:0],3'd7}};
end
end
//一帧数据最后一个指示信号,初始值为0;
always@(posedge clk)begin
if(rst)begin//初始值为0;
m_axi_tx_tlast <= 1'b0;
end
else if(m_axi_tx_tvalid && m_axi_tx_tready)begin//当发送最后一个数据时拉高,其余时间保持不变;
if(tx_cnt == TX_DATA_LEN - 2)
m_axi_tx_tlast <= 1'b1;
else if(tx_cnt == TX_DATA_LEN - 1)
m_axi_tx_tlast <= 1'b0;
end
end
//生成数据掩码信号
always@(posedge clk)begin
if(rst)begin//初始值为4'b1111;
m_axi_tx_tkeep <= 8'hff;
end
else if(m_axi_tx_tvalid && m_axi_tx_tready)begin
if(tx_cnt == TX_DATA_LEN - 2)//最后一个数据的掩码信号;
m_axi_tx_tkeep <= KEEP;
else if(tx_cnt == TX_DATA_LEN - 1)
m_axi_tx_tkeep <= 8'hff;
end
else begin
m_axi_tx_tkeep <= 8'hff;
end
end
endmodule
最后是将上述各个模块例化,得到顶层模块,对应的RTL视图如下所示。
顶层模块的参考代码如下所示:
//--###############################################################################################
//--#
//--# File Name : top
//--# Designer : 数字站
//--# Tool : Vivado 2021.1
//--# Design Date : 2024.4.9
//--# Description : aurora64B66B顶层模块;
//--# Version : 0.0
//--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode)
//--#
//--###############################################################################################
module top (
input clk ,//系统时钟信号;
input rst_n ,//系统复位信号,低电平有效;
input gt_refclk_p ,//gt差分参考时钟信号;
input gt_refclk_n ,//gt差分参考时钟信号;
input gt_rx_p_0 ,//gt接收差分数据线;
input gt_rx_n_0 ,//gt接收差分数据线;
output gt_tx_p_0 ,//gt发送差分数据线;
output gt_tx_n_0 ,//gt发送差分数据线;
input gt_rx_p_1 ,//gt接收差分数据线;
input gt_rx_n_1 ,//gt接收差分数据线;
output gt_tx_p_1 ,//gt发送差分数据线;
output gt_tx_n_1 ,//gt发送差分数据线;
output [1 :0] dislabe //光电转换模块失能信号;
);
wire system_rst ;//系统复位信号;
//GT收发器0的相关信号;
wire user_clk_0 ;//用户参考时钟信号;
wire user_reset_0 ;//输出给用户的复位信号;
(* MARK_DEBUG = "TRUE" *)wire hard_err_0 ;//硬件错误指示信号;
(* MARK_DEBUG = "TRUE" *)wire soft_err_0 ;//软件错误指示信号;
(* MARK_DEBUG = "TRUE" *)wire channel_up_0 ;//通道初始化完成且通道准备好数据时拉高;
(* MARK_DEBUG = "TRUE" *)wire lane_up_0 ;//单通道初始化成功信号;
(* MARK_DEBUG = "TRUE" *)wire [63 : 0] s_axi_tx_tdata_0 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [7 : 0] s_axi_tx_tkeep_0 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tlast_0 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tvalid_0 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tready_0 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [63 : 0] m_axi_rx_tdata_0 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [7 : 0] m_axi_rx_tkeep_0 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire m_axi_rx_tlast_0 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire m_axi_rx_tvalid_0 ;//用户接收数据的AXI_STEAM流接口信号;
//GT收发器1的相关信号;
wire user_clk_1 ;//用户参考时钟信号;
wire user_reset_1 ;//输出给用户的复位信号;
(* MARK_DEBUG = "TRUE" *)wire hard_err_1 ;//硬件错误指示信号;
(* MARK_DEBUG = "TRUE" *)wire soft_err_1 ;//软件错误指示信号;
(* MARK_DEBUG = "TRUE" *)wire channel_up_1 ;//通道初始化完成且通道准备好数据时拉高;
(* MARK_DEBUG = "TRUE" *)wire lane_up_1 ;//单通道初始化成功信号;
(* MARK_DEBUG = "TRUE" *)wire [63 : 0] s_axi_tx_tdata_1 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [7 : 0] s_axi_tx_tkeep_1 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tlast_1 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tvalid_1 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire s_axi_tx_tready_1 ;//用户发送数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [63 : 0] m_axi_rx_tdata_1 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire [7 : 0] m_axi_rx_tkeep_1 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire m_axi_rx_tlast_1 ;//用户接收数据的AXI_STEAM流接口信号;
(* MARK_DEBUG = "TRUE" *)wire m_axi_rx_tvalid_1 ;//用户接收数据的AXI_STEAM流接口信号;
assign dislabe = 2'd0;
//例化复位同步模块;
rst_syc_module #(
.RST_IN_VLD ( 1'b0 ),//复位输入有效电平,默认低电平;
.RST_OUT_VLD ( 1'b1 ),//复位输出有效电平,默认高电平;
.RST_CYCLE ( 8 ) //同步时钟个数;
)
rst_syc_module (
.clk ( clk ),//系统时钟信号;
.rst_n_in ( rst_n ),//复位输入信号,默认低电平有效;
.rst_out ( system_rst) //复位输出信号,默认高电平有效;
);
//例化生成用户测试数据模块0.
user_test_data #(
.TX_DATA_LEN ( 20 ),//发送一帧数据的长度;
.KEEP ( 8'hfc ) //最后一个数据的掩码;
)
u_user_test_data_0 (
.clk ( user_clk_0 ),//系统时钟信号;
.rst ( user_reset_0 ),//系统复位信号,高电平有效;
.m_axi_tx_tdata ( s_axi_tx_tdata_0 ),//发送数据的数据信号;
.m_axi_tx_tkeep ( s_axi_tx_tkeep_0 ),//发送数据的数据掩码信号,低电平有效;
.m_axi_tx_tlast ( s_axi_tx_tlast_0 ),//发送一帧数据的最后一个数据指示信号;
.m_axi_tx_tvalid ( s_axi_tx_tvalid_0 ),//发送数据的有效指示信号;
.m_axi_tx_tready ( s_axi_tx_tready_0 ),//发送数据的应答信号;
.s_axi_rx_tdata ( m_axi_rx_tdata_0 ),//接收数据的数据信号;
.s_axi_rx_tkeep ( m_axi_rx_tkeep_0 ),//接收数据的数据掩码信号;
.s_axi_rx_tlast ( m_axi_rx_tlast_0 ),//接收一帧数据的最后一个数据指示信号;
.s_axi_rx_tvalid ( m_axi_rx_tvalid_0 ) //接收数据的有效指示信号;
);
//例化生成用户测试数据模块1.
user_test_data #(
.TX_DATA_LEN ( 20 ),//发送一帧数据的长度;
.KEEP ( 8'hf0 ) //最后一个数据的掩码;
)
u_user_test_data_1 (
.clk ( user_clk_1 ),//系统时钟信号;
.rst ( user_reset_1 ),//系统复位信号,高电平有效;
.m_axi_tx_tdata ( s_axi_tx_tdata_1 ),//发送数据的数据信号;
.m_axi_tx_tkeep ( s_axi_tx_tkeep_1 ),//发送数据的数据掩码信号,低电平有效;
.m_axi_tx_tlast ( s_axi_tx_tlast_1 ),//发送一帧数据的最后一个数据指示信号;
.m_axi_tx_tvalid ( s_axi_tx_tvalid_1 ),//发送数据的有效指示信号;
.m_axi_tx_tready ( s_axi_tx_tready_1 ),//发送数据的应答信号;
.s_axi_rx_tdata ( m_axi_rx_tdata_1 ),//接收数据的数据信号;
.s_axi_rx_tkeep ( m_axi_rx_tkeep_1 ),//接收数据的数据掩码信号;
.s_axi_rx_tlast ( m_axi_rx_tlast_1 ),//接收一帧数据的最后一个数据指示信号;
.s_axi_rx_tvalid ( m_axi_rx_tvalid_1 ) //接收数据的有效指示信号;
);
//例化两个通道的GT收发器;
aurora_module u_aurora_module(
.gt_refclk_p ( gt_refclk_p ),//GT差分参考时钟,IP设置为156.25MHZ;
.gt_refclk_n ( gt_refclk_n ),//GT差分参考时钟,IP设置为156.25MHZ;
.system_rst ( system_rst ),//系统复位信号;
.init_clk ( clk ),//初始化时钟,IP设置为100MHz。
.drp_clk ( clk ),//DRP时钟信号,IP设置为100MHz。
//QPLL的DRP接口;
.qpll_drpaddr ( 0 ),//QPLL的DRP地址信号;
.qpll_drpdi ( 0 ),//QPLL的DRP数据输入信号;
.qpll_drprdy ( ),//QPLL的DRP应答信号;
.qpll_drpen ( 0 ),//QPLL的DRP使能信号;
.qpll_drpwe ( 0 ),//QPLL的DRP读写指示信号;
.qpll_drpdo ( ),//QPLL的DRP数据输出信号;
//GT收发器0的相关信号;
.gt_rx_p_0 ( gt_rx_p_0 ),//GT收发器的接收数据差分引脚;
.gt_rx_n_0 ( gt_rx_n_0 ),//GT收发器的接收数据差分引脚;
.user_clk_0 ( user_clk_0 ),//用户参考时钟信号;
.user_reset_0 ( user_reset_0 ),//输出给用户的复位信号;
.gt_loopback_0 ( 3'b000 ),//GT收发器的回环模式控制信号;
.gt_tx_p_0 ( gt_tx_p_0 ),//GT收发器的发送数据差分引脚;
.gt_tx_n_0 ( gt_tx_n_0 ),//GT收发器的发送数据差分引脚;
.hard_err_0 ( hard_err_0 ),//硬件错误指示信号;
.soft_err_0 ( soft_err_0 ),//软件错误指示信号;
.channel_up_0 ( channel_up_0 ),//通道初始化完成且通道准备好数据时拉高;
.lane_up_0 ( lane_up_0 ),//单通道初始化成功信号;
.s_axi_tx_tdata_0 ( s_axi_tx_tdata_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tkeep_0 ( s_axi_tx_tkeep_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tlast_0 ( s_axi_tx_tlast_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tvalid_0 ( s_axi_tx_tvalid_0 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tready_0 ( s_axi_tx_tready_0 ),//用户发送数据的AXI_STEAM流接口信号;
.m_axi_rx_tdata_0 ( m_axi_rx_tdata_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tkeep_0 ( m_axi_rx_tkeep_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tlast_0 ( m_axi_rx_tlast_0 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tvalid_0 ( m_axi_rx_tvalid_0 ),//用户接收数据的AXI_STEAM流接口信号;
.gt_drpaddr_0 ( 0 ),//GT收发器的DRP地址信号;
.gt_drpdi_0 ( 0 ),//GT收发器的DRP数据输入信号;
.gt_drprdy_0 ( ),//GT收发器的DRP应答信号;
.gt_drpen_0 ( 0 ),//GT收发器的DRP使能信号;
.gt_drpwe_0 ( 0 ),//GT收发器的DRP读写指示信号;
.gt_drpdo_0 ( ),//GT收发器的DRP数据输出信号;
//GT收发器1的相关信号;
.gt_rx_p_1 ( gt_rx_p_1 ),//GT收发器的接收数据差分引脚;
.gt_rx_n_1 ( gt_rx_n_1 ),//GT收发器的接收数据差分引脚;
.user_clk_1 ( user_clk_1 ),//用户参考时钟信号;
.user_reset_1 ( user_reset_1 ),//输出给用户的复位信号;
.gt_loopback_1 ( 3'b000 ),//GT收发器的回环模式控制信号;
.gt_tx_p_1 ( gt_tx_p_1 ),//GT收发器的发送数据差分引脚;
.gt_tx_n_1 ( gt_tx_n_1 ),//GT收发器的发送数据差分引脚;
.hard_err_1 ( hard_err_1 ),//硬件错误指示信号;
.soft_err_1 ( soft_err_1 ),//软件错误指示信号;
.channel_up_1 ( channel_up_1 ),//通道初始化完成且通道准备好数据时拉高;
.lane_up_1 ( lane_up_1 ),//单通道初始化成功信号;
.s_axi_tx_tdata_1 ( s_axi_tx_tdata_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tkeep_1 ( s_axi_tx_tkeep_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tlast_1 ( s_axi_tx_tlast_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tvalid_1 ( s_axi_tx_tvalid_1 ),//用户发送数据的AXI_STEAM流接口信号;
.s_axi_tx_tready_1 ( s_axi_tx_tready_1 ),//用户发送数据的AXI_STEAM流接口信号;
.m_axi_rx_tdata_1 ( m_axi_rx_tdata_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tkeep_1 ( m_axi_rx_tkeep_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tlast_1 ( m_axi_rx_tlast_1 ),//用户接收数据的AXI_STEAM流接口信号;
.m_axi_rx_tvalid_1 ( m_axi_rx_tvalid_1 ),//用户接收数据的AXI_STEAM流接口信号;
.gt_drpaddr_1 ( 0 ),//GT收发器的DRP地址信号;
.gt_drpdi_1 ( 0 ),//GT收发器的DRP数据输入信号;
.gt_drprdy_1 ( ),//GT收发器的DRP应答信号;
.gt_drpen_1 ( 0 ),//GT收发器的DRP使能信号;
.gt_drpwe_1 ( 0 ),//GT收发器的DRP读写指示信号;
.gt_drpdo_1 ( ) //GT收发器的DRP数据输出信号;
);
endmodule
3、工程仿真
测试激励如下所示,将两个收发器的短接即可。
//--###############################################################################################
//--#
//--# File Name : tb_top
//--# Designer : 数字站
//--# Tool : Vivado 2021.1
//--# Design Date : 2024.4.9
//--# Description : TestBentch
//--# Version : 0.0
//--# Coding scheme : GBK(If the Chinese comment of the file is garbled, please do not save it and check whether the file is opened in GBK encoding mode)
//--#
//--###############################################################################################
`timescale 1ns / 1ps
module tb_top ();
localparam CYCLE = 10 ;//系统时钟周期,单位ns,默认10ns;
localparam RST_TIME = 10 ;//系统复位持续时间,默认10个系统时钟周期;
reg clk ;//系统时钟,默认100MHz;
reg rst_n ;//系统复位,默认低电平有效;
reg gt_refclk_p ;//gt差分参考时钟信号;
reg gt_refclk_n ;//gt差分参考时钟信号;
wire gt_rx_p_0 ;//gt接收差分数据线;
wire gt_rx_n_0 ;//gt接收差分数据线;
wire gt_tx_p_0 ;//gt发送差分数据线;
wire gt_tx_n_0 ;//gt发送差分数据线;
wire gt_rx_p_1 ;//gt接收差分数据线;
wire gt_rx_n_1 ;//gt接收差分数据线;
wire gt_tx_p_1 ;//gt发送差分数据线;
wire gt_tx_n_1 ;//gt发送差分数据线;
wire [1 :0] dislabe ;//光电转换模块失能信号;
assign gt_rx_p_0 = gt_tx_p_1;
assign gt_rx_n_0 = gt_tx_n_1;
assign gt_rx_p_1 = gt_tx_p_0;
assign gt_rx_n_1 = gt_tx_n_0;
//例化待测试模块
top u_top (
.clk ( clk ),//系统时钟信号;
.rst_n ( rst_n ),//系统复位信号,低电平有效;
.gt_refclk_p ( gt_refclk_p ),//gt差分参考时钟信号;
.gt_refclk_n ( gt_refclk_n ),//gt差分参考时钟信号;
.gt_rx_p_0 ( gt_rx_p_0 ),//gt接收差分数据线;
.gt_rx_n_0 ( gt_rx_n_0 ),//gt接收差分数据线;
.gt_tx_p_0 ( gt_tx_p_0 ),//gt发送差分数据线;
.gt_tx_n_0 ( gt_tx_n_0 ),//gt发送差分数据线;
.gt_rx_p_1 ( gt_rx_p_1 ),//gt接收差分数据线;
.gt_rx_n_1 ( gt_rx_n_1 ),//gt接收差分数据线;
.gt_tx_p_1 ( gt_tx_p_1 ),//gt发送差分数据线;
.gt_tx_n_1 ( gt_tx_n_1 ),//gt发送差分数据线;
.dislabe ( dislabe ) //光电转换模块失能信号;
);
//生成周期为CYCLE数值的系统时钟;
initial begin
clk = 0;
forever #(CYCLE/2) clk = ~clk;
end
//生成频率为156.25MHz的差分时钟;
initial begin
gt_refclk_p = 0;
forever #3.2 gt_refclk_p = ~gt_refclk_p;
end
initial begin
gt_refclk_n = 1;
forever #3.2 gt_refclk_n = ~gt_refclk_n;
end
//生成复位信号;
initial begin
rst_n = 1;
#2;
rst_n = 0;//开始时复位10个时钟;
#(RST_TIME*CYCLE);
rst_n = 1;
end
endmodule
总体仿真结果如下所示,两个高速收发器均在一段时间后初始化完成,注意两个高速收发器初始化完成的时间可能会不相同。
如下图所示,高速收发器0向高速收发器1发送一帧数据。
将上图高速收发器0发送的一帧数据放大,如下图所示,得知发送的最后一个有效字节数据为8’h95。
把图5中高速收发器1接收的一帧数据放大,得到下图所示时序,接收最后一个有效字节数据为8’h95,与发送的数据保持一致,证明高速收发器0发送数据和高速收发器1接收数据的相关时序正常。
下图是高速收发器向高速收发器0发送一帧数据的时序。
将上图中的高速收发器1的发送数据时序放大,如下图所示,得到高速收发器1发送一帧数据的最后有效字节为8’h93。
把图8的高速收发器0接收的一帧数据放大,接收的最后一个有效字节数据也是8’h93,与高速收发器1发送的数据一致。
由此证明高速收发器1发送数据和高速收发器0接收数据的时序正常。
经过上述仿真,证明高速收发器0和高速收发器1的相关逻辑均正常,下面开始进行上板设计。
4、工程上板
综合上述工程,然后分配管脚,生成bit流,下载到开发板,通过ILA抓取数据。两个高速收发器驱动两路光口,两个光口通过光纤短接,开发板连接示意图如下所示。
上电一段时间之后,两路高速收发器的初始化完成,各自通道的初始化完成信号拉高。
然后使用ILA抓取两个高速收发器的收发数据是否正常,下图是高速收发器0发送一帧数据的时序,与前文仿真结果一致,发送数据最后一个有效字节数据为8’h95。
抓取高速收发器1接收一帧数据的时序如下,与上图高速收发器0发送的数据一致,且与仿真结果一致。
下图是高速收发器1发送一帧数据的时序,最后一个有效字节数据为8’h93,与前文仿真结果一致。
下图是高速收发器0接收一帧数据的时序,与高速收发器1发送数据一致,应证仿真结果的正确性。
综上,该IP的通常使用方式和扩展封装方式就讲解完毕了,如果熟悉了前文的基于GTX的64B66B开发,那么本文Aurora 64B/66B IP的开发简直没有难度,用户只需要发送和接收数据即可,加扰、解扰、接收端数据对齐都需要考虑。
后文可能会讲解该IP的流控使用方式,毕竟这才是这个IP的关键吧,常规使用与GTX其实差不多,但是GTX一般用户都不会做流控处理。
本文的工程项目可以在公众号后台回复“Aurora 64B/66B回环测试”(不包含引号)获取。
如果对文章内容理解有疑惑或者对代码不理解,可以在评论区或者后台留言,看到后均会回复!
如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!您的支持是我更新的最大动力!将持续更新工程!