整理Aurora 64B/66B示例工程并上板测试(高速收发器二十五)

  点击进入高速收发器系列文章导航界面


注意本文的IP整理思路及回环测试思路来自奇哥高速教程,经过奇哥允许后对该工程开源,文末有源工程获取方式

1、整理Aurora 64B/66B的IP

  如下图所示,每个高速收发器都可以包含复位逻辑和时钟信号,因此在每个通道内部都会封装复位同步模块和MMCM调用模块,如下图所示。

  将Aurora 64B/66B的一些专用信号引出即可。

在这里插入图片描述

图1 整理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。

在这里插入图片描述

图2 整理Aurora 64B/66B顶层模块

  该模块的参考代码如下所示,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视图如下所示。

在这里插入图片描述

图3 工程顶层模块

  顶层模块的参考代码如下所示:

//--###############################################################################################
//--#
//--# 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

  总体仿真结果如下所示,两个高速收发器均在一段时间后初始化完成,注意两个高速收发器初始化完成的时间可能会不相同。

在这里插入图片描述

图4 总体仿真

  如下图所示,高速收发器0向高速收发器1发送一帧数据。

在这里插入图片描述

图5 收发器0向收发器1发送一帧数据

  将上图高速收发器0发送的一帧数据放大,如下图所示,得知发送的最后一个有效字节数据为8’h95。

在这里插入图片描述

图6 高速收发器0发送一帧数据的时序

  把图5中高速收发器1接收的一帧数据放大,得到下图所示时序,接收最后一个有效字节数据为8’h95,与发送的数据保持一致,证明高速收发器0发送数据和高速收发器1接收数据的相关时序正常。

在这里插入图片描述

图7 高速收发器1接收一帧数据的时序

  下图是高速收发器向高速收发器0发送一帧数据的时序。

在这里插入图片描述

图8 收发器1向收发器0发送一帧数据

  将上图中的高速收发器1的发送数据时序放大,如下图所示,得到高速收发器1发送一帧数据的最后有效字节为8’h93。

在这里插入图片描述

图9 高速收发器1发送一帧数据的时序

  把图8的高速收发器0接收的一帧数据放大,接收的最后一个有效字节数据也是8’h93,与高速收发器1发送的数据一致。

  由此证明高速收发器1发送数据和高速收发器0接收数据的时序正常。

在这里插入图片描述

图10 高速收发器0接收一帧数据的时序

  经过上述仿真,证明高速收发器0和高速收发器1的相关逻辑均正常,下面开始进行上板设计。

4、工程上板

  综合上述工程,然后分配管脚,生成bit流,下载到开发板,通过ILA抓取数据。两个高速收发器驱动两路光口,两个光口通过光纤短接,开发板连接示意图如下所示。

在这里插入图片描述

图11 开发板连接

  上电一段时间之后,两路高速收发器的初始化完成,各自通道的初始化完成信号拉高。

在这里插入图片描述

图12 高速收发器初始化完成时序

  然后使用ILA抓取两个高速收发器的收发数据是否正常,下图是高速收发器0发送一帧数据的时序,与前文仿真结果一致,发送数据最后一个有效字节数据为8’h95。

在这里插入图片描述

图13 高速收发器0发送一帧数据

  抓取高速收发器1接收一帧数据的时序如下,与上图高速收发器0发送的数据一致,且与仿真结果一致。

在这里插入图片描述

图14 高速收发器1接收一帧数据

  下图是高速收发器1发送一帧数据的时序,最后一个有效字节数据为8’h93,与前文仿真结果一致。

在这里插入图片描述

图15 高速收发器1发送一帧数据

  下图是高速收发器0接收一帧数据的时序,与高速收发器1发送数据一致,应证仿真结果的正确性。
在这里插入图片描述

图16 高速收发器0接收一帧数据

  综上,该IP的通常使用方式和扩展封装方式就讲解完毕了,如果熟悉了前文的基于GTX的64B66B开发,那么本文Aurora 64B/66B IP的开发简直没有难度,用户只需要发送和接收数据即可,加扰、解扰、接收端数据对齐都需要考虑。

  后文可能会讲解该IP的流控使用方式,毕竟这才是这个IP的关键吧,常规使用与GTX其实差不多,但是GTX一般用户都不会做流控处理。

  本文的工程项目可以在公众号后台回复“Aurora 64B/66B回环测试”(不包含引号)获取。


  如果对文章内容理解有疑惑或者对代码不理解,可以在评论区或者后台留言,看到后均会回复!

  如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!您的支持是我更新的最大动力!将持续更新工程!

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电路_fpga

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值