前言

本文首先介绍了根据网上博文简单介绍了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种情况:

  1. 有5个0和5个1
  2. 有6个0和4个1
  3. 有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根据手册中推荐的复位时序进行复位。在该文中有详细介绍,Aurora8B10B IP使用 -02- IP功能设计技巧。

`timescale 1ns / 1ps
module rst_ctrl(input   wire            clk                 ,input  wire            start_en            ,output     wire            reset               ,// 系统复位output  wire            gt_reset             // 收发器复位);//parameter define
parameter GT_RESET_START = 128  ;
parameter GT_RESET_END = 384 ;
parameter RESET_MAX = GT_RESET_END + GT_RESET_START;//reg define
reg             reset_r          ;
reg             gt_reset_r       ;
reg             reset_busy     =0;//复位忙指示信号
reg     [1:0]   start_flag_dly =0;//复位使能信号延时
reg     [10:0]  cnt_rst        =0;//用于产生复位信号的计数器//wire define
assign    reset = reset_r   ;
assign gt_reset = gt_reset_r;//起始信号边沿
wire link_up_n = !start_flag_dly[1]&&start_flag_dly[0];
//start_flag_dly
always @(posedge clk) beginstart_flag_dly <= {start_flag_dly[0], start_en};
end//复位忙指示信号
always @(posedge clk) beginif(link_up_n==1) beginreset_busy <= 1;endelse if(cnt_rst== RESET_MAX - 1)beginreset_busy <= 0;end
end//复位计数器
always @(posedge clk) beginif (reset_busy == 'd1) beginif(reset_busy == 'd1 && (cnt_rst == RESET_MAX - 1))cnt_rst <= 'd0;elsecnt_rst <= cnt_rst + 1'b1;endelse begincnt_rst <= 'd0;end
end//gt_reset
always @(posedge clk) beginif (reset_busy == 'd1) beginif(cnt_rst == GT_RESET_START - 1) begingt_reset_r <= 1'b1;endelse if (cnt_rst == GT_RESET_END - 1|| cnt_rst == 0 ) begingt_reset_r <= 1'b0;endelse begingt_reset_r <= gt_reset_r;endendelse begingt_reset_r <= 1'b0;end
end//reset
always @(posedge clk) beginif (reset_busy == 'd1) beginreset_r <= 1'b1;endelse beginreset_r <= 1'b0;end
end
endmodule

发送模块

发送部分就是简单的模拟AXI总线协议进行发送,这里指定了几个参数,方便后期移植修改,同时又例化了一个ILA IP用于检测上板时数据正确性。

`timescale 1ns / 1ps
module Aurora_Tx #(parameter            DATA_WIDTH         = 32, // DATA bus widthparameter            TKEEP_WIDTH        = DATA_WIDTH/8, // TKEEP  widthparameter             STREAM_LEN         = 1024 ,parameter            REG_MAX_BURST      = 15
)
(input  wire            clk                 ,   input   wire            rst                 ,   output  wire [0 : DATA_WIDTH-1]     s_axi_tx_tdata ,output  wire [0 : TKEEP_WIDTH-1]    s_axi_tx_tkeep ,output  wire            s_axi_tx_tlast      ,output     wire            s_axi_tx_tvalid     ,input  wire            s_axi_tx_tready         );//reg define
reg     [0:DATA_WIDTH-1]    axi_tx_tdata ;
reg             axi_tx_tlast             ;
reg             axi_tx_tvalid            ;
reg     [REG_MAX_BURST:0]   cnt_data     ;//wire define
wire            cnt_data_tlast          ;
assign s_axi_tx_tdata     = axi_tx_tdata;
assign s_axi_tx_tkeep     = 4'hF        ;
assign s_axi_tx_tlast     = axi_tx_tlast;
assign s_axi_tx_tvalid    = axi_tx_tvalid;
assign cnt_data_tlast = (s_axi_tx_tready==1) && (axi_tx_tvalid==1) && (cnt_data == STREAM_LEN - 1);
//cnt_data
always @(posedge clk) beginif(rst==1)begincnt_data <= 'd0;endelse if ((s_axi_tx_tready==1) && (axi_tx_tvalid==1)) beginif(cnt_data_tlast==1)cnt_data <= 'd0;elsecnt_data <= cnt_data + 1'b1;end
end//axi_tx_tlast
always @(*) beginaxi_tx_tlast = cnt_data_tlast;
end//axi_tx_tvalid
always @(posedge clk) beginif(rst==1)beginaxi_tx_tvalid <= 1'b0;endelse if (cnt_data_tlast == 1'b1) beginaxi_tx_tvalid <= 1'b0;endelse if (axi_tx_tvalid == 1'b0 && s_axi_tx_tready == 1'b1) beginaxi_tx_tvalid <= 1'b1;end
end//axi_tx_tdata
always @(*) beginaxi_tx_tdata = cnt_data;
endwire [63:0]  probe0;
assign probe0 = {s_axi_tx_tdata        ,//32s_axi_tx_tkeep     ,//4s_axi_tx_tlast      ,//1s_axi_tx_tvalid     ,//1s_axi_tx_tready     ,//1cnt_data            //16};ila_0 u_tx (.clk(clk), // input wire clk.probe0(probe0) // input wire [63:0] probe0
);endmodule

