fpga单bank多通道Aurora配置方法

本文主要记录笔者关于单bank多通道Aurora的开发记录,基于xilinxFPGA平台的Aurora相关IP核。


场景需求

  通常我们使用Aurora时,将一个bank上的多条lane通过AuroraIP核组合起来使用。例如:使用四条lane,对FPGA互联而言,最后就通过Aurora IP转化成了一个M_AXI_STREAM和一个S_AXI_STREAM接口,即只有一个通道。

  但有些时候,我们希望将多条lane通过AuroraIP核组合起来使用。例如:使用四条lane,对FPGA互联而言,最后需要通过Aurora IP转化成了四个M_AXI_STREAM和四个S_AXI_STREAM接口,即四通道。
在这里插入图片描述

  那么问题需求出在哪里呢?如果单纯的像使用一条lane那样将Aurora例化四次,那么编译时将报错不会通过。因为当将AuroraIP核的Shared logic选项配置成include Shared logic in core时,IP核将包含了该bankGT时钟配置,而由于GT收发器的底层原理,一个bank只能有一个GT COMMON

在这里插入图片描述

  因此,我们可以将AuroraIP核的Shared logic选项配置成include Shared logic in example design,并且通过手动配置GT COMMON,这样IP核实例之间就互不影响了。但手动配置GT COMMON,对于不熟悉serdes收发器原理的人来说还是有些难度的。下面介绍一种简便的方法,可以跳过手动配置,仅仅使用xilinxIP核完成单bank多通道Aurora的开发。


整体架构流程

  如下图,通过“一主多从”的方式,可以轻松实现多通道的Aurora。其中一主是将AuroraIP核的Shared logic选项配置成include Shared logic in core,这就完成了GT COMMON和第一个通道的配置;接着例化1~3个多从,即将AuroraIP核的Shared logic选项配置成include Shared logic in example design,并且进行主从信号的连接即可完成单bank多通道Aurora的开发。

在这里插入图片描述


重要信号解释

  • ① pll_not_locked_out: 如果使用PLL为Aurora 8B/10B核心生成时钟信号,则应将pll_not_locked信号连接到PLL锁定信号的反相输出端。如果未使用PLL为Aurora 8B/10B核心生成时钟信号,则将pll_not_locked信号连接到地。即可接地。
  • ② gt0_qplllock, gt0_qpllrefclklost: GTX_COMMON出来的QPLL锁和锁丢失信号,如下图;
  • ③ gt_qpllclk_quard1, gt_qpllrefclk_quard1: GTX_COMMON出来的QPLL时钟信号,如下图;
  • ④ user_clk_out/tx_out_clk, sys_reset_out: 用户时钟和用户端复位,即AXI_STREAM时钟和复位,每个IP核单独为一个时钟域;
  • ⑤ 以上为一主多从的相关信号讲解,其他信号按照Aurora IP核文档说明即可。

在这里插入图片描述


代码实现

  如下,可通过参数生成1~4个Aurora通道。

`timescale 1ns / 1ps
// ********************************************************************************** // 
// Company:               JingCe
// Engineer:              Chen Xiong Zhi
// 
// File name:             aurora_8b10b_wrapper.v
// Create Date:           2024/10/18 14:32:23
// Version:               V1.0
// PATH:                  2018\2018_for_sim\2018_for_sim.srcs\sources_1\new\aurora_8b10b_wrapper.v
// Descriptions:          mutiple aurora channel
// 
// ********************************************************************************** // 
`default_nettype none


module aurora_8b10b_wrapper #(
    parameter                           SFP_CHANNEL               = 2     
) (
    input  wire                         init_clk_in                ,
    input  wire                         reset                      ,// #1000
    input  wire                         gt_reset                   ,// #5000
    // user interface
    output wire        [SFP_CHANNEL-1: 0]user_clk_out              ,
    output wire        [SFP_CHANNEL-1: 0]sys_reset_out             ,

    output wire        [SFP_CHANNEL-1: 0]channel_up                ,
    output wire        [SFP_CHANNEL-1: 0]lane_up                   ,

    input  wire        [SFP_CHANNEL*3-1: 0]loopback                ,

    input  wire        [SFP_CHANNEL*32-1: 0]s_axi_tx_tdata         ,
    input  wire        [SFP_CHANNEL*4-1: 0]s_axi_tx_tkeep          ,
    input  wire        [SFP_CHANNEL-1: 0]s_axi_tx_tlast            ,
    input  wire        [SFP_CHANNEL-1: 0]s_axi_tx_tvalid           ,
    output wire        [SFP_CHANNEL-1: 0]s_axi_tx_tready           ,

    output wire        [SFP_CHANNEL*32-1: 0]m_axi_rx_tdata         ,
    output wire        [SFP_CHANNEL*4-1: 0]m_axi_rx_tkeep          ,
    output wire        [SFP_CHANNEL-1: 0]m_axi_rx_tlast            ,
    output wire        [SFP_CHANNEL-1: 0]m_axi_rx_tvalid           ,
    // to the top level
    input  wire                         gt_refclk1_p               ,
    input  wire                         gt_refclk1_n               ,

    output wire        [SFP_CHANNEL-1: 0]SFP_TXP                   ,
    output wire        [SFP_CHANNEL-1: 0]SFP_TXN                   ,
    input  wire        [SFP_CHANNEL-1: 0]SFP_RXP                   ,
    input  wire        [SFP_CHANNEL-1: 0]SFP_RXN                    
);

