Aurora 64B 66B两种流量控制的使用方式(高速收发器二十七)

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


  前文对官方Aurora 64B66B的官方示例工程做了简要讲解,本文将整理该IP,并且实现UFC和NFC流控测试。

  为了测试简单,当接收端接收到一定数据时,通过NFC让发送端暂停数据发送。当按键按下时,通过UFC向接收端发送一帧指定长度的数据。

1、整理Aurora 64B66B工程

  首先跟前面几个工程一样,整理底层IP的通道文件,便于后续扩展,整理过程参考示例工程,整理后的通道模块的RTL视图如下所示。

在这里插入图片描述

图1 通道模块内部结构

  上图的相关模块表示一个高速收发器内部所需要的模块,在上层多次调用该模块,即可例化多个高速收发器。

  参考代码如下所示:

//--###############################################################################################
//--#
//--# File Name		: aurora_64b66b_channel
//--# Designer		: 数字站
//--# Tool			: Vivado 2021.1
//--# Design Date	: 2024.5.25
//--# 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_64b66b_channel (
    input                                   gt_refclk           ,//GT参考时钟,IP设置为156.25MHZ;
    input                                   system_rst          ,//将系统复位作为GT复位;
    output                                  user_clk            ,//输入用户时钟信号,频率与txusrclk2一致;
    output                                  user_reset          ,//输出用户端的系统复位信号;  
    input                                   ufc_tx_req          ,//用户流量控制请求信号,高电平有效;
    input           [7 : 0]                 ufc_tx_ms           ,//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    output                                  ufc_in_progress     ,//低电平表示高速收发器正在接收用户流量控制数据;
    input                                   gt_rx_p             ,//高速收发器的接收差分引脚;
    input                                   gt_rx_n             ,//高速收发器的接收差分引脚;
    input           [2 : 0]                 loopback            ,//回环模式控制信号;
    output                                  gt_tx_p             ,//高速收发器的发送差分引脚;
    output                                  gt_tx_n             ,//高速收发器的发送差分引脚;
    output                                  hard_err            ,//硬件错误指示信号;
    output                                  soft_err            ,//软件错误指示信号;
    output                                  channel_up          ,//通道和内核初始化完成指示信号;
    output                                  lane_up             ,//通道初始化完成指示信号;
    input           [63 : 0]                s_axi_tx_data       ,//用户发送数据端口的数据信号;
    input           [7 : 0]                 s_axi_tx_keep       ,//用户发送数据端口的尾端数据掩码信号;
    input                                   s_axi_tx_last       ,//用户发送数据端口的尾端数据指示信号;
    input                                   s_axi_tx_valid      ,//用户发送数据端口的有效数据指示信号;
    output                                  s_axi_tx_ready      ,//用户发送数据端口的接收数据应答信号;
    input                                   s_axi_nfc_valid     ,//本地流量控制的数据有效指示信号;
    input           [15 : 0]                s_axi_nfc_data      ,//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    output                                  s_axi_nfc_ready     ,//本地流量控制的接收数据应答指示信号;
    input           [63 : 0]                s_axi_ufc_tx_data   ,//用户流量控制发送端口的数据信号;
    input                                   s_axi_ufc_tx_valid  ,//用户流量控制发送端口的数据有效指示信号;
    output                                  s_axi_ufc_tx_ready  ,//用户流量控制发送端口的接收数据应答指示信号;
    output          [63 : 0]                m_axi_rx_data       ,//用户接收数据端口的数据信号;
    output          [7 : 0]                 m_axi_rx_keep       ,//用户接收数据端口的尾端数据掩码信号;
    output                                  m_axi_rx_last       ,//用户接收数据端口的尾端数据指示信号;
    output                                  m_axi_rx_valid      ,//用户接收数据端口的有效数据指示信号;
    output          [63 : 0]                m_axi_ufc_rx_data   ,//用户流量控制接收端口的数据信号;
    output          [7 : 0]                 m_axi_ufc_rx_keep   ,//用户流量控制接收端口的尾端数据掩码信号;
    output                                  m_axi_ufc_rx_last   ,//用户流量控制接收端口的尾端数据指示信号;
    output                                  m_axi_ufc_rx_valid  ,//用户流量控制接收端口的数据有效指示信号;
    input                                   init_clk            ,//初始化时钟信号,频率设置为100MHz;
    input                                   drp_clk             ,//DRP时钟信号,频率设置为100MHz;
    input           [8 : 0]                 gt_drpaddr          ,//高速收发器动态配置端口的地址信号;
    input           [15 : 0]                gt_drpdi            ,//高速收发器动态配置端口的输入数据信号;
    output                                  gt_drprdy           ,//高速收发器动态配置端口的忙闲信号;
    input                                   gt_drpen            ,//高速收发器动态配置端口的使能信号;
    input                                   gt_drpwe            ,//高速收发器动态配置端口的读写指示信号;
    output           [15 : 0]               gt_drpdo            ,//高速收发器动态配置端口的输出数据信号;
    input           [7 : 0]                 qpll_drpaddr        ,//QPLL动态重配置端口的地址信号;
    input           [15 : 0]                qpll_drpdi          ,//QPLL动态重配置端口的输入数据信号;
    input                                   qpll_drpen          ,//QPLL动态重配置端口的使能信号;
    input                                   qpll_drpwe          ,//QPLL动态重配置端口的读写指示信号;
    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         ;//MMCM锁定信号;
    wire                                    sync_clk            ;//同步时钟信号;
    wire                                    mmcm_not_locked     ;//MMCM没有锁定信号;
    wire                                    reset_pb            ;//内核复位信号;
    wire                                    gt_rst              ;//GT收发器复位信号;

    //例化复位模块;
    aurora_64b66b_0_SUPPORT_RESET_LOGIC support_reset_logic(
        .RESET          ( 1'b0    ),//将系统复位作为内核复位;
        .USER_CLK       ( user_clk      ),//用户时钟信号;
        .INIT_CLK       ( init_clk      ),//初始化时钟;
        .GT_RESET_IN    ( system_rst    ),//将高速收发器复位设置为无效;
        .SYSTEM_RESET   ( reset_pb      ),//内核复位信号;
        .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没有锁定信号;
    );

    //例化IP;
    aurora_64b66b_0 u_aurora_64b66b(
        .ufc_tx_req                 ( ufc_tx_req                ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms                  ( ufc_tx_ms                 ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .ufc_in_progress            ( ufc_in_progress           ),//低电平表示高速收发器正在接收用户流量控制数据;
        .rxp                        ( gt_rx_p                   ),//高速收发器的接收差分引脚;
        .rxn                        ( gt_rx_n                   ),//高速收发器的接收差分引脚;
        .refclk1_in                 ( gt_refclk                 ),//高速收发器的参考时钟信号;
        .user_clk                   ( user_clk                  ),//输入用户时钟信号,频率与txusrclk2一致;
        .sync_clk                   ( sync_clk                  ),//输入同步时钟信号;
        .reset_pb                   ( reset_pb                  ),//内核复位信号;
        .power_down                 ( 1'b0                      ),//掉电模式控制信号;
        .pma_init                   ( gt_rst                    ),//高速收发器复位信号;
        .loopback                   ( loopback                  ),//回环模式控制信号;
        .txp                        ( gt_tx_p                   ),//高速收发器的发送差分引脚;
        .txn                        ( gt_tx_n                   ),//高速收发器的发送差分引脚;
        .hard_err                   ( hard_err                  ),//硬件错误指示信号;
        .soft_err                   ( soft_err                  ),//软件错误指示信号;
        .channel_up                 ( channel_up                ),//通道和内核初始化完成指示信号;
        .lane_up                    ( lane_up                   ),//通道初始化完成指示信号;
        .tx_out_clk                 ( tx_out_clk                ),//发送通道的参考时钟信号;
        .drp_clk_in                 ( drp_clk                   ),//DRP时钟信号,频率设置为100MHz;
        .gt_pll_lock                ( gt_pll_lock               ),//高速收发器的QPLL锁定信号;
        .s_axi_tx_tdata             ( s_axi_tx_data             ),//用户发送数据端口的数据信号;
        .s_axi_tx_tkeep             ( s_axi_tx_keep             ),//用户发送数据端口的尾端数据掩码信号;
        .s_axi_tx_tlast             ( s_axi_tx_last             ),//用户发送数据端口的尾端数据指示信号;
        .s_axi_tx_tvalid            ( s_axi_tx_valid            ),//用户发送数据端口的有效数据指示信号;
        .s_axi_tx_tready            ( s_axi_tx_ready            ),//用户发送数据端口的接收数据应答信号;
        .s_axi_nfc_tvalid           ( s_axi_nfc_valid           ),//本地流量控制的数据有效指示信号;
        .s_axi_nfc_tdata            ( s_axi_nfc_data            ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .s_axi_nfc_tready           ( s_axi_nfc_ready           ),//本地流量控制的接收数据应答指示信号;
        .s_axi_ufc_tx_tdata         ( s_axi_ufc_tx_data         ),//用户流量控制发送端口的数据信号;
        .s_axi_ufc_tx_tvalid        ( s_axi_ufc_tx_valid        ),//用户流量控制发送端口的数据有效指示信号;
        .s_axi_ufc_tx_tready        ( s_axi_ufc_tx_ready        ),//用户流量控制发送端口的接收数据应答指示信号;
        .m_axi_rx_tdata             ( m_axi_rx_data             ),//用户接收数据端口的数据信号;
        .m_axi_rx_tkeep             ( m_axi_rx_keep             ),//用户接收数据端口的尾端数据掩码信号;
        .m_axi_rx_tlast             ( m_axi_rx_last             ),//用户接收数据端口的尾端数据指示信号;
        .m_axi_rx_tvalid            ( m_axi_rx_valid            ),//用户接收数据端口的有效数据指示信号;
        .m_axi_ufc_rx_tdata         ( m_axi_ufc_rx_data         ),//用户流量控制接收端口的数据信号;
        .m_axi_ufc_rx_tkeep         ( m_axi_ufc_rx_keep         ),//用户流量控制接收端口的尾端数据掩码信号;
        .m_axi_ufc_rx_tlast         ( m_axi_ufc_rx_last         ),//用户流量控制接收端口的尾端数据指示信号;
        .m_axi_ufc_rx_tvalid        ( m_axi_ufc_rx_valid        ),//用户流量控制接收端口的数据有效指示信号;
        .mmcm_not_locked            ( mmcm_not_locked           ),//MMCM失锁信号;
        .drpaddr_in                 ( gt_drpaddr                ),//高速收发器动态配置端口的地址信号;
        .drpdi_in                   ( gt_drpdi                  ),//高速收发器动态配置端口的输入数据信号;
        .drprdy_out                 ( gt_drprdy                 ),//高速收发器动态配置端口的忙闲信号;
        .drpen_in                   ( gt_drpen                  ),//高速收发器动态配置端口的使能信号;
        .drpwe_in                   ( gt_drpwe                  ),//高速收发器动态配置端口的读写指示信号;
        .drpdo_out                  ( gt_drpdo                  ),//高速收发器动态配置端口的输出数据信号;
        .qpll_drpaddr_in            ( qpll_drpaddr              ),//QPLL动态重配置端口的地址信号;
        .qpll_drpdi_in              ( qpll_drpdi                ),//QPLL动态重配置端口的输入数据信号;
        .qpll_drprdy_out            (                           ),//QPLL动态重配置端口的忙闲信号;
        .qpll_drpen_in              ( qpll_drpen                ),//QPLL动态重配置端口的使能信号;
        .qpll_drpwe_in              ( qpll_drpwe                ),//QPLL动态重配置端口的读写指示信号;
        .qpll_drpdo_out             (                           ),//QPLL动态重配置端口的输出数据信号;
        .init_clk                   ( init_clk                  ),//初始化时钟信号,频率设置为100MHz;
        .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_reset                ) //输出用户端的系统复位信号;
    );
    
endmodule

  下图是高速收发器顶层模块,内部例化两个高速收发器,共用同一个QPLL,但是只有高速收发器0能够复位QPLL。如果要使用更多的高速收发器,只需要多次例化图1模块即可。

在这里插入图片描述

图2 高速收发器顶层模块RTL视图

  高速收发器的顶层模块参考代码如下所示:

//--###############################################################################################
//--#
//--# File Name		: aurora_64b66b_module
//--# Designer		: 数字站
//--# Tool			: Vivado 2021.1
//--# Design Date	: 2024.5.26
//--# 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 aurora_64b66b_module (
    input                   gt_refclk_p             ,//GT差分参考时钟,IP设置为156.25MHZ;
    input                   gt_refclk_n             ,//GT差分参考时钟,IP设置为156.25MHZ;
    input                   system_rst              ,//将系统复位作为GT复位;
    input                   init_clk                ,//初始化时钟,IP设置为100MHz。
    input                   drp_clk                 ,//DRP时钟信号,IP设置为100MHz。
    //QPLL的DRP接口;
    input       [7 : 0]     qpll_drpaddr            ,//QPLL动态重配置端口的地址信号;
    input       [15 : 0]    qpll_drpdi              ,//QPLL动态重配置端口的输入数据信号;
    output                  qpll_drprdy             ,//QPLL动态重配置端口的忙闲信号;
    input                   qpll_drpen              ,//QPLL动态重配置端口的使能信号;
    input                   qpll_drpwe              ,//QPLL动态重配置端口的读写指示信号;
    output      [15 : 0]    qpll_drpdo              ,//QPLL动态重配置端口的输出数据信号;
    //高速收发器0相关信号;
    output                  user_clk_0              ,//输入用户时钟信号,频率与txusrclk2一致;
    output                  user_reset_0            ,//输出用户端的系统复位信号;  
    input                   ufc_tx_req_0            ,//用户流量控制请求信号,高电平有效;
    input       [7 : 0]     ufc_tx_ms_0             ,//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    output                  ufc_in_progress_0       ,//低电平表示高速收发器正在接收用户流量控制数据;
    input                   gt_rx_p_0               ,//高速收发器的接收差分引脚;
    input                   gt_rx_n_0               ,//高速收发器的接收差分引脚;
    input       [2 : 0]     loopback_0              ,//回环模式控制信号;
    output                  gt_tx_p_0               ,//高速收发器的发送差分引脚;
    output                  gt_tx_n_0               ,//高速收发器的发送差分引脚;
    output                  hard_err_0              ,//硬件错误指示信号;
    output                  soft_err_0              ,//软件错误指示信号;
    output                  channel_up_0            ,//通道和内核初始化完成指示信号;
    output                  lane_up_0               ,//通道初始化完成指示信号;
    input       [63 : 0]    s_axi_tx_data_0         ,//用户发送数据端口的数据信号;
    input       [7 : 0]     s_axi_tx_keep_0         ,//用户发送数据端口的尾端数据掩码信号;
    input                   s_axi_tx_last_0         ,//用户发送数据端口的尾端数据指示信号;
    input                   s_axi_tx_valid_0        ,//用户发送数据端口的有效数据指示信号;
    output                  s_axi_tx_ready_0        ,//用户发送数据端口的接收数据应答信号;
    input                   s_axi_nfc_valid_0       ,//本地流量控制的数据有效指示信号;
    input       [15 : 0]    s_axi_nfc_data_0        ,//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    output                  s_axi_nfc_ready_0       ,//本地流量控制的接收数据应答指示信号;
    input       [63 : 0]    s_axi_ufc_tx_data_0     ,//用户流量控制发送端口的数据信号;
    input                   s_axi_ufc_tx_valid_0    ,//用户流量控制发送端口的数据有效指示信号;
    output                  s_axi_ufc_tx_ready_0    ,//用户流量控制发送端口的接收数据应答指示信号;
    output      [63 : 0]    m_axi_rx_data_0         ,//用户接收数据端口的数据信号;
    output      [7 : 0]     m_axi_rx_keep_0         ,//用户接收数据端口的尾端数据掩码信号;
    output                  m_axi_rx_last_0         ,//用户接收数据端口的尾端数据指示信号;
    output                  m_axi_rx_valid_0        ,//用户接收数据端口的有效数据指示信号;
    output      [63 : 0]    m_axi_ufc_rx_data_0     ,//用户流量控制接收端口的数据信号;
    output      [7 : 0]     m_axi_ufc_rx_keep_0     ,//用户流量控制接收端口的尾端数据掩码信号;
    output                  m_axi_ufc_rx_last_0     ,//用户流量控制接收端口的尾端数据指示信号;
    output                  m_axi_ufc_rx_valid_0    ,//用户流量控制接收端口的数据有效指示信号;
    input       [8 : 0]     gt_drpaddr_0            ,//高速收发器动态配置端口的地址信号;
    input       [15 : 0]    gt_drpdi_0              ,//高速收发器动态配置端口的输入数据信号;
    output                  gt_drprdy_0             ,//高速收发器动态配置端口的忙闲信号;
    input                   gt_drpen_0              ,//高速收发器动态配置端口的使能信号;
    input                   gt_drpwe_0              ,//高速收发器动态配置端口的读写指示信号;
    output      [15 : 0]    gt_drpdo_0              ,//高速收发器动态配置端口的输出数据信号;
    //高速收发器1相关信号;
    output                  user_clk_1              ,//输入用户时钟信号,频率与txusrclk2一致;
    output                  user_reset_1            ,//输出用户端的系统复位信号;  
    input                   ufc_tx_req_1            ,//用户流量控制请求信号,高电平有效;
    input       [7 : 0]     ufc_tx_ms_1             ,//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    output                  ufc_in_progress_1       ,//低电平表示高速收发器正在接收用户流量控制数据;
    input                   gt_rx_p_1               ,//高速收发器的接收差分引脚;
    input                   gt_rx_n_1               ,//高速收发器的接收差分引脚;
    input       [2 : 0]     loopback_1              ,//回环模式控制信号;
    output                  gt_tx_p_1               ,//高速收发器的发送差分引脚;
    output                  gt_tx_n_1               ,//高速收发器的发送差分引脚;
    output                  hard_err_1              ,//硬件错误指示信号;
    output                  soft_err_1              ,//软件错误指示信号;
    output                  channel_up_1            ,//通道和内核初始化完成指示信号;
    output                  lane_up_1               ,//通道初始化完成指示信号;
    input       [63 : 0]    s_axi_tx_data_1         ,//用户发送数据端口的数据信号;
    input       [7 : 0]     s_axi_tx_keep_1         ,//用户发送数据端口的尾端数据掩码信号;
    input                   s_axi_tx_last_1         ,//用户发送数据端口的尾端数据指示信号;
    input                   s_axi_tx_valid_1        ,//用户发送数据端口的有效数据指示信号;
    output                  s_axi_tx_ready_1        ,//用户发送数据端口的接收数据应答信号;
    input                   s_axi_nfc_valid_1       ,//本地流量控制的数据有效指示信号;
    input       [15 : 0]    s_axi_nfc_data_1        ,//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    output                  s_axi_nfc_ready_1       ,//本地流量控制的接收数据应答指示信号;
    input       [63 : 0]    s_axi_ufc_tx_data_1     ,//用户流量控制发送端口的数据信号;
    input                   s_axi_ufc_tx_valid_1    ,//用户流量控制发送端口的数据有效指示信号;
    output                  s_axi_ufc_tx_ready_1    ,//用户流量控制发送端口的接收数据应答指示信号;
    output      [63 : 0]    m_axi_rx_data_1         ,//用户接收数据端口的数据信号;
    output      [7 : 0]     m_axi_rx_keep_1         ,//用户接收数据端口的尾端数据掩码信号;
    output                  m_axi_rx_last_1         ,//用户接收数据端口的尾端数据指示信号;
    output                  m_axi_rx_valid_1        ,//用户接收数据端口的有效数据指示信号;
    output      [63 : 0]    m_axi_ufc_rx_data_1     ,//用户流量控制接收端口的数据信号;
    output      [7 : 0]     m_axi_ufc_rx_keep_1     ,//用户流量控制接收端口的尾端数据掩码信号;
    output                  m_axi_ufc_rx_last_1     ,//用户流量控制接收端口的尾端数据指示信号;
    output                  m_axi_ufc_rx_valid_1    ,//用户流量控制接收端口的数据有效指示信号;
    input       [8 : 0]     gt_drpaddr_1            ,//高速收发器动态配置端口的地址信号;
    input       [15 : 0]    gt_drpdi_1              ,//高速收发器动态配置端口的输入数据信号;
    output                  gt_drprdy_1             ,//高速收发器动态配置端口的忙闲信号;
    input                   gt_drpen_1              ,//高速收发器动态配置端口的使能信号;
    input                   gt_drpwe_1              ,//高速收发器动态配置端口的读写指示信号;
    output      [15 : 0]    gt_drpdo_1               //高速收发器动态配置端口的输出数据信号;
);
    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   ) //差分时钟输入信号;
    );

    //例化GT_COMMON
    aurora_64b66b_0_gt_common_wrapper gt_common_wrapper(
        .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          ),//初始化时钟,100MHz。
        .GT0_QPLLREFCLKLOST_OUT     ( gt_qpllrefclklost ),//QPLL失锁信号;
        .qpll_drpaddr_in            ( qpll_drpaddr      ),//QPLL动态重配置端口的地址信号;
        .qpll_drpdi_in              ( qpll_drpdi        ),//QPLL动态重配置端口的输入数据信号;
        .qpll_drpclk_in             ( drp_clk           ),//DRP时钟信号,频率设置为100MHz;
        .qpll_drpen_in              ( qpll_drpen        ),//QPLL动态重配置端口的使能信号;
        .qpll_drpwe_in              ( qpll_drpwe        ),//QPLL动态重配置端口的读写指示信号;
        .qpll_drpdo_out             ( qpll_drpdo        ),//QPLL动态重配置端口的输出数据信号;
        .qpll_drprdy_out            ( qpll_drprdy       ) //QPLL动态重配置端口的忙闲信号;
    );

    //例化高速收发器0
    aurora_64b66b_channel u_aurora_64b66b_channel_0(
        .gt_refclk          ( gt_refclk             ),//GT参考时钟,IP设置为156.25MHZ;
        .system_rst         ( system_rst            ),//将系统复位作为GT复位;
        .user_clk           ( user_clk_0            ),//输入用户时钟信号,频率与txusrclk2一致;
        .user_reset         ( user_reset_0          ),//输出用户端的系统复位信号;  
        .ufc_tx_req         ( ufc_tx_req_0          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms          ( ufc_tx_ms_0           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .ufc_in_progress    ( ufc_in_progress_0     ),//低电平表示高速收发器正在接收用户流量控制数据;
        .gt_rx_p            ( gt_rx_p_0             ),//高速收发器的接收差分引脚;
        .gt_rx_n            ( gt_rx_n_0             ),//高速收发器的接收差分引脚;
        .loopback           ( loopback_0            ),//回环模式控制信号;
        .gt_tx_p            ( gt_tx_p_0             ),//高速收发器的发送差分引脚;
        .gt_tx_n            ( gt_tx_n_0             ),//高速收发器的发送差分引脚;
        .hard_err           ( hard_err_0            ),//硬件错误指示信号;
        .soft_err           ( soft_err_0            ),//软件错误指示信号;
        .channel_up         ( channel_up_0          ),//通道和内核初始化完成指示信号;
        .lane_up            ( lane_up_0             ),//通道初始化完成指示信号;
        .s_axi_tx_data      ( s_axi_tx_data_0       ),//用户发送数据端口的数据信号;
        .s_axi_tx_keep      ( s_axi_tx_keep_0       ),//用户发送数据端口的尾端数据掩码信号;
        .s_axi_tx_last      ( s_axi_tx_last_0       ),//用户发送数据端口的尾端数据指示信号;
        .s_axi_tx_valid     ( s_axi_tx_valid_0      ),//用户发送数据端口的有效数据指示信号;
        .s_axi_tx_ready     ( s_axi_tx_ready_0      ),//用户发送数据端口的接收数据应答信号;
        .s_axi_nfc_valid    ( s_axi_nfc_valid_0     ),//本地流量控制的数据有效指示信号;
        .s_axi_nfc_data     ( s_axi_nfc_data_0      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .s_axi_nfc_ready    ( s_axi_nfc_ready_0     ),//本地流量控制的接收数据应答指示信号;
        .s_axi_ufc_tx_data  ( s_axi_ufc_tx_data_0   ),//用户流量控制发送端口的数据信号;
        .s_axi_ufc_tx_valid ( s_axi_ufc_tx_valid_0  ),//用户流量控制发送端口的数据有效指示信号;
        .s_axi_ufc_tx_ready ( s_axi_ufc_tx_ready_0  ),//用户流量控制发送端口的接收数据应答指示信号;
        .m_axi_rx_data      ( m_axi_rx_data_0       ),//用户接收数据端口的数据信号;
        .m_axi_rx_keep      ( m_axi_rx_keep_0       ),//用户接收数据端口的尾端数据掩码信号;
        .m_axi_rx_last      ( m_axi_rx_last_0       ),//用户接收数据端口的尾端数据指示信号;
        .m_axi_rx_valid     ( m_axi_rx_valid_0      ),//用户接收数据端口的有效数据指示信号;
        .m_axi_ufc_rx_data  ( m_axi_ufc_rx_data_0   ),//用户流量控制接收端口的数据信号;
        .m_axi_ufc_rx_keep  ( m_axi_ufc_rx_keep_0   ),//用户流量控制接收端口的尾端数据掩码信号;
        .m_axi_ufc_rx_last  ( m_axi_ufc_rx_last_0   ),//用户流量控制接收端口的尾端数据指示信号;
        .m_axi_ufc_rx_valid ( m_axi_ufc_rx_valid_0  ),//用户流量控制接收端口的数据有效指示信号;
        .init_clk           ( init_clk              ),//初始化时钟信号,频率设置为100MHz;
        .drp_clk            ( drp_clk               ),//DRP时钟信号,频率设置为100MHz;
        .gt_drpaddr         ( gt_drpaddr_0          ),//高速收发器动态配置端口的地址信号;
        .gt_drpdi           ( gt_drpdi_0            ),//高速收发器动态配置端口的输入数据信号;
        .gt_drprdy          ( gt_drprdy_0           ),//高速收发器动态配置端口的忙闲信号;
        .gt_drpen           ( gt_drpen_0            ),//高速收发器动态配置端口的使能信号;
        .gt_drpwe           ( gt_drpwe_0            ),//高速收发器动态配置端口的读写指示信号;
        .gt_drpdo           ( gt_drpdo_0            ),//高速收发器动态配置端口的输出数据信号;
        .qpll_drpaddr       ( qpll_drpaddr          ),//QPLL动态重配置端口的地址信号;
        .qpll_drpdi         ( qpll_drpdi            ),//QPLL动态重配置端口的输入数据信号;
        .qpll_drpen         ( qpll_drpen            ),//QPLL动态重配置端口的使能信号;
        .qpll_drpwe         ( qpll_drpwe            ),//QPLL动态重配置端口的读写指示信号;
        .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_64b66b_channel u_aurora_64b66b_channel_1(
        .gt_refclk          ( gt_refclk             ),//GT参考时钟,IP设置为156.25MHZ;
        .system_rst         ( system_rst            ),//将系统复位作为GT复位;
        .user_clk           ( user_clk_1            ),//输入用户时钟信号,频率与txusrclk2一致;
        .user_reset         ( user_reset_1          ),//输出用户端的系统复位信号;  
        .ufc_tx_req         ( ufc_tx_req_1          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms          ( ufc_tx_ms_1           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .ufc_in_progress    ( ufc_in_progress_1     ),//低电平表示高速收发器正在接收用户流量控制数据;
        .gt_rx_p            ( gt_rx_p_1             ),//高速收发器的接收差分引脚;
        .gt_rx_n            ( gt_rx_n_1             ),//高速收发器的接收差分引脚;
        .loopback           ( loopback_1            ),//回环模式控制信号;
        .gt_tx_p            ( gt_tx_p_1             ),//高速收发器的发送差分引脚;
        .gt_tx_n            ( gt_tx_n_1             ),//高速收发器的发送差分引脚;
        .hard_err           ( hard_err_1            ),//硬件错误指示信号;
        .soft_err           ( soft_err_1            ),//软件错误指示信号;
        .channel_up         ( channel_up_1          ),//通道和内核初始化完成指示信号;
        .lane_up            ( lane_up_1             ),//通道初始化完成指示信号;
        .s_axi_tx_data      ( s_axi_tx_data_1       ),//用户发送数据端口的数据信号;
        .s_axi_tx_keep      ( s_axi_tx_keep_1       ),//用户发送数据端口的尾端数据掩码信号;
        .s_axi_tx_last      ( s_axi_tx_last_1       ),//用户发送数据端口的尾端数据指示信号;
        .s_axi_tx_valid     ( s_axi_tx_valid_1      ),//用户发送数据端口的有效数据指示信号;
        .s_axi_tx_ready     ( s_axi_tx_ready_1      ),//用户发送数据端口的接收数据应答信号;
        .s_axi_nfc_valid    ( s_axi_nfc_valid_1     ),//本地流量控制的数据有效指示信号;
        .s_axi_nfc_data     ( s_axi_nfc_data_1      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .s_axi_nfc_ready    ( s_axi_nfc_ready_1     ),//本地流量控制的接收数据应答指示信号;
        .s_axi_ufc_tx_data  ( s_axi_ufc_tx_data_1   ),//用户流量控制发送端口的数据信号;
        .s_axi_ufc_tx_valid ( s_axi_ufc_tx_valid_1  ),//用户流量控制发送端口的数据有效指示信号;
        .s_axi_ufc_tx_ready ( s_axi_ufc_tx_ready_1  ),//用户流量控制发送端口的接收数据应答指示信号;
        .m_axi_rx_data      ( m_axi_rx_data_1       ),//用户接收数据端口的数据信号;
        .m_axi_rx_keep      ( m_axi_rx_keep_1       ),//用户接收数据端口的尾端数据掩码信号;
        .m_axi_rx_last      ( m_axi_rx_last_1       ),//用户接收数据端口的尾端数据指示信号;
        .m_axi_rx_valid     ( m_axi_rx_valid_1      ),//用户接收数据端口的有效数据指示信号;
        .m_axi_ufc_rx_data  ( m_axi_ufc_rx_data_1   ),//用户流量控制接收端口的数据信号;
        .m_axi_ufc_rx_keep  ( m_axi_ufc_rx_keep_1   ),//用户流量控制接收端口的尾端数据掩码信号;
        .m_axi_ufc_rx_last  ( m_axi_ufc_rx_last_1   ),//用户流量控制接收端口的尾端数据指示信号;
        .m_axi_ufc_rx_valid ( m_axi_ufc_rx_valid_1  ),//用户流量控制接收端口的数据有效指示信号;
        .init_clk           ( init_clk              ),//初始化时钟信号,频率设置为100MHz;
        .drp_clk            ( drp_clk               ),//DRP时钟信号,频率设置为100MHz;
        .gt_drpaddr         ( gt_drpaddr_1          ),//高速收发器动态配置端口的地址信号;
        .gt_drpdi           ( gt_drpdi_1            ),//高速收发器动态配置端口的输入数据信号;
        .gt_drprdy          ( gt_drprdy_1           ),//高速收发器动态配置端口的忙闲信号;
        .gt_drpen           ( gt_drpen_1            ),//高速收发器动态配置端口的使能信号;
        .gt_drpwe           ( gt_drpwe_1            ),//高速收发器动态配置端口的读写指示信号;
        .gt_drpdo           ( gt_drpdo_1            ),//高速收发器动态配置端口的输出数据信号;
        .qpll_drpaddr       ( qpll_drpaddr          ),//QPLL动态重配置端口的地址信号;
        .qpll_drpdi         ( qpll_drpdi            ),//QPLL动态重配置端口的输入数据信号;
        .qpll_drpen         ( qpll_drpen            ),//QPLL动态重配置端口的使能信号;
        .qpll_drpwe         ( qpll_drpwe            ),//QPLL动态重配置端口的读写指示信号;
        .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、测试数据生成模块

  该模块用于生成测试数,用户数据发送端口一直生成固定的数据帧,当接收端接收到指定数据(模仿接收端的FIFO溢出)时,向发送端发送nfc,让发送端暂停发送数据。

  不管任何状态下,当检测到按键被按下时,发送一帧数据。这个功能使用ufc数据帧实现。要求用户数据帧长度、nfc暂停时间长度、ufc数据帧长度均可以设置。

  该模块的端口信号和相关参数如下所示,包含接收和发送数据端口,ufc和nfc数据端口信号。

module user_test_data #(
    parameter           TX_DATA_LEN             =   40                  ,//发送一帧数据的长度,单位字节;
    parameter           UFC_TX_DATA_LEN         =   40                  ,//用户流量控制发送一帧数据的长度,单位字节;
    parameter           NFC_TX_LEN              =   40                   //本地流量控制暂停发送数据长度,单位时钟周期;
)(  
    input									        clk		            ,//系统时钟信号;
    input									        rst 	            ,//系统复位信号,高电平有效;
    input                                           key                 ,//按键输入信号;
    //用户发送数据端口;
    output  reg          [63 : 0]                   m_axi_tx_data       ,//发送数据的数据信号,大端对齐;
    output  reg          [7  : 0]                   m_axi_tx_keep       ,//发送数据的数据掩码信号,低电平有效;
    output  reg                                     m_axi_tx_last       ,//发送一帧数据的最后一个数据指示信号;
    output  reg                                     m_axi_tx_valid      ,//发送数据的有效指示信号;
    input                                           m_axi_tx_ready      ,//发送数据的应答信号;
    //用户接收数据端口;    
    input               [63 : 0]                    s_axi_rx_data       ,//接收数据的数据信号;
    input               [7  : 0]                    s_axi_rx_keep       ,//接收数据的数据掩码信号;
    input                                           s_axi_rx_last       ,//接收一帧数据的最后一个数据指示信号;
    input                                           s_axi_rx_valid      ,//接收数据的有效指示信号;
    //本地流量控制端口;    
    output  reg                                     m_axi_nfc_valid     ,//本地流量控制的数据有效指示信号;
    output  reg         [15 : 0]                    m_axi_nfc_data      ,//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    input                                           m_axi_nfc_ready     ,//本地流量控制的接收数据应答指示信号;
    //用户流量发送控制端口;
    output  reg                                     ufc_tx_req          ,//用户流量控制请求信号,高电平有效;
    output  reg         [7 : 0]                     ufc_tx_ms           ,//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    output  reg         [63 : 0]                    m_axi_ufc_tx_data   ,//用户流量控制发送端口的数据信号;
    output  reg                                     m_axi_ufc_tx_valid  ,//用户流量控制发送端口的数据有效指示信号;
    input                                           m_axi_ufc_tx_ready  ,//用户流量控制发送端口的接收数据应答指示信号;
    //用户流量接收控制端口;    
    input               [63 : 0]                    s_axi_ufc_rx_data   ,//用户流量控制接收端口的数据信号;
    input               [7 : 0]                     s_axi_ufc_rx_keep   ,//用户流量控制接收端口的尾端数据掩码信号;
    input                                           s_axi_ufc_rx_last   ,//用户流量控制接收端口的尾端数据指示信号;
    input                                           s_axi_ufc_rx_valid  ,//用户流量控制接收端口的数据有效指示信号;
    output  reg         [8 : 0]                     ready_cnt            //用户记录主机暂停发送数据的时间;
);
    localparam          TX_DATA_BYTE_LEN        =   (TX_DATA_LEN / 8 )      ;//计算一帧数据对应的数据长度,每个数据包含8字节;
    localparam          UFC_TX_DATA_BYTE_LEN    =   UFC_TX_DATA_LEN[2:0] ? ((UFC_TX_DATA_LEN / 8) + 1) : (UFC_TX_DATA_LEN / 8);//计算一帧用户流量控制数据对应的数据长度,每个数据包含8字节;
    localparam          KEEP                    =   (8'hff << (3'd7 - TX_DATA_LEN[2:0]));//计算一帧数据的尾端掩码信号;

  以下代码用于生成待发送的数据帧,每隔8个时钟周期,发送一帧指定长度的数据,代码比较简单,而且都有注释,就不再详述。

    /************* 生成用户发送数据的时序开始 *********************/
    //用于记录两帧数据之间的时钟个数,初始值为0,之后对时钟计数;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            rdy_cnt <= 'd0;
        end
        else if(m_axi_tx_valid)begin//当处于发送数据时清零;
            rdy_cnt <= 'd0;
        end
        else begin//如果不处于发送数据阶段,则计数器清零;
            rdy_cnt <= rdy_cnt + 'd1;
        end
    end

    //发送数据有效指示信号,初始值为0;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_tx_valid <= 1'b0;
        end
        else if(m_axi_tx_last && m_axi_tx_ready)begin//发送最后一个后拉低;
            m_axi_tx_valid <= 1'b0;
        end
        else if(&rdy_cnt)begin//当计数器计数到最大值时发送一帧数据,此时拉高;
            m_axi_tx_valid <= 1'b1;
        end
    end

    //用于生成产生数据个数的计数器,初始值为0,当发送指定个数数据时清零
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            tx_data_cnt <= 'd0;
        end
        else if(m_axi_tx_valid && m_axi_tx_ready)begin//当发送端和接收端握手时
            if(tx_data_cnt == TX_DATA_BYTE_LEN - 1)//如果发完指定数据则清零;
                tx_data_cnt <= 'd0;
            else//否则计数器加1;
                tx_data_cnt <= tx_data_cnt + 'd1;
        end
    end

    //生成测试数据;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_tx_data <= 32'd0;
        end
        else if(m_axi_tx_last && m_axi_tx_valid)begin//当发送完最后一个数据时清零;
            m_axi_tx_data <= 32'd0;
        end
        else if(m_axi_tx_valid && m_axi_tx_ready)begin
            m_axi_tx_data <= {{tx_data_cnt[4:0],3'd0},{tx_data_cnt[4:0],3'd1},{tx_data_cnt[4:0],3'd2},{tx_data_cnt[4:0],3'd3},
                                {tx_data_cnt[4:0],3'd4},{tx_data_cnt[4:0],3'd5},{tx_data_cnt[4:0],3'd6},{tx_data_cnt[4:0],3'd7}};
        end
    end
    
    //一帧数据最后一个指示信号,初始值为0;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_tx_last <= 1'b0;
        end
        else if(m_axi_tx_valid && m_axi_tx_ready)begin//当发送最后一个数据时拉高,其余时间保持不变;
            if(tx_data_cnt == TX_DATA_BYTE_LEN - 2)
                m_axi_tx_last <= 1'b1;
            else if(tx_data_cnt == TX_DATA_BYTE_LEN - 1)
                m_axi_tx_last <= 1'b0;
        end
    end

    //生成数据掩码信号
    always@(posedge clk)begin
        if(rst)begin//初始值为4'b1111;
            m_axi_tx_keep <= 8'hff;
        end
        else if(m_axi_tx_valid && m_axi_tx_ready)begin
            if(tx_data_cnt == TX_DATA_BYTE_LEN - 2)//最后一个数据的掩码信号;
                m_axi_tx_keep <= KEEP;
            else if(tx_data_cnt == TX_DATA_BYTE_LEN - 1)
                m_axi_tx_keep <= 8'hff;
        end
        else begin
            m_axi_tx_keep <= 8'hff;
        end
    end

  接收端口每接收128个数据,会向发送端发送一个nfc数据帧,让发送端在接下来的NFC_TX_LEN个时钟内暂停发送数据,对应代码如下所示。

    //本地流量控制一般用于当接收端处理不了数据时,让发送端暂停发送数据。
    //因此此处每当接收端接收到128个数据,就让发送端停止发送一段时间的数据;
    //rx_data_cnt计数器,对接收数据个数进行计数,溢出时表示收到128个数据;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            rx_data_cnt <= 'd0;
        end
        else if(s_axi_rx_valid)begin
            rx_data_cnt <= rx_data_cnt + 'd1;
        end
    end

    //生成本地流量控制信号;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_nfc_valid <= 'd0;
        end
        else if(m_axi_nfc_ready)begin
            m_axi_nfc_valid <= 'd0;//当IP应答时拉低;
        end
        else if(&rx_data_cnt)begin//当计数器计数到127时拉高;
            m_axi_nfc_valid <= 1'b1;
        end
    end

    //发送端暂停发送数据时间设置,单位是字节。
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_nfc_data <= 'd0;
        end
        else begin//暂停发送NFC_TX_LEN个字节数据对应的时间。
            m_axi_nfc_data <= {8'd0,(NFC_TX_LEN[7:0] - 8'd1)};
        end
    end

  为了便于统计发送端每次暂停的时间,通过一个计数器ready_cnt对发送端口的应答信号进行计数。

    //为了便于后续查看本地流量控制暂停时间,通过一个计数器来对应答信号的低电平持续时间进行计数。
    always@(posedge clk)begin
        if(rst)begin//初始值为1;
            ready_cnt <= 'd1;
        end
        else if(~m_axi_tx_ready)begin
            ready_cnt <= ready_cnt + 'd1;
        end
        else begin
            ready_cnt <= 'd1;
        end
    end

  最后是ufc数据帧的产生,首先当按键被按下后,将ufc_tx_req拉高,并且将ufc的数据帧长度通过ufc_tx_ms发出。

    //用户流量控制用于发送优先级较高的数据。
    //因此当按键被按下时,立即通过该接口向接收端发送一帧数据;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            ufc_tx_req <= 'd0;
            ufc_tx_ms <= UFC_TX_DATA_LEN[8:0] - 9'd1;
        end
        else begin
            ufc_tx_req <= key;//当按键按下时,发送一个UFC请求;
            ufc_tx_ms <= UFC_TX_DATA_LEN[8:0] - 9'd1;//发送数据长度,单位字节;
        end
    end

  然后将ufc数据有效指示信号拉高,并且使用一个计数器记录已经发送数据的长度,直到发送完指定数据为止。

    //生成数据有效指示信号;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_ufc_tx_valid <= 'd0;
        end
        else if(end_ufc_tx_cnt)begin
            m_axi_ufc_tx_valid <= 1'b0;//发送完一帧数据时清零;
        end
        else if(ufc_tx_req)begin
            m_axi_ufc_tx_valid <= 1'b1;//按键按下时拉高;
        end
    end
    
    //用于记录发送数据个数的计数器;
    always@(posedge clk)begin
        if(rst)begin//
            ufc_tx_cnt <= 0;
        end
        else if(add_ufc_tx_cnt)begin
            if(end_ufc_tx_cnt)
                ufc_tx_cnt <= 0;
            else
                ufc_tx_cnt <= ufc_tx_cnt + 1;
        end
    end
    
    assign add_ufc_tx_cnt = (m_axi_ufc_tx_valid && m_axi_ufc_tx_ready);//发送完一个数据时加一,其余时间保持不变;
    assign end_ufc_tx_cnt = add_ufc_tx_cnt && (ufc_tx_cnt == UFC_TX_DATA_BYTE_LEN - 1);//发送完一帧数据时拉低;

    //生成用户数据;
    always@(posedge clk)begin
        if(rst)begin//初始值为0;
            m_axi_ufc_tx_data <= 'd0;
        end
        else begin
            m_axi_ufc_tx_data <= {{ufc_tx_cnt[4:0],3'd0},{ufc_tx_cnt[4:0],3'd1},{ufc_tx_cnt[4:0],3'd2},{ufc_tx_cnt[4:0],3'd3},
                                    {ufc_tx_cnt[4:0],3'd4},{ufc_tx_cnt[4:0],3'd5},{ufc_tx_cnt[4:0],3'd6},{ufc_tx_cnt[4:0],3'd7}};
        end
    end

3、顶层模块

  顶层模块就是将测试数据生成模块、复位同步模块、按键消抖模块、高速收发器顶层模块的各个端口连接,对应的RTL视图如下所示。

在这里插入图片描述

图3 顶层模块RTL视图

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

//--###############################################################################################
//--#
//--# File Name		: top
//--# Designer		: 数字站
//--# Tool			: Vivado 2021.1
//--# Design Date	: 2024.5.26
//--# 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 top #(
    parameter   TIME_20MS   =   20_000_000               //按键抖动持续的最长时间,默认最长持续时间为20ms。
)(
    input					    clk		                ,//系统时钟信号;
    input					    rst_n	                ,//系统复位信号,低电平有效;

    input                       key_in                  ,//按键输入信号,低电平有效;

    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              ;//系统复位信号;
    wire                        key_out_0               ;
    wire                        key_out_1               ;
    //高速收发器0相关信号;
    wire                        user_clk_0              ;//输入用户时钟信号,频率与txusrclk2一致;
    wire                        user_reset_0            ;//输出用户端的系统复位信号;  
    (* MARK_DEBUG = "TRUE" *)wire                        ufc_tx_req_0            ;//用户流量控制请求信号,高电平有效;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         ufc_tx_ms_0             ;//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    (* MARK_DEBUG = "TRUE" *)wire                        ufc_in_progress_0       ;//低电平表示高速收发器正在接收用户流量控制数据;
    wire                        gt_rx_p_0               ;//高速收发器的接收差分引脚;
    wire                        gt_rx_n_0               ;//高速收发器的接收差分引脚;
    wire                        gt_tx_p_0               ;//高速收发器的发送差分引脚;
    wire                        gt_tx_n_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_data_0         ;//用户发送数据端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         s_axi_tx_keep_0         ;//用户发送数据端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_last_0         ;//用户发送数据端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_valid_0        ;//用户发送数据端口的有效数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_ready_0        ;//用户发送数据端口的接收数据应答信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_nfc_valid_0       ;//本地流量控制的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [15 : 0]        s_axi_nfc_data_0        ;//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_nfc_ready_0       ;//本地流量控制的接收数据应答指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        s_axi_ufc_tx_data_0     ;//用户流量控制发送端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_ufc_tx_valid_0    ;//用户流量控制发送端口的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_ufc_tx_ready_0    ;//用户流量控制发送端口的接收数据应答指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        m_axi_rx_data_0         ;//用户接收数据端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         m_axi_rx_keep_0         ;//用户接收数据端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_rx_last_0         ;//用户接收数据端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_rx_valid_0        ;//用户接收数据端口的有效数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        m_axi_ufc_rx_data_0     ;//用户流量控制接收端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         m_axi_ufc_rx_keep_0     ;//用户流量控制接收端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_ufc_rx_last_0     ;//用户流量控制接收端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_ufc_rx_valid_0    ;//用户流量控制接收端口的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [8 : 0]         ready_cnt_0             ;//用户记录主机暂停发送数据的时间;
    //高速收发器1相关信号;
    wire                        user_clk_1              ;//输入用户时钟信号,频率与txusrclk2一致;
    wire                        user_reset_1            ;//输出用户端的系统复位信号;  
    (* MARK_DEBUG = "TRUE" *)wire                        ufc_tx_req_1            ;//用户流量控制请求信号,高电平有效;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         ufc_tx_ms_1             ;//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
    (* MARK_DEBUG = "TRUE" *)wire                        ufc_in_progress_1       ;//低电平表示高速收发器正在接收用户流量控制数据;
    wire                        gt_rx_p_1               ;//高速收发器的接收差分引脚;
    wire                        gt_rx_n_1               ;//高速收发器的接收差分引脚;
    wire                        gt_tx_p_1               ;//高速收发器的发送差分引脚;
    wire                        gt_tx_n_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_data_1         ;//用户发送数据端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         s_axi_tx_keep_1         ;//用户发送数据端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_last_1         ;//用户发送数据端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_valid_1        ;//用户发送数据端口的有效数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_tx_ready_1        ;//用户发送数据端口的接收数据应答信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_nfc_valid_1       ;//本地流量控制的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [15 : 0]        s_axi_nfc_data_1        ;//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_nfc_ready_1       ;//本地流量控制的接收数据应答指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        s_axi_ufc_tx_data_1     ;//用户流量控制发送端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_ufc_tx_valid_1    ;//用户流量控制发送端口的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        s_axi_ufc_tx_ready_1    ;//用户流量控制发送端口的接收数据应答指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        m_axi_rx_data_1         ;//用户接收数据端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         m_axi_rx_keep_1         ;//用户接收数据端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_rx_last_1         ;//用户接收数据端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_rx_valid_1        ;//用户接收数据端口的有效数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [63 : 0]        m_axi_ufc_rx_data_1     ;//用户流量控制接收端口的数据信号;
    (* MARK_DEBUG = "TRUE" *)wire        [7 : 0]         m_axi_ufc_rx_keep_1     ;//用户流量控制接收端口的尾端数据掩码信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_ufc_rx_last_1     ;//用户流量控制接收端口的尾端数据指示信号;
    (* MARK_DEBUG = "TRUE" *)wire                        m_axi_ufc_rx_valid_1    ;//用户流量控制接收端口的数据有效指示信号;
    (* MARK_DEBUG = "TRUE" *)wire        [8 : 0]         ready_cnt_1             ;//用户记录主机暂停发送数据的时间;

    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) //复位输出信号,默认高电平有效;
    );

    //例化按键消抖模块;
    key #(
        .TIME_20MS      ( TIME_20MS     ) //按键抖动持续的最长时间,默认最长持续时间为20ms。
    )
    u_key_0 (
        .clk            ( user_clk_0    ),//系统时钟,125MHz。
        .rst            ( user_reset_0  ),//系统复位,低电平有效。
        .key_in         ( key_in        ),//待输入的按键输入信号,默认低电平有效;
        .key_out        ( key_out_0     ) //按键消抖后输出信号,当按键按下一次时,输出一个时钟宽度的高电平;
    );

    //例化按键消抖模块1;
    key #(
        .TIME_20MS      ( TIME_20MS     ) //按键抖动持续的最长时间,默认最长持续时间为20ms。
    )
    u_key_1 (
        .clk            ( user_clk_1    ),//系统时钟,125MHz。
        .rst            ( user_reset_1  ),//系统复位,低电平有效。
        .key_in         ( key_in        ),//待输入的按键输入信号,默认低电平有效;
        .key_out        ( key_out_1     ) //按键消抖后输出信号,当按键按下一次时,输出一个时钟宽度的高电平;
    );

    //例化高速收发器0的测试数据产生模块
    user_test_data #(
        .TX_DATA_LEN        ( 127                   ),//发送一帧数据的长度,单位字节;
        .UFC_TX_DATA_LEN    ( 256                   ),//用户流量控制发送一帧数据的长度,单位字节;
        .NFC_TX_LEN         ( 65                    ) //本地流量控制暂停发送数据长度,单位字节;
    )
    u_user_test_data_0 (
        .clk		        ( user_clk_0            ),//系统时钟信号;
        .rst 	            ( user_reset_0          ),//系统复位信号,高电平有效;
        .key                ( key_out_0             ),//按键输入信号;
        //用户发送数据端口;
        .m_axi_tx_data      ( s_axi_tx_data_0       ),//发送数据的数据信号,大端对齐;
        .m_axi_tx_keep      ( s_axi_tx_keep_0       ),//发送数据的数据掩码信号,低电平有效;
        .m_axi_tx_last      ( s_axi_tx_last_0       ),//发送一帧数据的最后一个数据指示信号;
        .m_axi_tx_valid     ( s_axi_tx_valid_0      ),//发送数据的有效指示信号;
        .m_axi_tx_ready     ( s_axi_tx_ready_0      ),//发送数据的应答信号;
        //用户接收数据端口;    
        .s_axi_rx_data      ( m_axi_rx_data_0       ),//接收数据的数据信号;
        .s_axi_rx_keep      ( m_axi_rx_keep_0       ),//接收数据的数据掩码信号;
        .s_axi_rx_last      ( m_axi_rx_last_0       ),//接收一帧数据的最后一个数据指示信号;
        .s_axi_rx_valid     ( m_axi_rx_valid_0      ),//接收数据的有效指示信号;
        //本地流量控制端口;    
        .m_axi_nfc_valid    ( s_axi_nfc_valid_0     ),//本地流量控制的数据有效指示信号;
        .m_axi_nfc_data     ( s_axi_nfc_data_0      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .m_axi_nfc_ready    ( s_axi_nfc_ready_0     ),//本地流量控制的接收数据应答指示信号;
        //用户流量发送控制端口;
        .ufc_tx_req         ( ufc_tx_req_0          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms          ( ufc_tx_ms_0           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .m_axi_ufc_tx_data  ( s_axi_ufc_tx_data_0   ),//用户流量控制发送端口的数据信号;
        .m_axi_ufc_tx_valid ( s_axi_ufc_tx_valid_0  ),//用户流量控制发送端口的数据有效指示信号;
        .m_axi_ufc_tx_ready ( s_axi_ufc_tx_ready_0  ),//用户流量控制发送端口的接收数据应答指示信号;
        //用户流量接收控制端口;    
        .s_axi_ufc_rx_data  ( m_axi_ufc_rx_data_0   ),//用户流量控制接收端口的数据信号;
        .s_axi_ufc_rx_keep  ( m_axi_ufc_rx_keep_0   ),//用户流量控制接收端口的尾端数据掩码信号;
        .s_axi_ufc_rx_last  ( m_axi_ufc_rx_last_0   ),//用户流量控制接收端口的尾端数据指示信号;
        .s_axi_ufc_rx_valid ( m_axi_ufc_rx_valid_0  ),//用户流量控制接收端口的数据有效指示信号;
        .ready_cnt          ( ready_cnt_0           )
    );

    //例化高速收发器1的测试数据产生模块
    user_test_data #(
        .TX_DATA_LEN        ( 81                    ),//发送一帧数据的长度,单位字节;
        .UFC_TX_DATA_LEN    ( 88                    ),//用户流量控制发送一帧数据的长度,单位字节;
        .NFC_TX_LEN         ( 128                   ) //本地流量控制暂停发送数据长度,单位字节;
    )
    u_user_test_data_1 (  
        .clk		        ( user_clk_1            ),//系统时钟信号;
        .rst 	            ( user_reset_1          ),//系统复位信号,高电平有效;
        .key                ( key_out_1             ),//按键输入信号;
        //用户发送数据端口;
        .m_axi_tx_data      ( s_axi_tx_data_1       ),//发送数据的数据信号,大端对齐;
        .m_axi_tx_keep      ( s_axi_tx_keep_1       ),//发送数据的数据掩码信号,低电平有效;
        .m_axi_tx_last      ( s_axi_tx_last_1       ),//发送一帧数据的最后一个数据指示信号;
        .m_axi_tx_valid     ( s_axi_tx_valid_1      ),//发送数据的有效指示信号;
        .m_axi_tx_ready     ( s_axi_tx_ready_1      ),//发送数据的应答信号;
        //用户接收数据端口;    
        .s_axi_rx_data      ( m_axi_rx_data_1       ),//接收数据的数据信号;
        .s_axi_rx_keep      ( m_axi_rx_keep_1       ),//接收数据的数据掩码信号;
        .s_axi_rx_last      ( m_axi_rx_last_1       ),//接收一帧数据的最后一个数据指示信号;
        .s_axi_rx_valid     ( m_axi_rx_valid_1      ),//接收数据的有效指示信号;
        //本地流量控制端口;    
        .m_axi_nfc_valid    ( s_axi_nfc_valid_1     ),//本地流量控制的数据有效指示信号;
        .m_axi_nfc_data     ( s_axi_nfc_data_1      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .m_axi_nfc_ready    ( s_axi_nfc_ready_1     ),//本地流量控制的接收数据应答指示信号;
        //用户流量发送控制端口;
        .ufc_tx_req         ( ufc_tx_req_1          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms          ( ufc_tx_ms_1           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .m_axi_ufc_tx_data  ( s_axi_ufc_tx_data_1   ),//用户流量控制发送端口的数据信号;
        .m_axi_ufc_tx_valid ( s_axi_ufc_tx_valid_1  ),//用户流量控制发送端口的数据有效指示信号;
        .m_axi_ufc_tx_ready ( s_axi_ufc_tx_ready_1  ),//用户流量控制发送端口的接收数据应答指示信号;
        //用户流量接收控制端口;    
        .s_axi_ufc_rx_data  ( m_axi_ufc_rx_data_1   ),//用户流量控制接收端口的数据信号;
        .s_axi_ufc_rx_keep  ( m_axi_ufc_rx_keep_1   ),//用户流量控制接收端口的尾端数据掩码信号;
        .s_axi_ufc_rx_last  ( m_axi_ufc_rx_last_1   ),//用户流量控制接收端口的尾端数据指示信号;
        .s_axi_ufc_rx_valid ( m_axi_ufc_rx_valid_1  ),//用户流量控制接收端口的数据有效指示信号;
        .ready_cnt          ( ready_cnt_1           )
    );

    //例化两路高速收发器
    aurora_64b66b_module u_aurora_64b66b_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            ),//将系统复位作为GT复位;
        .init_clk               ( clk                   ),//初始化时钟,IP设置为100MHz。
        .drp_clk                ( clk                   ),//DRP时钟信号,IP设置为100MHz。
        //QPLL的DRP接口;
        .qpll_drpaddr           ( 0                     ),//QPLL动态重配置端口的地址信号;
        .qpll_drpdi             ( 0                     ),//QPLL动态重配置端口的输入数据信号;
        .qpll_drprdy            (                       ),//QPLL动态重配置端口的忙闲信号;
        .qpll_drpen             ( 0                     ),//QPLL动态重配置端口的使能信号;
        .qpll_drpwe             ( 0                     ),//QPLL动态重配置端口的读写指示信号;
        .qpll_drpdo             (                       ),//QPLL动态重配置端口的输出数据信号;
        //高速收发器0相关信号;
        .user_clk_0             ( user_clk_0            ),//输入用户时钟信号,频率与txusrclk2一致;
        .user_reset_0           ( user_reset_0          ),//输出用户端的系统复位信号;  
        .ufc_tx_req_0           ( ufc_tx_req_0          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms_0            ( ufc_tx_ms_0           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .ufc_in_progress_0      ( ufc_in_progress_0     ),//低电平表示高速收发器正在接收用户流量控制数据;
        .gt_rx_p_0              ( gt_rx_p_0             ),//高速收发器的接收差分引脚;
        .gt_rx_n_0              ( gt_rx_n_0             ),//高速收发器的接收差分引脚;
        .loopback_0             ( 3'b000                ),//回环模式控制信号;
        .gt_tx_p_0              ( gt_tx_p_0             ),//高速收发器的发送差分引脚;
        .gt_tx_n_0              ( gt_tx_n_0             ),//高速收发器的发送差分引脚;
        .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_data_0        ( s_axi_tx_data_0       ),//用户发送数据端口的数据信号;
        .s_axi_tx_keep_0        ( s_axi_tx_keep_0       ),//用户发送数据端口的尾端数据掩码信号;
        .s_axi_tx_last_0        ( s_axi_tx_last_0       ),//用户发送数据端口的尾端数据指示信号;
        .s_axi_tx_valid_0       ( s_axi_tx_valid_0      ),//用户发送数据端口的有效数据指示信号;
        .s_axi_tx_ready_0       ( s_axi_tx_ready_0      ),//用户发送数据端口的接收数据应答信号;
        .s_axi_nfc_valid_0      ( s_axi_nfc_valid_0     ),//本地流量控制的数据有效指示信号;
        .s_axi_nfc_data_0       ( s_axi_nfc_data_0      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .s_axi_nfc_ready_0      ( s_axi_nfc_ready_0     ),//本地流量控制的接收数据应答指示信号;
        .s_axi_ufc_tx_data_0    ( s_axi_ufc_tx_data_0   ),//用户流量控制发送端口的数据信号;
        .s_axi_ufc_tx_valid_0   ( s_axi_ufc_tx_valid_0  ),//用户流量控制发送端口的数据有效指示信号;
        .s_axi_ufc_tx_ready_0   ( s_axi_ufc_tx_ready_0  ),//用户流量控制发送端口的接收数据应答指示信号;
        .m_axi_rx_data_0        ( m_axi_rx_data_0       ),//用户接收数据端口的数据信号;
        .m_axi_rx_keep_0        ( m_axi_rx_keep_0       ),//用户接收数据端口的尾端数据掩码信号;
        .m_axi_rx_last_0        ( m_axi_rx_last_0       ),//用户接收数据端口的尾端数据指示信号;
        .m_axi_rx_valid_0       ( m_axi_rx_valid_0      ),//用户接收数据端口的有效数据指示信号;
        .m_axi_ufc_rx_data_0    ( m_axi_ufc_rx_data_0   ),//用户流量控制接收端口的数据信号;
        .m_axi_ufc_rx_keep_0    ( m_axi_ufc_rx_keep_0   ),//用户流量控制接收端口的尾端数据掩码信号;
        .m_axi_ufc_rx_last_0    ( m_axi_ufc_rx_last_0   ),//用户流量控制接收端口的尾端数据指示信号;
        .m_axi_ufc_rx_valid_0   ( m_axi_ufc_rx_valid_0  ),//用户流量控制接收端口的数据有效指示信号;
        .gt_drpaddr_0           ( 0                     ),//高速收发器动态配置端口的地址信号;
        .gt_drpdi_0             ( 0                     ),//高速收发器动态配置端口的输入数据信号;
        .gt_drprdy_0            (                       ),//高速收发器动态配置端口的忙闲信号;
        .gt_drpen_0             ( 0                     ),//高速收发器动态配置端口的使能信号;
        .gt_drpwe_0             ( 0                     ),//高速收发器动态配置端口的读写指示信号;
        .gt_drpdo_0             (                       ),//高速收发器动态配置端口的输出数据信号;
        //高速收发器1相关信号;
        .user_clk_1             ( user_clk_1            ),//输入用户时钟信号,频率与txusrclk2一致;
        .user_reset_1           ( user_reset_1          ),//输出用户端的系统复位信号;  
        .ufc_tx_req_1           ( ufc_tx_req_1          ),//用户流量控制请求信号,高电平有效;
        .ufc_tx_ms_1            ( ufc_tx_ms_1           ),//用户流量控制的发送数据长度信号,发送数据长度等于该数据加1,单位字节。
        .ufc_in_progress_1      ( ufc_in_progress_1     ),//低电平表示高速收发器正在接收用户流量控制数据;
        .gt_rx_p_1              ( gt_rx_p_1             ),//高速收发器的接收差分引脚;
        .gt_rx_n_1              ( gt_rx_n_1             ),//高速收发器的接收差分引脚;
        .loopback_1             ( 3'b000                ),//回环模式控制信号;
        .gt_tx_p_1              ( gt_tx_p_1             ),//高速收发器的发送差分引脚;
        .gt_tx_n_1              ( gt_tx_n_1             ),//高速收发器的发送差分引脚;
        .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_data_1        ( s_axi_tx_data_1       ),//用户发送数据端口的数据信号;
        .s_axi_tx_keep_1        ( s_axi_tx_keep_1       ),//用户发送数据端口的尾端数据掩码信号;
        .s_axi_tx_last_1        ( s_axi_tx_last_1       ),//用户发送数据端口的尾端数据指示信号;
        .s_axi_tx_valid_1       ( s_axi_tx_valid_1      ),//用户发送数据端口的有效数据指示信号;
        .s_axi_tx_ready_1       ( s_axi_tx_ready_1      ),//用户发送数据端口的接收数据应答信号;
        .s_axi_nfc_valid_1      ( s_axi_nfc_valid_1     ),//本地流量控制的数据有效指示信号;
        .s_axi_nfc_data_1       ( s_axi_nfc_data_1      ),//本地流量控制的数据信号,[8]表示是否停止发送数据,[7:0]表示停止发送数据的周期数据;
        .s_axi_nfc_ready_1      ( s_axi_nfc_ready_1     ),//本地流量控制的接收数据应答指示信号;
        .s_axi_ufc_tx_data_1    ( s_axi_ufc_tx_data_1   ),//用户流量控制发送端口的数据信号;
        .s_axi_ufc_tx_valid_1   ( s_axi_ufc_tx_valid_1  ),//用户流量控制发送端口的数据有效指示信号;
        .s_axi_ufc_tx_ready_1   ( s_axi_ufc_tx_ready_1  ),//用户流量控制发送端口的接收数据应答指示信号;
        .m_axi_rx_data_1        ( m_axi_rx_data_1       ),//用户接收数据端口的数据信号;
        .m_axi_rx_keep_1        ( m_axi_rx_keep_1       ),//用户接收数据端口的尾端数据掩码信号;
        .m_axi_rx_last_1        ( m_axi_rx_last_1       ),//用户接收数据端口的尾端数据指示信号;
        .m_axi_rx_valid_1       ( m_axi_rx_valid_1      ),//用户接收数据端口的有效数据指示信号;
        .m_axi_ufc_rx_data_1    ( m_axi_ufc_rx_data_1   ),//用户流量控制接收端口的数据信号;
        .m_axi_ufc_rx_keep_1    ( m_axi_ufc_rx_keep_1   ),//用户流量控制接收端口的尾端数据掩码信号;
        .m_axi_ufc_rx_last_1    ( m_axi_ufc_rx_last_1   ),//用户流量控制接收端口的尾端数据指示信号;
        .m_axi_ufc_rx_valid_1   ( m_axi_ufc_rx_valid_1  ),//用户流量控制接收端口的数据有效指示信号;
        .gt_drpaddr_1           ( 0                     ),//高速收发器动态配置端口的地址信号;
        .gt_drpdi_1             ( 0                     ),//高速收发器动态配置端口的输入数据信号;
        .gt_drprdy_1            (                       ),//高速收发器动态配置端口的忙闲信号;
        .gt_drpen_1             ( 0                     ),//高速收发器动态配置端口的使能信号;
        .gt_drpwe_1             ( 0                     ),//高速收发器动态配置端口的读写指示信号;
        .gt_drpdo_1             (                       ) //高速收发器动态配置端口的输出数据信号;
    );

endmodule

4、模块仿真

  顶层模块的仿真激励文件如下所示。

//--###############################################################################################
//--#
//--# File Name		: test
//--# Designer		: 数字站
//--# Tool			: Vivado 2021.1
//--# Design Date	: 2024.5.26
//--# 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)
//--#
//--###############################################################################################
`timescale 1ns / 1ps
module test ();
    localparam	CYCLE		= 	10			    ;//系统时钟周期,单位ns,默认10ns;
    localparam	RST_TIME	= 	10			    ;//系统复位持续时间,默认10个系统时钟周期;
    localparam  TIME_20MS   =   500             ;//按键抖动持续的最长时间,默认最长持续时间为20ms。

    reg							clk			    ;//系统时钟,默认100MHz;
    reg							rst_n		    ;//系统复位,默认低电平有效;

    reg                         key_in          ;//按键输入信号,低电平有效;
    reg                         gt_refclk_p     ;//gt差分参考时钟信号;
    reg                         gt_refclk_n     ;//gt差分参考时钟信号;

    wire                        gt_tx_p_0       ;//gt发送差分数据线;
    wire                        gt_tx_n_0       ;//gt发送差分数据线;
    wire                        gt_tx_p_1       ;//gt发送差分数据线;
    wire                        gt_tx_n_1       ;//gt发送差分数据线;
    wire        [1 : 0]         dislabe         ;//光电转换模块失能信号;

    //例化待测试模块
    top #(
        .TIME_20MS      ( TIME_20MS     ) //按键抖动持续的最长时间,默认最长持续时间为20ms。
    )
    u_top (
        .clk		    ( clk		    ),//系统时钟信号;
        .rst_n	        ( rst_n	        ),//系统复位信号,低电平有效;
        .key_in         ( key_in        ),//按键输入信号,低电平有效;
        .gt_refclk_p    ( gt_refclk_p   ),//gt差分参考时钟信号;
        .gt_refclk_n    ( gt_refclk_n   ),//gt差分参考时钟信号;
        .gt_rx_p_0      ( gt_tx_p_1     ),//gt接收差分数据线;
        .gt_rx_n_0      ( gt_tx_n_1     ),//gt接收差分数据线;
        .gt_tx_p_0      ( gt_tx_p_0     ),//gt发送差分数据线;
        .gt_tx_n_0      ( gt_tx_n_0     ),//gt发送差分数据线;
        .gt_rx_p_1      ( gt_tx_p_0     ),//gt接收差分数据线;
        .gt_rx_n_1      ( gt_tx_n_0     ),//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

    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
        key_in = 1'b1;
        rst_n = 1;
        #2;
        rst_n = 0;//开始时复位10个时钟;
        #(RST_TIME*CYCLE);
        rst_n = 1;
        repeat(2000)@(posedge clk);
        forever begin
            key_i();
            repeat(300)@(posedge gt_refclk_p);
        end
    end

    //按键信号产生任务;
    task key_i();
        begin : KEY_I
            key_in <= 1'b1;
            @(posedge gt_refclk_p);
            repeat({$random} % 10)begin
                key_in <= ~key_in;
                repeat({$random} % (2*TIME_20MS))@(posedge gt_refclk_p);
            end
            key_in <= 1'b0;
            repeat(TIME_20MS + 200)@(posedge gt_refclk_p);
            repeat({$random} % 10)begin
                key_in <= ~key_in;
                repeat({$random} % (2*TIME_20MS))@(posedge gt_refclk_p);
            end
            key_in <= 1'b1;
            @(posedge gt_refclk_p);
        end
    endtask
    
endmodule

  将顶层模块的信号添加到仿真列表,然后运行仿真,结果如下所示:

在这里插入图片描述

图4 总体仿真

  首先高速收发器0向高速收发器1正常发送数据,如下图所示:

在这里插入图片描述

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

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

在这里插入图片描述

图6 高速收发器1向高速收发器0发送一帧数据

  当高速收发器0接收到高速收发器1发送的128个数据后,向高速收发器1发送NFC数据帧,使得高速收发器1暂停发送64个时钟的数据。

在这里插入图片描述

图7 高速收发器0向高速收发器1发送NFC数据帧

  高速收发器1在接收到NFC数据帧之后,将用户发送数据端口的应答信号拉低64个时钟周期,来暂停发送数据。

在这里插入图片描述

图8 高速收发器1暂停发送64个数据

  当高速收发器1接收到高速收发器0发送的128个数据后,向高速收发器0发送NFC数据帧,使得高速收发器0暂停发送127个时钟的数据。

在这里插入图片描述

图9 高速收发器1向高速收发器0发送NFC数据帧

  高速收发器0在接收到NFC数据帧之后,将用户发送数据端口的应答信号拉低127个时钟周期,来暂停发送数据。

在这里插入图片描述

图10 高速收发器0暂停发送127个数据

  当检测到按键按下时,高速收发器0向高速收发器1发送一帧长度为256字节的UFC数据,最后一个有效字节数据为8’hf7。

在这里插入图片描述

图11 高速收发器0向高速收发器1发送UFC数据帧

  如下图所示,高速收发器1接收到的UFC数据帧的最后一个有效字节数据为8’hf7。

在这里插入图片描述

图12 高速收发器1接收到的UFC数据帧

  按键按下时,高速收发器1向高速收发器0发送一帧长为88字节的UFC数据,如下图所示,发送的最后一字节有效数据为8’h4f。

在这里插入图片描述

图13 高速收发器1向高速收发器0发送UFC数据帧

  如下图所示,高速收发器0接收到的UFC数据帧的最后一个有效字节数据为8’h4f,与发送的数据一致。

在这里插入图片描述

图14 高速收发器0接收到的UFC数据帧

  上述仿真完成两种流控模式的仿真,可能发送数据的长度会存在一点问题,但是不影响结果。

5、上板测试

  然后综合工程,并且分配管脚,如下图所示,然后引入ILA调试信号,最后生成比特流。

在这里插入图片描述

图15 引脚分配列表

  然后将比特流下载到开发板,开发板的两个光口通过光纤回环,然后使用ILA抓取数据。

  如下图所示,时高速收发器0发送和接收的一帧数据,接收一帧数据的最后一个有效字节数据为8’h43。

在这里插入图片描述

图16 高速收发器0收发数据时序

  下图是高速收发器1收发一帧数据的时序,由图可知发送一帧数据的最后一个有效字节数据为8’h43,与高速收发器0接收的数据帧一致。

在这里插入图片描述

图17 高速收发器1收发一帧数据时序

  下图是高速收发器1向高速收发器0发送的一帧NFC数据,让高速收发器0在接下来的127个时钟周期内停止发送数据。

在这里插入图片描述

图18 高速收发器1产生NFC时序

  下图是高速收发器0收到高速收发器1发送的NFC数据帧之后,将用户发送数据端口的应答信号拉低127个时钟周期,来达到暂停发送数据的目的。

在这里插入图片描述

图19 高速收发器0的NFC响应时序

  下图是高速收发器0向高速收发器1发送NFC数据帧时序,让高速收发器在接下来的64个时钟内暂停发送数据。

在这里插入图片描述

图20 高速收发器0发送NFC数据帧时序

  当高速收发器1接收到高速收发器0发送的NFC数据帧之后,将用户发送数据端口的应答信号拉低64个时钟来暂停数据的发送。

在这里插入图片描述

图21 高速收发器1的NFC响应时序

  下面对UFC数据帧进行测试,首先将ILA把ufc_tx_req高电平作为触发条件,然后按下开发板的按键,抓取以下数据。

  按键被按下时,高速收发器0会向高速收发器1发送一帧长度为256字节的UFC数据帧。如下图所示,最后一个有效字节数据为8’hf7。

在这里插入图片描述

图22 高速收发器0向高速收发器1发送UFC数据

  下图是高速收发器1接收到上图高速收发器0发出的UFC数据帧,最后一个有效字节数据为8’hf7,证明收发数据正常。

在这里插入图片描述

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

  当按键被按下时,高速收发器1同样会向高速收发器0发送一帧长度为88字节的UFC数据,对应时序如下图所示,最后一个有效字节数据为8’h4f。

在这里插入图片描述

图24 高速收发器1向高速收发器0发送UFC数据

  高速收发器0接收到高速收发器1发送的UFC数据帧,对应时序如下图所示。最后一个有效字节数据为8’h4f,与上图发送数据一致,证明收发数据正常。

在这里插入图片描述

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

  综上,通过仿真和上板测试,完成了对Aurora 64B66B的UFC和NFC的测试,前面的Aurora 8B10B的流控模式使用方式相同,有兴趣的读者可以自己试试。

  至此,GTX关于8B10B,64B66B,以及Aurora 8B10B、Aurora 64B66B的使用到此结束了,经过这一路的学习,面对高速收发器的开发,应该不会存在什么问题了吧。

  本文工程可以在公众号后台回复“Aurora 64B/66B的流控工程”(不包括引号)获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

电路_fpga

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

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

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

打赏作者

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

抵扣说明:

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

余额充值