Xilinx Aurora 64B66B IP 仿真测试

1 Aurora  64B66B IP 简介

   Aurora  64B66B IP 核是Xilinx 推出的可扩展、轻量级、高速串行通信的链路层协议,一般用于FPGA芯片间的高速通信。相较于8B/10B编码方案,其理论性能更优,8B10B需要25%的传输开销,64B/66B编码仅需3%的开销,显著提升传输效率。

image

2 Aurora 64B66B IP 配置

   64B66B IP和8B10B IP的配置基本相同,相对于8B10B IP,目前V12.0 暂时不支持链路位宽调整。下面为单lane配置示意。

image

image

image

3 Aurora 64B66B IP 用户接口操作时序

3.1 Framing数据接口时序

  Framing数据接口TX端的操作时序如下图所示,RX端相对TX端少了axi_tready的信号,相当于RX的数据接口是没有弹性缓冲机制,若用户有弹性需求,其实只需要直接在RX数据端添加一个FIFO即可。

image

image

3.2 Streaming数据接口时序

image

image

4 流量控制

4.1 Native Flow Control

   本地流控是接收方反制发送方的手段。一般情形下,若接收方处理数据速率慢于发送方的发送速率时,接收方就可以通过NFC反制发送方,甚至让发送方完全停止发送。

4.2 User Flow Control 

   用户流控相当于简短的高优先级数据传输,传输最大字节数为256。

4.3 User-K Block

   USER-K块是一种特殊单块代码,其控制块可直接传递至用户应用程序,无需经过Aurora 64B/66B接口解码。这类代码块可用于实现特定应用的控制功能,其优先级低于UFC块但高于用户数据块。

5 Aurora 64B66B IP 仿真

5.1 仿真流程

  例化两个Aurora 64B66B IP核,将他们的RX/TX Serdes 物理接口对接,也就是TX0-->RX1/TX1-->RX0。待双方链路建立完毕后,TX端发送数据,RX端接收数据并比较,比较出错产生error信号。

5.2 仿真TestBench

`timescale 1 ns/1 ps
`define clk_period 8

module aurora_64b66b_tb();

reg             clk                           ;
reg             rst_n                         ;

//--------------- u0 signal ------------------//
reg  [63:0]     u0_s_axi_tx_tdata             ;
reg             u0_s_axi_tx_tlast             ;
reg  [7:0]      u0_s_axi_tx_tkeep             ;
reg             u0_s_axi_tx_tvalid            ;
wire            u0_s_axi_tx_tready            ;

wire [63:0]     u0_m_axi_rx_tdata             ;
wire            u0_m_axi_rx_tlast             ;
wire [7:0]      u0_m_axi_rx_tkeep             ;
wire            u0_m_axi_rx_tvalid            ;

wire [0:0]      u0_rxp                        ;
wire [0:0]      u0_rxn                        ;
wire [0:0]      u0_txp                        ;
wire [0:0]      u0_txn                        ;

wire            u0_gt_refclk1_p               ;
wire            u0_gt_refclk1_n               ;
wire            u0_gt_refclk1_out             ;

wire            u0_init_clk_p                 ;
wire            u0_init_clk_n                 ;

wire            u0_hard_err                   ;
wire            u0_soft_err                   ;
wire            u0_channel_up                 ;
wire [0:0]      u0_lane_up                    ;
wire            u0_user_clk_out               ;
wire            u0_init_clk_out               ;
wire            u0_mmcm_not_locked_out        ;
wire            u0_sync_clk_out               ;

wire            u0_reset_pb                   ;
wire            u0_gt_rxcdrovrden_in          ;
wire            u0_power_down                 ;
wire[2:0]       u0_loopback                   ;
wire            u0_pma_init                   ;
wire            u0_gt_pll_lock                ;