// ********************************************************************************** // 
//---------------------------------------------------------------------
// declarations
//---------------------------------------------------------------------
    genvar i;

    wire                                gt_refclk1                 ;
    wire                                gt_refclk1_div2            ;
    wire                                drpclk_in                  ;
    wire                                power_down                 ;

    wire               [SFP_CHANNEL-1: 0]tx_lock                   ;
    wire               [SFP_CHANNEL-1: 0]tx_resetdone_out          ;
    wire               [SFP_CHANNEL-1: 0]rx_resetdone_out          ;
    wire               [SFP_CHANNEL-1: 0]link_reset_out            ;

    wire               [SFP_CHANNEL-1: 0]hard_err                  ;
    wire               [SFP_CHANNEL-1: 0]soft_err                  ;
    wire               [SFP_CHANNEL-1: 0]frame_err                 ;
// master aurora ip
    wire                                gt0_qplllock_out           ;
    wire                                gt0_qpllrefclklost_out     ;
    wire                                gt_qpllclk_quad1_out       ;
    wire                                gt_qpllrefclk_quad1_out    ;
    wire                                sync_clk_out               ;
    wire                                gt_reset_out               ;
    wire                                pll_not_locked_out         ;

// ********************************************************************************** // 
//---------------------------------------------------------------------
// logics
//---------------------------------------------------------------------
    assign                              drpclk_in                 = init_clk_in;

    assign                              power_down                = 'd0;
    
// ********************************************************************************** // 
//---------------------------------------------------------------------
// instance
//---------------------------------------------------------------------

