[FPGA] Aurora8B10B IP使用 - 收发测试应用示例

[复制链接]
2274|0
 楼主| Williamwxh 发表于 2022-8-22 19:31 | 显示全部楼层 |阅读模式
前言
本文首先介绍了根据网上博文简单介绍了8B/10B的原理,并根据Aurora IP的相关使用方法,参考IP手册进行设计递增数测试用例,并下板进行实际验证。
8B/10B简介
8B/10B,也叫做8比特/10比特或8b10b。8b/10b方式最初由IBM公司于1983年发明并应用于ESCON(200M互连系统),由Al Widmer和Peter Franaszek在IBM的刊物“研究与开发”上描述。
8b/10b编码的特性之一是保证DC 平衡,采用8b/10b编码方式,可使得发送的“0”、“1”数量保持基本一致,连续的“1”或“0”不超过5位,即每5个连续的“1”或“0”后必须插入一位“0”或“1”,从而保证信号DC平衡,它就是说,在链路超时时不致发生DC失调。通过8b/10b编码,可以保证传输的数据串在接收端能够被正确复原,除此之外,利用一些特殊的代码( 在PCI-Express总线中为K码) ,可以帮助接收端进行还原的工作,并且可以在早期发现数据位的传输错误,抑制错误继续发生。
8b/10b编码是将一组连续的8位数据分解成两组数据,一组3位,一组5位,经过编码后分别成为一组4位的代码和一组6位的代码,从而组成一组10位的数据发送出去。相反,解码是将1组10位的输入数据经过变换得到8位数据位。数据值可以统一的表示为DX.Y或KX.Y,其中D表示为数据代码,K表示为特殊的命令代码,X表示输入的原始数据的低5位EDCBA,Y 表示输入的原始数据的高3位HGF。
8b/10b编码是目前许多高速串行总线采用的编码机制,如 USB3.0、1394b、Serial ATA、PCI Express、Infini-band、Fibre Channel(光纤通道)、RapidIO等总线或网络等。
工作原理
8B/10B编码是目前高速串行通信中经常用到的一种编码方式。将8bit编码成10bit后,10B中0和1的位数只可能出现3种情况:
有5个0和5个1
有6个0和4个1
有4个0和6个1
这样引出了一个新术语“不均等性(Disparity)”,就是1的位数和0的位数的差值,根据上面3种情况就有对应的3个Disparity 0、-2、+2。8bit原始数据会分成两部分,其低5位会进行5B/6B编码,高3位则进行3B/4B编码,这两种映射关系在当时已经成为了一个标准化的表格。人们喜欢把8bit数据表示成Dx.y的形式,其x=5LSB(least significant bit最低有效位),y=3MSB(most significant bit最高有效位)。
例如一个8bit数据101 10101,x=10101(21) y="101"(5),现在我们就把这8bit数据写成D21.5。
对于8bit数据,它在表中的位序为HGFEDCBA,即H为最高位,A为最低位,EDCBA经过5B/6B编码为abcdei,HGF经过3B/4B编码为fghj。传送10bit编码的顺序为abcdeifghj。

创建工程
新建一个空白工程,这里我选择的芯片型号为xc7k160tffg676-2,米联客MK7160FA。
配置Aurora IP
创建完工程,将Aurora IP添加到工程下,并修改相关配置。lane宽度设置为4,接口则生成32位宽的数据,若选择2,则生成16位宽的数据。

由于只是进行传输测试,所以该界面的相关参数就根据板卡的相关时钟进行配置即可,Link层选择帧模式,其余默认即可。
米联客的板卡在MGT的116对外引出,所以这里对应连接到GTXQ1上。

共享逻辑选择包含在内核中,并使能初始化时钟的单端口时钟选项,Aurora IP配置完成。

程序架构设计
参考例程的思路,这里设计了Aurora发送递增数的测试示例,主要包含四个模块,复位模块,Aurora发送数据生成模块,Aurora接收数据模块,Aurora IP。
复位模块主要用于对reset和gt_reset两个信号进行初始化复位,确保Aurora IP能正常工作。
Aurora发送数据生成模块,根据AXI总线协议进行生成递增测试数据,然后通过Aurora IP将数据通过光口传输。
Aurora接收数据模块,根据AXI总线协议接收数据,并通过接收计数信号进行比对递增数传输是否存在错误,用于错误指示。