wire            u0_drp_clk_in                 ;
wire [31:0]     u0_s_axi_awaddr               ;
wire            u0_s_axi_awvalid              ;
wire            u0_s_axi_awready              ;
wire [31:0]     u0_s_axi_wdata                ;
wire [3:0]      u0_s_axi_wstrb                ;
wire            u0_s_axi_wvalid               ;
wire            u0_s_axi_wready               ;
wire            u0_s_axi_bvalid               ;
wire [1:0]      u0_s_axi_bresp                ;
wire            u0_s_axi_bready               ;
wire [31:0]     u0_s_axi_araddr               ;
wire            u0_s_axi_arvalid              ;
wire            u0_s_axi_arready              ;
wire [31:0]     u0_s_axi_rdata                ;
wire            u0_s_axi_rvalid               ;
wire [1:0]      u0_s_axi_rresp                ;
wire            u0_s_axi_rready               ;

wire            u0_link_reset_out             ;
wire            u0_gt_qpllclk_quad1_out       ;
wire            u0_gt_qpllrefclk_quad1_out    ;
wire            u0_sys_reset_out              ;
wire            u0_gt_reset_out               ;
wire            u0_tx_out_clk                 ;

//--------------- u1 signal ------------------//
reg  [63:0]     u1_s_axi_tx_tdata             ;
reg             u1_s_axi_tx_tlast             ;
reg  [7:0]      u1_s_axi_tx_tkeep             ;
reg             u1_s_axi_tx_tvalid            ;
wire            u1_s_axi_tx_tready            ;

wire [63:0]     u1_m_axi_rx_tdata             ;
wire            u1_m_axi_rx_tlast             ;
wire [7:0]      u1_m_axi_rx_tkeep             ;
wire            u1_m_axi_rx_tvalid            ;

wire [0:0]      u1_rxp                        ;
wire [0:0]      u1_rxn                        ;
wire [0:0]      u1_txp                        ;
wire [0:0]      u1_txn                        ;

wire            u1_gt_refclk1_p               ;
wire            u1_gt_refclk1_n               ;
wire            u1_gt_refclk1_out             ;

wire            u1_init_clk_p                 ;
wire            u1_init_clk_n                 ;

wire            u1_hard_err                   ;
wire            u1_soft_err                   ;
wire            u1_channel_up                 ;
wire [0:0]      u1_lane_up                    ;
wire            u1_user_clk_out               ;
wire            u1_init_clk_out               ;
wire            u1_mmcm_not_locked_out        ;
wire            u1_sync_clk_out               ;

wire            u1_reset_pb                   ;
wire            u1_gt_rxcdrovrden_in          ;
wire            u1_power_down                 ;
wire[2:0]       u1_loopback                   ;
wire            u1_pma_init                   ;
wire            u1_gt_pll_lock                ;

wire            u1_drp_clk_in                 ;
wire [31:0]     u1_s_axi_awaddr               ;
wire            u1_s_axi_awvalid              ;
wire            u1_s_axi_awready              ;
wire [31:0]     u1_s_axi_wdata                ;
wire [3:0]      u1_s_axi_wstrb                ;
wire            u1_s_axi_wvalid               ;
wire            u1_s_axi_wready               ;
wire            u1_s_axi_bvalid               ;
wire [1:0]      u1_s_axi_bresp                ;
wire            u1_s_axi_bready               ;
wire [31:0]     u1_s_axi_araddr               ;
wire            u1_s_axi_arvalid              ;
wire            u1_s_axi_arready              ;
wire [31:0]     u1_s_axi_rdata                ;
wire            u1_s_axi_rvalid               ;
wire [1:0]      u1_s_axi_rresp                ;
wire            u1_s_axi_rready               ;

wire            u1_link_reset_out             ;
wire            u1_gt_qpllclk_quad1_out       ;
wire            u1_gt_qpllrefclk_quad1_out    ;
wire            u1_sys_reset_out              ;
wire            u1_gt_reset_out               ;
wire            u1_tx_out_clk                 ;

reg  [63:0]     u0_check_data_cnt             ;
reg             u0_check_data_err             ;

reg  [63:0]     u1_check_data_cnt             ;
reg             u1_check_data_err             ;


initial     clk = 1;
always #(`clk_period/2) clk = ~clk;

assign u0_gt_refclk1_p =  clk;
assign u0_gt_refclk1_n = ~clk;

assign u0_init_clk_p   =  clk;
assign u0_init_clk_n   = ~clk;

assign u0_drp_clk_in   =  clk;

assign u1_gt_refclk1_p =  clk;
assign u1_gt_refclk1_n = ~clk;