//--- Instance of GT differential buffer ---------//
IBUFDS_GTE2 #(
    .CLKCM_CFG                          ("TRUE"                    ),// Refer to Transceiver User Guide
    .CLKRCV_TRST                        ("TRUE"                    ),// Refer to Transceiver User Guide
    .CLKSWING_CFG                       (2'b11                     ) // Refer to Transceiver User Guide
)
u_IBUFDS_GTE2 (
    .I                                  (gt_refclk1_p              ),
    .IB                                 (gt_refclk1_n              ),
    .CEB                                (1'b0                      ),
    .O                                  (gt_refclk1                ),
    .ODIV2                              (gt_refclk1_div2           ) 
);
// ********************************************************************************** // 
//---------------------------------------------------------------------
// aurora_8b10b_master
//---------------------------------------------------------------------
aurora_8b10b_master u_aurora_8b10b_master (
    // AXI TX Interface
    .s_axi_tx_tdata                     (s_axi_tx_tdata[0*32 +: 32]),// input wire [31 : 0] s_axi_tx_tdata
    .s_axi_tx_tkeep                     (s_axi_tx_tkeep[0*4 +: 4]  ),// input wire [3 : 0] s_axi_tx_tkeep
    .s_axi_tx_tlast                     (s_axi_tx_tlast[0]         ),// input wire s_axi_tx_tlast
    .s_axi_tx_tvalid                    (s_axi_tx_tvalid[0]        ),// input wire s_axi_tx_tvalid
    .s_axi_tx_tready                    (s_axi_tx_tready[0]        ),// output wire s_axi_tx_tready
    // AXI RX Interface
    .m_axi_rx_tdata                     (m_axi_rx_tdata[0*32 +: 32]),// output wire [31 : 0] m_axi_rx_tdata
    .m_axi_rx_tkeep                     (m_axi_rx_tkeep[0*4 +: 4]  ),// output wire [3 : 0] m_axi_rx_tkeep
    .m_axi_rx_tlast                     (m_axi_rx_tlast[0]         ),// output wire m_axi_rx_tlast
    .m_axi_rx_tvalid                    (m_axi_rx_tvalid[0]        ),// output wire m_axi_rx_tvalid
    // V5 Serial I/O
    .txp                                (SFP_TXP[0]                ),// output wire [0 : 0] txp
    .txn                                (SFP_TXN[0]                ),// output wire [0 : 0] txn
    .rxp                                (SFP_RXP[0]                ),// input wire [0 : 0] rxp
    .rxn                                (SFP_RXN[0]                ),// input wire [0 : 0] rxn
    // GT Reference Clock Interface
    .gt_refclk1                         (gt_refclk1                ),// input wire gt_refclk1
    // Error Detection Interface
    .hard_err                           (hard_err[0]               ),// output wire hard_err
    .soft_err                           (soft_err[0]               ),// output wire soft_err
    .frame_err                          (frame_err[0]              ),// output wire frame_err
    // Status
    .channel_up                         (channel_up[0]             ),// output wire channel_up
    .lane_up                            (lane_up[0]                ),// output wire [0 : 0] lane_up
    // System Interface
    .user_clk_out                       (user_clk_out[0]           ),// output wire user_clk_out
    .sys_reset_out                      (sys_reset_out[0]          ),// output wire sys_reset_out

    .reset                              (reset                     ),// input wire reset
    .gt_reset                           (gt_reset                  ),// input wire gt_reset
    .sync_clk_out                       (sync_clk_out              ),// output wire sync_clk_out
    .gt_reset_out                       (gt_reset_out              ),// output wire gt_reset_out
    .init_clk_in                        (init_clk_in               ),// input wire init_clk_in
    .pll_not_locked_out                 (pll_not_locked_out        ),// output wire pll_not_locked_out

    .drpclk_in                          (drpclk_in                 ),// input wire drpclk_in
    .drpaddr_in                         (9'h0                      ),// input wire [8 : 0] drpaddr_in
    .drpen_in                           (1'b0                      ),// input wire drpen_in
    .drpdi_in                           (16'h0                     ),// input wire [15 : 0] drpdi_in
    .drprdy_out                         (                          ),// output wire drprdy_out
    .drpdo_out                          (                          ),// output wire [15 : 0] drpdo_out
    .drpwe_in                           (1'b0                      ),// input wire drpwe_in

    .loopback                           (loopback[0*3 +: 3]        ),// input wire [2 : 0] loopback
    .power_down                         (power_down                ),// input wire power_down
    .tx_lock                            (tx_lock[0]                ),// output wire tx_lock
    .tx_resetdone_out                   (tx_resetdone_out[0]       ),// output wire tx_resetdone_out
    .rx_resetdone_out                   (rx_resetdone_out[0]       ),// output wire rx_resetdone_out
    .link_reset_out                     (link_reset_out[0]         ),// output wire link_reset_out
//____________________________COMMON PORTS _______________________________
//    ------------------------- Common Block - QPLL Ports ------------------------
    .gt0_qplllock_out                   (gt0_qplllock_out          ),// output wire gt0_qplllock_out
    .gt0_qpllrefclklost_out             (gt0_qpllrefclklost_out    ),// output wire gt0_qpllrefclklost_out
    .gt_qpllclk_quad1_out               (gt_qpllclk_quad1_out      ),// output wire gt_qpllclk_quad1_out
    .gt_qpllrefclk_quad1_out            (gt_qpllrefclk_quad1_out   ) // output wire gt_qpllrefclk_quad1_out
);

// ********************************************************************************** // 
//---------------------------------------------------------------------
// instance slave
//---------------------------------------------------------------------
generate
    for (i = 1; i < SFP_CHANNEL; i = i+1) begin : s

aurora_8b10b_slave u_aurora_8b10b_slave (
    // AXI TX Interface
    .s_axi_tx_tdata                     (s_axi_tx_tdata[i*32 +: 32]),// input wire [31 : 0] s_axi_tx_tdata
    .s_axi_tx_tkeep                     (s_axi_tx_tkeep[i*4 +: 4]  ),// input wire [3 : 0] s_axi_tx_tkeep
    .s_axi_tx_tlast                     (s_axi_tx_tlast[i]         ),// input wire s_axi_tx_tlast
    .s_axi_tx_tvalid                    (s_axi_tx_tvalid[i]        ),// input wire s_axi_tx_tvalid
    .s_axi_tx_tready                    (s_axi_tx_tready[i]        ),// output wire s_axi_tx_tready
    // AXI RX Interface
    .m_axi_rx_tdata                     (m_axi_rx_tdata[i*32 +: 32]),// output wire [31 : 0] m_axi_rx_tdata
    .m_axi_rx_tkeep                     (m_axi_rx_tkeep[i*4 +: 4]  ),// output wire [3 : 0] m_axi_rx_tkeep
    .m_axi_rx_tlast                     (m_axi_rx_tlast[i]         ),// output wire m_axi_rx_tlast
    .m_axi_rx_tvalid                    (m_axi_rx_tvalid[i]        ),// output wire m_axi_rx_tvalid
    // GT Serial I/O
    .txp                                (SFP_TXP[i]                ),// output wire [0 : 0] txp
    .txn                                (SFP_TXN[i]                ),// output wire [0 : 0] txn
    .rxp                                (SFP_RXP[i]                ),// input wire [0 : 0] rxp
    .rxn                                (SFP_RXN[i]                ),// input wire [0 : 0] rxn
    // GT Reference Clock Interface
    .gt_refclk1                         (gt_refclk1                ),// input wire gt_refclk1
    // Error Detection Interface
    .hard_err                           (hard_err[i]               ),// output wire hard_err
    .soft_err                           (soft_err[i]               ),// output wire soft_err
    .frame_err                          (frame_err[i]              ),// output wire frame_err
    // Status
    .channel_up                         (channel_up[i]             ),// output wire channel_up
    .lane_up                            (lane_up[i]                ),// output wire [0 : 0] lane_up
    // System Interface
    .tx_out_clk                         (user_clk_out[i]           ),// output wire tx_out_clk
    .sys_reset_out                      (sys_reset_out[i]          ),// output wire sys_reset_out
    .reset                              (sys_reset_out[0]          ),// input wire reset
    .gt_reset                           (gt_reset_out              ),// input wire gt_reset
    
    .drpclk_in                          (drpclk_in                 ),// input wire drpclk_in
    .drpaddr_in                         (9'h0                      ),// input wire [8 : 0] drpaddr_in
    .drpen_in                           (1'b0                      ),// input wire drpen_in
    .drpdi_in                           (16'h0                     ),// input wire [15 : 0] drpdi_in
    .drprdy_out                         (                          ),// output wire drprdy_out
    .drpdo_out                          (                          ),// output wire [15 : 0] drpdo_out
    .drpwe_in                           (1'b0                      ),// input wire drpwe_in

    .loopback                           (loopback[i*3 +: 3]        ),// input wire [2 : 0] loopback
    .power_down                         (power_down                ),// input wire power_down
    .tx_lock                            (tx_lock[i]                ),// output wire tx_lock
    .tx_resetdone_out                   (tx_resetdone_out[i]       ),// output wire tx_resetdone_out
    .rx_resetdone_out                   (rx_resetdone_out[i]       ),// output wire rx_resetdone_out
    .link_reset_out                     (link_reset_out[i]         ),// output wire link_reset_out
    
    .init_clk_in                        (init_clk_in               ),// input wire init_clk_in
    .pll_not_locked                     (pll_not_locked_out        ),// input wire pll_not_locked
    .sync_clk                           (sync_clk_out              ),// input wire sync_clk
    .user_clk                           (user_clk_out[0]           ),// input wire user_clk
//------------------{
//_________________COMMON PORTS _______________________________{
//    ------------------------- Common Block - QPLL Ports ------------------------
    .gt0_qplllock_in                    (gt0_qplllock_out          ),// input wire gt0_qplllock_in
    .gt0_qpllrefclklost_in              (gt0_qpllrefclklost_out    ),// input wire gt0_qpllrefclklost_in
    .gt0_qpllreset_out                  (                          ),// output wire gt0_qpllreset_out
    .gt_qpllclk_quad1_in                (gt_qpllclk_quad1_out      ),// input wire gt_qpllclk_quad1_in
    .gt_qpllrefclk_quad1_in             (gt_qpllrefclk_quad1_out   ) // input wire gt_qpllrefclk_quad1_in
//____________________________COMMON PORTS ,_______________________________}
//------------------}
);

    end
endgenerate


endmodule


`default_nettype wire

仿真验证

  仿真结果如下,四个通道的channel up均能正常拉高,表面链路建立完成:
在这里插入图片描述

小结

  该方案的本质还是单独配置GT COMMON,然后使用XilinxAurora IP核(shared logic配置为in the example),我们可以通过反复的练习思考,掌握高速收发器的使用方法。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值