复位模块
复位模块使用start_en作为复位的指示信号,当检测到start_en的上升沿时,模块对系统复位信号和收发器的复位信号进行复位。reset和gt_reset根据手册中推荐的复位时序进行复位。在该文中有详细介绍, HYPERLINK "https://blog.csdn.net/weixin_41445387/article/details/125182703?spm=1001.2014.3001.5501" \h 。
  1. `timescale 1ns / 1ps
  2. module rst_ctrl(
  3.         input        wire                         clk                                 ,
  4.         input        wire                         start_en            ,
  5.         output         wire                         reset                                 ,// 系统复位
  6.         output         wire                         gt_reset                           // 收发器复位
  7.     );

  8. //parameter define
  9. parameter GT_RESET_START = 128  ;
  10. parameter GT_RESET_END = 384 ;
  11. parameter RESET_MAX = GT_RESET_END + GT_RESET_START;

  12. //reg define
  13. reg             reset_r          ;
  14. reg             gt_reset_r       ;
  15. reg             reset_busy     =0;//复位忙指示信号
  16. reg         [1:0]        start_flag_dly =0;//复位使能信号延时
  17. reg         [10:0]        cnt_rst        =0;//用于产生复位信号的计数器

  18. //wire define
  19. assign    reset = reset_r   ;
  20. assign gt_reset = gt_reset_r;

  21. //起始信号边沿
  22. wire link_up_n = !start_flag_dly[1]&&start_flag_dly[0];
  23. //start_flag_dly
  24. always @(posedge clk) begin
  25.         start_flag_dly <= {start_flag_dly[0], start_en};
  26. end

  27. //复位忙指示信号
  28. always @(posedge clk) begin
  29.         if(link_up_n==1) begin
  30.                 reset_busy <= 1;
  31.         end
  32.         else if(cnt_rst== RESET_MAX - 1)begin
  33.                 reset_busy <= 0;
  34.         end
  35. end

  36. //复位计数器
  37. always @(posedge clk) begin
  38.         if (reset_busy == 'd1) begin
  39.                 if(reset_busy == 'd1 && (cnt_rst == RESET_MAX - 1))
  40.                         cnt_rst <= 'd0;
  41.                 else
  42.                         cnt_rst <= cnt_rst + 1'b1;
  43.         end
  44.         else begin
  45.                 cnt_rst <= 'd0;
  46.         end
  47. end

  48. //gt_reset
  49. always @(posedge clk) begin
  50.         if (reset_busy == 'd1) begin
  51.                 if(cnt_rst == GT_RESET_START - 1) begin
  52.                         gt_reset_r <= 1'b1;
  53.                 end
  54.                 else if (cnt_rst == GT_RESET_END - 1|| cnt_rst == 0 ) begin
  55.                         gt_reset_r <= 1'b0;
  56.                 end
  57.                 else begin
  58.                         gt_reset_r <= gt_reset_r;
  59.                 end
  60.         end
  61.         else begin
  62.                 gt_reset_r <= 1'b0;
  63.         end
  64. end

  65. //reset
  66. always @(posedge clk) begin
  67.         if (reset_busy == 'd1) begin
  68.                 reset_r <= 1'b1;
  69.         end
  70.         else begin
  71.                 reset_r <= 1'b0;
  72.         end
  73. end
  74. endmodule

发送模块
发送部分就是简单的模拟AXI总线协议进行发送,这里指定了几个参数,方便后期移植修改,同时又例化了一个ILA IP用于检测上板时数据正确性。
  1. `timescale 1ns / 1ps
  2. module Aurora_Tx #(
  3.     parameter            DATA_WIDTH         = 32, // DATA bus width
  4.     parameter            TKEEP_WIDTH        = DATA_WIDTH/8, // TKEEP  width
  5.     parameter                  STREAM_LEN         = 1024 ,
  6.     parameter            REG_MAX_BURST      = 15
  7. )
  8. (
  9.         input        wire                        clk                                 ,       
  10.         input        wire                        rst                                 ,       
  11.         output         wire [0 : DATA_WIDTH-1]         s_axi_tx_tdata ,
  12.         output         wire [0 : TKEEP_WIDTH-1]         s_axi_tx_tkeep ,
  13.         output         wire                         s_axi_tx_tlast                ,
  14.         output         wire                         s_axi_tx_tvalid                ,
  15.         input         wire                         s_axi_tx_tready                       
  16.     );

  17. //reg define
  18. reg         [0:DATA_WIDTH-1]        axi_tx_tdata ;
  19. reg                         axi_tx_tlast                         ;
  20. reg                         axi_tx_tvalid                     ;
  21. reg         [REG_MAX_BURST:0]        cnt_data     ;

  22. //wire define
  23. wire                         cnt_data_tlast                         ;
  24. assign s_axi_tx_tdata     = axi_tx_tdata;
  25. assign s_axi_tx_tkeep     = 4'hF        ;
  26. assign s_axi_tx_tlast     = axi_tx_tlast;
  27. assign s_axi_tx_tvalid    = axi_tx_tvalid;
  28. assign cnt_data_tlast = (s_axi_tx_tready==1) && (axi_tx_tvalid==1) && (cnt_data == STREAM_LEN - 1);
  29. //cnt_data
  30. always @(posedge clk) begin
  31.         if(rst==1)begin
  32.                 cnt_data <= 'd0;
  33.         end
  34.         else if ((s_axi_tx_tready==1) && (axi_tx_tvalid==1)) begin
  35.                 if(cnt_data_tlast==1)
  36.                         cnt_data <= 'd0;
  37.                 else
  38.                         cnt_data <= cnt_data + 1'b1;
  39.         end
  40. end

  41. //axi_tx_tlast
  42. always @(*) begin
  43.         axi_tx_tlast = cnt_data_tlast;
  44. end

  45. //axi_tx_tvalid
  46. always @(posedge clk) begin
  47.         if(rst==1)begin
  48.                 axi_tx_tvalid <= 1'b0;
  49.         end
  50.         else if (cnt_data_tlast == 1'b1) begin
  51.                 axi_tx_tvalid <= 1'b0;
  52.         end
  53.         else if (axi_tx_tvalid == 1'b0 && s_axi_tx_tready == 1'b1) begin
  54.                 axi_tx_tvalid <= 1'b1;
  55.         end
  56. end

  57. //axi_tx_tdata
  58. always @(*) begin
  59.         axi_tx_tdata = cnt_data;
  60. end

  61. wire [63:0]        probe0;
  62. assign probe0 = {
  63.         s_axi_tx_tdata                ,//32
  64.         s_axi_tx_tkeep                ,//4
  65.         s_axi_tx_tlast                ,//1
  66.         s_axi_tx_tvalid                ,//1
  67.         s_axi_tx_tready                ,//1
  68.         cnt_data            //16

  69. };

  70. ila_0 u_tx (
  71.         .clk(clk), // input wire clk
  72.         .probe0(probe0) // input wire [63:0] probe0
  73. );

  74. endmodule

接收模块
接收部分就是简单的模拟AXI总线协议接收数据,这里也指定了几个参数,方便后期移植修改,同时又例化了一个ILA IP用于检测上板时数据正确性。
  1. module Aurora_Rx #(
  2.     parameter            DATA_WIDTH         = 32, // DATA bus width
  3.     parameter            TKEEP_WIDTH        = DATA_WIDTH/8, // TKEEP  width
  4.     parameter                  STREAM_LEN         = 1024 ,
  5.     parameter            REG_MAX_BURST      = 15
  6. )(
  7.         input         wire                        clk                                 ,
  8.         input         wire                        rst                                 ,
  9.         input        wire [0 : DATA_WIDTH-1]         m_axi_rx_tdata                ,
  10.         input        wire [0 : TKEEP_WIDTH-1]         m_axi_rx_tkeep                ,
  11.         input        wire                         m_axi_rx_tlast                ,
  12.         input        wire                         m_axi_rx_tvalid               
  13.     );
  14. //reg define
  15. reg         [REG_MAX_BURST:0]        cnt_burst ;
  16. reg     error_r ;

  17. always @(posedge clk) begin
  18.         if(rst==1)begin
  19.                 cnt_burst <= 'd0;
  20.         end
  21.         else if (m_axi_rx_tvalid == 1) begin
  22.                 if(m_axi_rx_tvalid == 1 &&        cnt_burst == STREAM_LEN - 1)
  23.                         cnt_burst <= 'd0;
  24.                 else
  25.                         cnt_burst <= cnt_burst + 1'b1;
  26.         end
  27. end

  28. //check
  29. always @(posedge clk) begin
  30.         if(rst==1)begin
  31.                 error_r <= 'd0;
  32.         end
  33.         else if (m_axi_rx_tvalid==1 && (m_axi_rx_tdata != cnt_burst)) begin
  34.                 error_r <= 1'b1;
  35.         end
  36. end

  37. wire [63:0]        probe0;
  38. assign probe0 = {
  39.         m_axi_rx_tdata                ,
  40.         m_axi_rx_tkeep                ,
  41.         m_axi_rx_tlast                ,
  42.         m_axi_rx_tvalid                ,
  43.         error_r             ,
  44.         cnt_burst
  45. };
  46. ila_0 u_rx (
  47.         .clk(clk), // input wire clk
  48.         .probe0(probe0) // input wire [63:0] probe0
  49. );
  50. endmodule