assign u1_init_clk_p   =  clk;
assign u1_init_clk_n   = ~clk;

assign u1_drp_clk_in   =  clk; 

initial begin
    rst_n = 1;
    #1000
    rst_n = 0;
    #10000000;
    $display("Simulation Time Overflow %0t", $time);
    $stop;
end

assign u0_reset_pb          = rst_n;
assign u0_power_down        = 'b0;
assign u0_pma_init          = 'b0;
assign u0_loopback          = 'b0;
assign u0_gt_rxcdrovrden_in = 'b0;

assign u1_reset_pb          = rst_n;
assign u1_power_down        = 'b0;
assign u1_pma_init          = 'b0;
assign u1_loopback          = 'b0;
assign u1_gt_rxcdrovrden_in = 'b0;

assign u0_rxp = u1_txp;
assign u0_rxn = u1_txn;

assign u1_rxp = u0_txp;
assign u1_rxn = u0_txn;


initial begin
    u0_s_axi_tx_tdata  = 'h0000_0000;
    u0_s_axi_tx_tlast  = 'b0;
    u0_s_axi_tx_tkeep  = 'b0;
    u0_s_axi_tx_tvalid = 'b0;    
    #1200;
    while(~u0_channel_up) @(posedge u0_user_clk_out);
    #200;
    u0_tx_task;    
    #200;
    u0_tx_task;
    #200;
    u0_tx_task;
end

initial begin
    u1_s_axi_tx_tdata  = 'hffff_0000;
    u1_s_axi_tx_tlast  = 'b0;
    u1_s_axi_tx_tkeep  = 'b0;
    u1_s_axi_tx_tvalid = 'b0;    
    #1200;
    while(~u1_channel_up) @(posedge u1_user_clk_out);
    #400;
    u1_tx_task;    
    #400;
    u1_tx_task;
    #400;
    u1_tx_task;
    #400;
    u1_tx_task;
end

initial begin
    u0_check_data_cnt = 'hffff_0000;
    u0_check_data_err = 'b0;
    while(~u0_channel_up) @(posedge u0_user_clk_out);
    
    while(1) begin
        if(u0_m_axi_rx_tvalid) begin
            u0_check_data_cnt = u0_check_data_cnt + 1'b1;
            u0_check_data_err = u0_check_data_cnt != u0_m_axi_rx_tdata;
        end
        @(posedge u0_user_clk_out);
    end
end

initial begin
    u1_check_data_cnt = 'h0000_0000;
    u1_check_data_err = 'b0;
    while(~u1_channel_up) @(posedge u1_user_clk_out);
    
    while(1) begin
        if(u1_m_axi_rx_tvalid) begin
            u1_check_data_cnt = u1_check_data_cnt + 1'b1;
            u1_check_data_err = u1_check_data_cnt != u1_m_axi_rx_tdata;
        end
        @(posedge u1_user_clk_out);
    end
end

task u0_tx_task;
    @(posedge u0_user_clk_out);
    @(posedge u0_user_clk_out);
    repeat(1024) begin
        u0_s_axi_tx_tlast  = &u0_s_axi_tx_tdata[5:0];
        u0_s_axi_tx_tkeep  = 8'hff;
        u0_s_axi_tx_tvalid = 1'b1;    
        u0_s_axi_tx_tdata  = u0_s_axi_tx_tdata + 1'b1;
        @(posedge u0_user_clk_out);
        while(~u0_s_axi_tx_tready) @(posedge u0_user_clk_out);
        u0_s_axi_tx_tvalid = 1'b0;    
        u0_s_axi_tx_tlast  = 1'b0;
    end
endtask

task u1_tx_task;
    @(posedge u1_user_clk_out);
    @(posedge u1_user_clk_out);
    repeat(1024) begin
        u1_s_axi_tx_tlast  = &u1_s_axi_tx_tdata[5:0];
        u1_s_axi_tx_tkeep  = 8'hff;
        u1_s_axi_tx_tvalid = 1'b1;    
        u1_s_axi_tx_tdata  = u1_s_axi_tx_tdata + 1'b1;
        @(posedge u1_user_clk_out);
        while(~u1_s_axi_tx_tready) @(posedge u1_user_clk_out);
        u1_s_axi_tx_tvalid = 1'b0;    
        u1_s_axi_tx_tlast  = 1'b0;
    end