接收模块

接收部分就是简单的模拟AXI总线协议接收数据,这里也指定了几个参数,方便后期移植修改,同时又例化了一个ILA IP用于检测上板时数据正确性。

module Aurora_Rx #(parameter            DATA_WIDTH         = 32, // DATA bus widthparameter            TKEEP_WIDTH        = DATA_WIDTH/8, // TKEEP  widthparameter              STREAM_LEN         = 1024 ,parameter            REG_MAX_BURST      = 15
)(input     wire            clk                 ,input  wire            rst                 ,input  wire [0 : DATA_WIDTH-1]     m_axi_rx_tdata      ,input  wire [0 : TKEEP_WIDTH-1]    m_axi_rx_tkeep      ,input  wire            m_axi_rx_tlast      ,input  wire            m_axi_rx_tvalid     );
//reg define
reg     [REG_MAX_BURST:0]   cnt_burst ;
reg     error_r ;always @(posedge clk) beginif(rst==1)begincnt_burst <= 'd0;endelse if (m_axi_rx_tvalid == 1) beginif(m_axi_rx_tvalid == 1 &&   cnt_burst == STREAM_LEN - 1)cnt_burst <= 'd0;elsecnt_burst <= cnt_burst + 1'b1;end
end//check
always @(posedge clk) beginif(rst==1)beginerror_r <= 'd0;endelse if (m_axi_rx_tvalid==1 && (m_axi_rx_tdata != cnt_burst)) beginerror_r <= 1'b1;end
endwire [63:0]  probe0;
assign probe0 = {m_axi_rx_tdata        ,m_axi_rx_tkeep     ,m_axi_rx_tlast     ,m_axi_rx_tvalid        ,error_r             ,cnt_burst
};
ila_0 u_rx (.clk(clk), // input wire clk.probe0(probe0) // input wire [63:0] probe0
);
endmodule

顶层连接

根据前面绘制的框图连接上述各个模块,例化了一个VIO IP进行检测和控制复位。

