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

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



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


3.2 Streaming数据接口时序


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

6 参考链接
1)Introduction • Aurora 64B/66B LogiCORE IP Product Guide (PG074) • 阅读器 • AMD 技术信息门户网站
2)Aurora 64B/66B Protocol Specification (SP011) • 查看器 • AMD 技术信息门户网站

浙公网安备 33010602011771号