endtask


aurora_64b66b_0 u0_aurora_ip(
    .s_axi_tx_tdata         (u0_s_axi_tx_tdata            ),
    .s_axi_tx_tlast         (u0_s_axi_tx_tlast            ),
    .s_axi_tx_tkeep         (u0_s_axi_tx_tkeep            ),
    .s_axi_tx_tvalid        (u0_s_axi_tx_tvalid           ),
    .s_axi_tx_tready        (u0_s_axi_tx_tready           ),
    .m_axi_rx_tdata         (u0_m_axi_rx_tdata            ),
    .m_axi_rx_tlast         (u0_m_axi_rx_tlast            ),
    .m_axi_rx_tkeep         (u0_m_axi_rx_tkeep            ),
    .m_axi_rx_tvalid        (u0_m_axi_rx_tvalid           ),
    .rxp                    (u0_rxp                       ),
    .rxn                    (u0_rxn                       ),
    .txp                    (u0_txp                       ),
    .txn                    (u0_txn                       ),
    .gt_refclk1_p           (u0_gt_refclk1_p              ),
    .gt_refclk1_n           (u0_gt_refclk1_n              ),
    .gt_refclk1_out         (u0_gt_refclk1_out            ),
    .hard_err               (u0_hard_err                  ),
    .soft_err               (u0_soft_err                  ),
    .channel_up             (u0_channel_up                ),
    .lane_up                (u0_lane_up                   ),
    .user_clk_out           (u0_user_clk_out              ),
    .init_clk_out           (u0_init_clk_out              ),
    .mmcm_not_locked_out    (u0_mmcm_not_locked_out       ),
    .sync_clk_out           (u0_sync_clk_out              ),
    .reset_pb               (u0_reset_pb                  ),
    .gt_rxcdrovrden_in      (u0_gt_rxcdrovrden_in         ),
    .power_down             (u0_power_down                ),
    .loopback               (u0_loopback                  ),
    .pma_init               (u0_pma_init                  ),
    .gt_pll_lock            (u0_gt_pll_lock               ),
    .drp_clk_in             (u0_drp_clk_in                ),
    .s_axi_awaddr           (u0_s_axi_awaddr              ),
    .s_axi_awvalid          (u0_s_axi_awvalid             ),
    .s_axi_awready          (u0_s_axi_awready             ),
    .s_axi_wdata            (u0_s_axi_wdata               ),
    .s_axi_wstrb            (u0_s_axi_wstrb               ),
    .s_axi_wvalid           (u0_s_axi_wvalid              ),
    .s_axi_wready           (u0_s_axi_wready              ),
    .s_axi_bvalid           (u0_s_axi_bvalid              ),
    .s_axi_bresp            (u0_s_axi_bresp               ),
    .s_axi_bready           (u0_s_axi_bready              ),
    .s_axi_araddr           (u0_s_axi_araddr              ),
    .s_axi_arvalid          (u0_s_axi_arvalid             ),
    .s_axi_arready          (u0_s_axi_arready             ),
    .s_axi_rdata            (u0_s_axi_rdata               ),
    .s_axi_rvalid           (u0_s_axi_rvalid              ),
    .s_axi_rresp            (u0_s_axi_rresp               ),
    .s_axi_rready           (u0_s_axi_rready              ),
    .init_clk_p             (u0_init_clk_p                ),
    .init_clk_n             (u0_init_clk_n                ),
    .link_reset_out         (u0_link_reset_out            ),
    .gt_qpllclk_quad1_out   (u0_gt_qpllclk_quad1_out      ),
    .gt_qpllrefclk_quad1_out(u0_gt_qpllrefclk_quad1_out   ),
    .sys_reset_out          (u0_sys_reset_out             ),
    .gt_reset_out           (u0_gt_reset_out              ),
    .tx_out_clk             (u0_tx_out_clk                )
);