`timescale 1ns / 1ps
module Aurora_Top(//clock---------------------------------input clk_in,          //系统钟input gt_refclk116_p , //差分参考钟input gt_refclk116_n , //差分参考钟//Serial I/O----------------------------input  rxp        ,input  rxn         ,output txp         ,output txn         ,//--------------------------------------output     tx_dis  ,output  led_link_up );//==========================================//wire definewire start;//------------------------------SEND--------------------------------------------// AXI TX Interfacewire [0 : 31] s_axi_tx_tdata  ;wire [0 : 3]  s_axi_tx_tkeep  ;wire s_axi_tx_tlast  ;wire s_axi_tx_tvalid ;wire s_axi_tx_tready ;//------------------------------RECEIVE-----------------------------------------// AXI RX Interfacewire [0 : 31] m_axi_rx_tdata  ;wire [0 : 3]  m_axi_rx_tkeep  ;wire m_axi_rx_tlast  ;wire m_axi_rx_tvalid ;//------------------------------SYSTEM------------------------------------------// reset IO,testwire reset;wire gt_reset;wire [2 : 0] loopback;//------------------------------clock-------------------------------------------// GT Reference Clock Interfacewire gt_refclk1_p;                       wire gt_refclk1_n;                       wire init_clk_in ;         wire user_clk_out;wire sync_clk_out;                       wire gt_refclk1_out;                               //--------------------------------drp-------------------------------------------//drp Interfacewire drpclk_in ;  //-----------------------------Status Detection--------------------------------// Error Detection Interface                       wire hard_err ;wire soft_err ;wire frame_err;// Status link wire channel_up;wire lane_up;wire sys_reset_out;//==========================================//wire assignassign tx_dis = 0;assign gt_refclk116_p =gt_refclk1_p;assign gt_refclk116_n =gt_refclk1_n;assign led_link_up = channel_up & lane_up;assign init_clk_in = clk_in;assign drpclk_in = clk_in; wire sys_rst = ~(channel_up & lane_up & (~sys_reset_out));rst_ctrl u_rst_ctrl(.clk              ( init_clk_in   ),.start_en         (     start     ),  .reset            ( reset         ),.gt_reset         ( gt_reset      ));Aurora_Tx u_Aurora_Tx(.clk              ( user_clk_out     ),.rst              (     start        ),.s_axi_tx_tdata   ( s_axi_tx_tdata   ),.s_axi_tx_tkeep   ( s_axi_tx_tkeep   ),.s_axi_tx_tlast   ( s_axi_tx_tlast   ),.s_axi_tx_tvalid  ( s_axi_tx_tvalid  ),.s_axi_tx_tready  ( s_axi_tx_tready  ));Aurora_Rx u_Aurora_Rx(.clk              ( user_clk_out     ),.rst              (       start      ),.m_axi_rx_tdata   ( m_axi_rx_tdata   ),.m_axi_rx_tkeep   ( m_axi_rx_tkeep   ),.m_axi_rx_tlast   ( m_axi_rx_tlast   ),.m_axi_rx_tvalid  ( m_axi_rx_tvalid  ));aurora_8b10b_0 u_aurora(//------------------------------SEND--------------------------------------------// AXI TX Interface.s_axi_tx_tdata (s_axi_tx_tdata ),                    // input wire [0 : 31] s_axi_tx_tdata.s_axi_tx_tkeep (s_axi_tx_tkeep ),                    // input wire [0 : 3] s_axi_tx_tkeep.s_axi_tx_tlast (s_axi_tx_tlast ),                    // input wire s_axi_tx_tlast.s_axi_tx_tvalid(s_axi_tx_tvalid),                  // input wire s_axi_tx_tvalid.s_axi_tx_tready(s_axi_tx_tready),                  // output wire s_axi_tx_tready//------------------------------RECEIVE-----------------------------------------// AXI RX Interface.m_axi_rx_tdata (m_axi_rx_tdata ),                    // output wire [0 : 31] m_axi_rx_tdata.m_axi_rx_tkeep (m_axi_rx_tkeep ),                    // output wire [0 : 3] m_axi_rx_tkeep.m_axi_rx_tlast (m_axi_rx_tlast ),                    // output wire m_axi_rx_tlast.m_axi_rx_tvalid(m_axi_rx_tvalid),                  // output wire m_axi_rx_tvalid  //------------------------------SYSTEM------------------------------------------// reset IO,test.reset(reset),                                      // input wire reset.gt_reset(gt_reset),                                // input wire gt_reset.loopback(loopback),                                // input wire [2 : 0] loopback//--------------------------------Serial I/O------------------------------------.txp(txp),                                          // output wire [0 : 0] txp.txn(txn),                                          // output wire [0 : 0] txn.rxp(rxp),                                          // input wire [0 : 0] rxp.rxn(rxn),                                          // input wire [0 : 0] rxn//------------------------------clock-------------------------------------------// GT Reference Clock Interface.gt_refclk1_p(gt_refclk1_p),                        // input wire gt_refclk1_p.gt_refclk1_n(gt_refclk1_n),                        // input wire gt_refclk1_n.init_clk_in(init_clk_in),                          // input wire init_clk_in//--------------------------------drp-------------------------------------------//drp Interface.drpclk_in(drpclk_in),                              // input wire drpclk_in.drpaddr_in(0),                            // input wire [8 : 0] drpaddr_in.drpen_in(0),                                // input wire drpen_in.drpdi_in(0),                                // input wire [15 : 0] drpdi_in.drprdy_out(),                            // output wire drprdy_out.drpdo_out(),                              // output wire [15 : 0] drpdo_out.drpwe_in(0),                                // input wire drpwe_in  //-----------------------------Status Detection--------------------------------// Error Detection Interface.hard_err (hard_err ),                                // output wire hard_err.soft_err (soft_err ),                                // output wire soft_err.frame_err(frame_err),                              // output wire frame_err// Status .power_down(0),                            // input wire power_down.channel_up(channel_up),                            // output wire channel_up.lane_up(lane_up),                                  // output wire [0 : 0] lane_up//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------.tx_lock(tx_lock),                                  // output wire tx_lock.tx_resetdone_out(tx_resetdone_out),                // output wire tx_resetdone_out.rx_resetdone_out(rx_resetdone_out),                // output wire rx_resetdone_out.pll_not_locked_out(pll_not_locked_out),            // output wire pll_not_locked_out//reset_out.gt_reset_out(gt_reset_out),                        // output wire gt_reset_out.link_reset_out(link_reset_out),                    // output wire link_reset_out.sys_reset_out(sys_reset_out),                      // output wire sys_reset_out//clk_out.user_clk_out(user_clk_out),                        // output wire user_clk_out.sync_clk_out(),                        // output wire sync_clk_out.gt_refclk1_out(),                    // output wire gt_refclk1_out//qplllock_out.gt0_qplllock_out(),                // output wire gt0_qplllock_out.gt0_qpllrefclklost_out(),    // output wire gt0_qpllrefclklost_out.gt_qpllclk_quad2_out(),        // output wire gt_qpllclk_quad2_out.gt_qpllrefclk_quad2_out()   // output wire gt_qpllrefclk_quad2_out);vio_0 Status_dect (.clk(user_clk_out),                // input wire clk.probe_in0(hard_err),    // input wire [0 : 0] probe_in0.probe_in1(soft_err),    // input wire [0 : 0] probe_in1.probe_in2(frame_err),    // input wire [0 : 0] probe_in2.probe_in3(channel_up),    // input wire [0 : 0] probe_in3.probe_in4(lane_up),    // input wire [0 : 0] probe_in4.probe_out0(loopback),  // output wire [2 : 0] probe_out0.probe_out1(start)  // output wire [0 : 0] probe_out1);
endmodule

下板测试

设置loopback的默认值为0,或者不为0的先设置为0,然后设置为0 ,然后设置模式为近端回环测试,1或2都可。则可以看到channel_up和lane_up都拉高,连接建立。start信号拉高复位,然后置零可去发送接收的窗口观察信号收发是否正确。

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

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

reference

  1. PG046
  2. Aurora例程
  3. 8B/10B编码基本原理
  4. 8B/10B编码
  5. 8B/10B百度百科

Aurora8B10B IP使用 -05- 收发测试应用示例相关推荐

  1. Xilinx FPGA平台GTX简易使用教程(五)GTX收发测试及示例工程介绍

    GTX IP配置完了,你不得搞个回环测试一番? 汇总篇: Xilinx FPGA平台GTX简易使用教程(汇总篇) 目录 前言 一.示例工程Example Design 1.1 gtx_support模 ...

  2. Aurora8B10B IP使用 -04- IP例程应用实例

    前言 本文主要介绍了关于Aurora8B10B IP官方提供的模板工程的使用,并进行了简要的仿真查看测试结果,确保仿真传输的正确性. 示例设计架构 示例设计 每个 Aurora 8B/10B 内核都包 ...

  3. pybullet机器人仿真环境搭建 1.安装pybullet,测试官方示例,基础环境搭建

    pybullet机器人仿真环境搭建 1.安装pybullet 前言 安装 测试官方示例 基础环境搭建 导入pybullet 创建服务端 (可选)配置图形GUI 添加资源路径 设置重力 加载模型 迭代运 ...

  4. Jmeter实现1秒100次并发测试的示例

    1秒100次并发测试的示例----jmeter实现 一.打开JMeter 打开后的界面如下: 二.右击"测试计划",添加线程组 三.设置线程组的线程数 JMeter中的线程组,类似 ...

  5. java转换ip地址格式转换_Java编程IP地址和数字相互转换代码示例

    最近才知道,将ip地址转换成十进制.八进制.十六进制同样可以访问网站. IP转为数字(第二种算法.用左移.按位或实现.效率更高.): public long ipToLong(String ipAdd ...

  6. SQL Server AlwaysOn 集群 关于主Server IP与Listener IP调换的详细测试

    1. 背景 SQL Server 搭建AlwaysOn后,我们就希望程序连接时使用虚拟的侦听IP(Listener IP),而不再是主Server 的IP.如果我们有采用中间件,则可以在配置中,直接用 ...

  7. python流量实时统计_Python实现获取nginx服务器ip及流量统计信息功能示例

    本文实例讲述了Python实现获取nginx服务器ip及流量统计信息功能.分享给大家供大家参考,具体如下: #!/usr/bin/python #coding=utf8 log_file = &quo ...

  8. JUnit5 测试套件示例

    使用 JUnit5 测试套件,您可以运行分散到多个测试类和不同包中的测试. JUnit5 提供了两个注解:@SelectPackages和@SelectClasses以创建测试套件. 此外,您可以使用 ...

  9. Linux ping 测试IP地址与 telnet 测试IP端口

    文章目录 一.ping命令使用 二.telnet 端口使用 转载文章 一.ping命令使用 原文地址:https://www.cnblogs.com/FengZeng666/p/15093267.ht ...

最新文章

  1. 设计前沿:16款扁平风格 iOS 7 图标设计
  2. 1 数列分块入门_线性代数入门——利用分块矩阵简化矩阵乘法运算
  3. 测试开发面试技巧_面试技巧将给您带来信心并帮助您获得开发工作
  4. IIS6.0下ASP的新增功能
  5. 【iCore4 双核心板_uC/OS-II】例程十:信号量集
  6. oracle 访问adf 慢,ORACLE ADF 问题总结
  7. 动态规划实战14 leetcode-312. Burst Balloons
  8. Brooklyn 最新版 |创意多用途响应式 WordPress 主题下载
  9. Unity 讯飞实时语音转写(一)—— 使用WebSocket连接讯飞语音服务器
  10. 基于sklearn的文本特征提取与分类
  11. Redmine使用介绍
  12. 推荐系统(十九)Gate网络(二):百度GemNN(Gating-Enhanced Multi-Task Neural Networks)
  13. 苹果官方mfi认证名单_苹果入驻抖音,完成官方认证
  14. python实现mysql多条件查询筛选功能
  15. 使用单视点模型进行水下标定的分析
  16. PMBOK第六版10大知识领域ITTO思维导图-干货!
  17. Ubuntu安装nvidia显卡驱动和CUDA CUDNN autoinstall
  18. 我们怎样处理垃圾网站举报?
  19. 骑缝章 Java_Java实现在PDF中添加骑缝章
  20. 低温高温环境试验机构

热门文章

  1. LVS均衡负载(一) LVS详解
  2. 后端开发——Java
  3. 入职 3 天“窃取”上万个代码文件,特斯拉起诉前软件工程师!
  4. dmp格式怎么转换_如何生成转储(dmp)文件--工具篇
  5. 计算机组成原理实验一:全加器实验
  6. 安卓各大平台APP上架的一些总结
  7. 算法思想之递归分治回溯
  8. Ubuntu开发环境_TLP电源管理模块、禁用笔记本触摸板
  9. 使用Navicat导入execl到mysql数据库中日期值显示0000-00-00的问题解决
  10. HTML页面为什么设置了UTF-8仍然中文乱码