顶层连接
根据前面绘制的框图连接上述各个模块,例化了一个VIO IP进行检测和控制复位。
  1. `timescale 1ns / 1ps
  2. module Aurora_Top(
  3.     //clock---------------------------------
  4.     input clk_in,          //系统钟
  5.     input gt_refclk116_p , //差分参考钟
  6.     input gt_refclk116_n , //差分参考钟
  7.     //Serial I/O----------------------------
  8.     input  rxp                 ,
  9.         input  rxn                 ,
  10.         output txp                 ,
  11.         output txn                 ,
  12.     //--------------------------------------
  13.     output         tx_dis  ,
  14.     output  led_link_up
  15.     );

  16.     //==========================================
  17.     //wire define
  18.     wire start;
  19.      //------------------------------SEND--------------------------------------------
  20.     // AXI TX Interface
  21.     wire [0 : 31] s_axi_tx_tdata  ;
  22.     wire [0 : 3]  s_axi_tx_tkeep  ;
  23.     wire s_axi_tx_tlast  ;
  24.     wire s_axi_tx_tvalid ;
  25.     wire s_axi_tx_tready ;
  26.     //------------------------------RECEIVE-----------------------------------------
  27.     // AXI RX Interface
  28.     wire [0 : 31] m_axi_rx_tdata  ;
  29.     wire [0 : 3]  m_axi_rx_tkeep  ;
  30.     wire m_axi_rx_tlast  ;
  31.     wire m_axi_rx_tvalid ;
  32.     //------------------------------SYSTEM------------------------------------------
  33.     // reset IO,test
  34.     wire reset;
  35.     wire gt_reset;
  36.     wire [2 : 0] loopback;
  37.     //------------------------------clock-------------------------------------------
  38.     // GT Reference Clock Interface
  39.     wire gt_refclk1_p;                       
  40.     wire gt_refclk1_n;                       
  41.     wire init_clk_in ;         
  42.     wire user_clk_out;
  43.     wire sync_clk_out;                       
  44.     wire gt_refclk1_out;                              
  45.     //--------------------------------drp-------------------------------------------
  46.     //drp Interface
  47.     wire drpclk_in ;  
  48.     //-----------------------------Status Detection--------------------------------
  49.     // Error Detection Interface                       
  50.     wire hard_err ;
  51.     wire soft_err ;
  52.     wire frame_err;
  53.     // Status link
  54.     wire channel_up;
  55.     wire lane_up;
  56.     wire sys_reset_out;
  57.     //==========================================
  58.     //wire assign
  59.     assign tx_dis = 0;
  60.     assign gt_refclk116_p =gt_refclk1_p;
  61.     assign gt_refclk116_n =gt_refclk1_n;
  62.     assign led_link_up = channel_up & lane_up;
  63.     assign init_clk_in = clk_in;
  64.     assign drpclk_in = clk_in;

  65.     wire sys_rst = ~(channel_up & lane_up & (~sys_reset_out));
  66.    
  67.     rst_ctrl u_rst_ctrl(
  68.         .clk              ( init_clk_in   ),
  69.         .start_en         (     start     ),  
  70.         .reset            ( reset         ),
  71.         .gt_reset         ( gt_reset      )
  72.     );

  73.     Aurora_Tx u_Aurora_Tx(
  74.         .clk              ( user_clk_out     ),
  75.         .rst              (     start        ),
  76.         .s_axi_tx_tdata   ( s_axi_tx_tdata   ),
  77.         .s_axi_tx_tkeep   ( s_axi_tx_tkeep   ),
  78.         .s_axi_tx_tlast   ( s_axi_tx_tlast   ),
  79.         .s_axi_tx_tvalid  ( s_axi_tx_tvalid  ),
  80.         .s_axi_tx_tready  ( s_axi_tx_tready  )
  81.     );

  82.     Aurora_Rx u_Aurora_Rx(
  83.         .clk              ( user_clk_out     ),
  84.         .rst              (       start      ),
  85.         .m_axi_rx_tdata   ( m_axi_rx_tdata   ),
  86.         .m_axi_rx_tkeep   ( m_axi_rx_tkeep   ),
  87.         .m_axi_rx_tlast   ( m_axi_rx_tlast   ),
  88.         .m_axi_rx_tvalid  ( m_axi_rx_tvalid  )
  89.     );

  90.     aurora_8b10b_0 u_aurora(
  91.         //------------------------------SEND--------------------------------------------
  92.         // AXI TX Interface
  93.         .s_axi_tx_tdata (s_axi_tx_tdata ),                    // input wire [0 : 31] s_axi_tx_tdata
  94.         .s_axi_tx_tkeep (s_axi_tx_tkeep ),                    // input wire [0 : 3] s_axi_tx_tkeep
  95.         .s_axi_tx_tlast (s_axi_tx_tlast ),                    // input wire s_axi_tx_tlast
  96.         .s_axi_tx_tvalid(s_axi_tx_tvalid),                  // input wire s_axi_tx_tvalid
  97.         .s_axi_tx_tready(s_axi_tx_tready),                  // output wire s_axi_tx_tready
  98.         //------------------------------RECEIVE-----------------------------------------
  99.         // AXI RX Interface
  100.         .m_axi_rx_tdata (m_axi_rx_tdata ),                    // output wire [0 : 31] m_axi_rx_tdata
  101.         .m_axi_rx_tkeep (m_axi_rx_tkeep ),                    // output wire [0 : 3] m_axi_rx_tkeep
  102.         .m_axi_rx_tlast (m_axi_rx_tlast ),                    // output wire m_axi_rx_tlast
  103.         .m_axi_rx_tvalid(m_axi_rx_tvalid),                  // output wire m_axi_rx_tvalid  
  104.         //------------------------------SYSTEM------------------------------------------
  105.         // reset IO,test
  106.         .reset(reset),                                      // input wire reset
  107.         .gt_reset(gt_reset),                                // input wire gt_reset
  108.         .loopback(loopback),                                // input wire [2 : 0] loopback
  109.         //--------------------------------Serial I/O------------------------------------
  110.         .txp(txp),                                          // output wire [0 : 0] txp
  111.         .txn(txn),                                          // output wire [0 : 0] txn
  112.         .rxp(rxp),                                          // input wire [0 : 0] rxp
  113.         .rxn(rxn),                                          // input wire [0 : 0] rxn
  114.         //------------------------------clock-------------------------------------------
  115.         // GT Reference Clock Interface
  116.         .gt_refclk1_p(gt_refclk1_p),                        // input wire gt_refclk1_p
  117.         .gt_refclk1_n(gt_refclk1_n),                        // input wire gt_refclk1_n
  118.         .init_clk_in(init_clk_in),                          // input wire init_clk_in
  119.         //--------------------------------drp-------------------------------------------
  120.         //drp Interface
  121.         .drpclk_in(drpclk_in),                              // input wire drpclk_in
  122.         .drpaddr_in(0),                            // input wire [8 : 0] drpaddr_in
  123.         .drpen_in(0),                                // input wire drpen_in
  124.         .drpdi_in(0),                                // input wire [15 : 0] drpdi_in
  125.         .drprdy_out(),                            // output wire drprdy_out
  126.         .drpdo_out(),                              // output wire [15 : 0] drpdo_out
  127.         .drpwe_in(0),                                // input wire drpwe_in  
  128.         //-----------------------------Status Detection--------------------------------
  129.         // Error Detection Interface
  130.         .hard_err (hard_err ),                                // output wire hard_err
  131.         .soft_err (soft_err ),                                // output wire soft_err
  132.         .frame_err(frame_err),                              // output wire frame_err
  133.         // Status
  134.         .power_down(0),                            // input wire power_down
  135.         .channel_up(channel_up),                            // output wire channel_up
  136.         .lane_up(lane_up),                                  // output wire [0 : 0] lane_up
  137.         //-----------------------------------------------------------------------------
  138.         //-----------------------------------------------------------------------------
  139.         .tx_lock(tx_lock),                                  // output wire tx_lock
  140.         .tx_resetdone_out(tx_resetdone_out),                // output wire tx_resetdone_out
  141.         .rx_resetdone_out(rx_resetdone_out),                // output wire rx_resetdone_out
  142.         .pll_not_locked_out(pll_not_locked_out),            // output wire pll_not_locked_out
  143.         //reset_out
  144.         .gt_reset_out(gt_reset_out),                        // output wire gt_reset_out
  145.         .link_reset_out(link_reset_out),                    // output wire link_reset_out
  146.         .sys_reset_out(sys_reset_out),                      // output wire sys_reset_out
  147.         //clk_out
  148.         .user_clk_out(user_clk_out),                        // output wire user_clk_out
  149.         .sync_clk_out(),                        // output wire sync_clk_out
  150.         .gt_refclk1_out(),                    // output wire gt_refclk1_out
  151.         //qplllock_out
  152.         .gt0_qplllock_out(),                // output wire gt0_qplllock_out
  153.         .gt0_qpllrefclklost_out(),    // output wire gt0_qpllrefclklost_out
  154.         .gt_qpllclk_quad2_out(),        // output wire gt_qpllclk_quad2_out
  155.         .gt_qpllrefclk_quad2_out()   // output wire gt_qpllrefclk_quad2_out
  156.     );
  157.    
  158.     vio_0 Status_dect (
  159.         .clk(user_clk_out),                // input wire clk
  160.         .probe_in0(hard_err),    // input wire [0 : 0] probe_in0
  161.         .probe_in1(soft_err),    // input wire [0 : 0] probe_in1
  162.         .probe_in2(frame_err),    // input wire [0 : 0] probe_in2
  163.         .probe_in3(channel_up),    // input wire [0 : 0] probe_in3
  164.         .probe_in4(lane_up),    // input wire [0 : 0] probe_in4
  165.         .probe_out0(loopback),  // output wire [2 : 0] probe_out0
  166.         .probe_out1(start)  // output wire [0 : 0] probe_out1
  167.     );
  168. endmodule
下板测试
设置loopback的默认值为0,或者不为0的先设置为0,然后设置为0 ,然后设置模式为近端回环测试,1或2都可。则可以看到channel_up和lane_up都拉高,连接建立。start信号拉高复位,然后置零可去发送接收的窗口观察信号收发是否正确。

发送部分的ILA窗口抓取到数据正常发送,同时满足AXI的协议。

接收部分的ILA窗口抓取到数据正常接收,同时满足AXI的协议,error指示信号常为低,证明数据传输正常,链路稳定。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

6

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部