aurora_64b66b_0 u1_aurora_ip(
    .s_axi_tx_tdata         (u1_s_axi_tx_tdata            ),
    .s_axi_tx_tlast         (u1_s_axi_tx_tlast            ),
    .s_axi_tx_tkeep         (u1_s_axi_tx_tkeep            ),
    .s_axi_tx_tvalid        (u1_s_axi_tx_tvalid           ),
    .s_axi_tx_tready        (u1_s_axi_tx_tready           ),
    .m_axi_rx_tdata         (u1_m_axi_rx_tdata            ),
    .m_axi_rx_tlast         (u1_m_axi_rx_tlast            ),
    .m_axi_rx_tkeep         (u1_m_axi_rx_tkeep            ),
    .m_axi_rx_tvalid        (u1_m_axi_rx_tvalid           ),
    .rxp                    (u1_rxp                       ),
    .rxn                    (u1_rxn                       ),
    .txp                    (u1_txp                       ),
    .txn                    (u1_txn                       ),
    .gt_refclk1_p           (u1_gt_refclk1_p              ),
    .gt_refclk1_n           (u1_gt_refclk1_n              ),
    .gt_refclk1_out         (u1_gt_refclk1_out            ),
    .hard_err               (u1_hard_err                  ),
    .soft_err               (u1_soft_err                  ),
    .channel_up             (u1_channel_up                ),
    .lane_up                (u1_lane_up                   ),
    .user_clk_out           (u1_user_clk_out              ),
    .init_clk_out           (u1_init_clk_out              ),
    .mmcm_not_locked_out    (u1_mmcm_not_locked_out       ),
    .sync_clk_out           (u1_sync_clk_out              ),
    .reset_pb               (u1_reset_pb                  ),
    .gt_rxcdrovrden_in      (u1_gt_rxcdrovrden_in         ),
    .power_down             (u1_power_down                ),
    .loopback               (u1_loopback                  ),
    .pma_init               (u1_pma_init                  ),
    .gt_pll_lock            (u1_gt_pll_lock               ),
    .drp_clk_in             (u1_drp_clk_in                ),
    .s_axi_awaddr           (u1_s_axi_awaddr              ),
    .s_axi_awvalid          (u1_s_axi_awvalid             ),
    .s_axi_awready          (u1_s_axi_awready             ),
    .s_axi_wdata            (u1_s_axi_wdata               ),
    .s_axi_wstrb            (u1_s_axi_wstrb               ),
    .s_axi_wvalid           (u1_s_axi_wvalid              ),
    .s_axi_wready           (u1_s_axi_wready              ),
    .s_axi_bvalid           (u1_s_axi_bvalid              ),
    .s_axi_bresp            (u1_s_axi_bresp               ),
    .s_axi_bready           (u1_s_axi_bready              ),
    .s_axi_araddr           (u1_s_axi_araddr              ),
    .s_axi_arvalid          (u1_s_axi_arvalid             ),
    .s_axi_arready          (u1_s_axi_arready             ),
    .s_axi_rdata            (u1_s_axi_rdata               ),
    .s_axi_rvalid           (u1_s_axi_rvalid              ),
    .s_axi_rresp            (u1_s_axi_rresp               ),
    .s_axi_rready           (u1_s_axi_rready              ),
    .init_clk_p             (u1_init_clk_p                ),
    .init_clk_n             (u1_init_clk_n                ),
    .link_reset_out         (u1_link_reset_out            ),
    .gt_qpllclk_quad1_out   (u1_gt_qpllclk_quad1_out      ),
    .gt_qpllrefclk_quad1_out(u1_gt_qpllrefclk_quad1_out   ),
    .sys_reset_out          (u1_sys_reset_out             ),
    .gt_reset_out           (u1_gt_reset_out              ),
    .tx_out_clk             (u1_tx_out_clk                )
);

endmodule
View Code

5.3 仿真波形

  从仿真波形看出,双方的channel_up 后,开始发送数据,接收数据后开始比较数据,两端的rx_data_err保持置0 ,说明两端数据交互正常。

image

6 参考链接

1)Introduction • Aurora 64B/66B LogiCORE IP Product Guide (PG074) • 阅读器 • AMD 技术信息门户网站

2)Aurora 64B/66B Protocol Specification (SP011) • 查看器 • AMD 技术信息门户网站

posted @ 2025-12-04 20:21  KD_one  阅读(4)  评论(0)    收藏  举报