64b_66b_xcku60_GTH学习记录

 0,引言

最近在学习GTH,尝试在GHT外部套用一个phy层实现64b/66b,从官方例程开始学起:

参考资料:ug576-ultrascale-gth-transceivers (详细阅读)

                   pg182-gtwizard-ultrascale            (根据example例程去找对应端口连接的通道,去ug576找详细解释)
以太网扫盲——64b/66b编码icon-default.png?t=O83Ahttps://blog.chinaaet.com/justlxy/p/5100064750

例如:tx_sequence_in(外部序列计数器)

在pg182中:

 可以看到与TXSEQUENCE端口连接,去ug576寻找如下:

ug576提供对应端口的详细描述与例子,可以帮助学习。

开发平台:vivado2020.2

开发板卡:axck060(黑金板卡)

FPGA芯片:xcku060ffva_1156_2_i 

1.GTH IP核的创建

ip核的具体配置参考pg182-c4:design flow steps (从第81页开始,详细介绍了IP配置信息。)

以下为我自己要用的配置。

一、Basic

 System:

  1. 传输配置:白身配置,自己编写;
  2. 只有GTH;

Transmitter:

1,Line_Rate:线速率:12.5Gb/s。因为FPGA板卡链接的参考时钟为156.25Mhz,线速率与参考时钟一般为倍数关系

156.25\times 80=12500=12.5Gb/s

2,PLL_type:GTH的一个quad包含两个qpll(qpll0,qpll1),以及四个cpll。

在ug576-p49可以看到两个qpll支持的频率范围:

cpll速率支持如下:(ug576-p45)

因为我们的线速率为12.5Gb/s,选择使用qpll0(qpll1也可以)

3,Actual Reference:根据自身板卡,我是156.25Mhz

4,Encoding:编码方式,实际上编码还是用GTH做,

我是实现64B/66B,有4种组合,根据Sync,Async,以及CAUI来区分。选择Sync:gearbox for 64B/66B。

Sync,Async的区别是sync要求在序列计数器32时暂停发送数据,而async允许每个txusrclk2周期连续应用数据。

因为gearbox64b/66b变速箱的输入带宽为66b(多了两个bit做数据包和控制包区分),输出带宽为64b,每次会少发两个bit,经过32个周期,会累积少发64个,刚好是一整个数据,这时外部序列计数器会使得外部发送数据暂停一个周期,将前面累积的64bit数据发送出去,这样不会造成数据丢失,且gearbox两端的整体带宽匹配。但会使得外部发送模块有周期性暂停。具体gearbox64b/66b参考ug576-C3:TC synchronous Gearbox:

 5,User data width:64

 6,internal data width :32

 user data width 与internal data width的关系会导致 userclk与userclk2的倍数关系改变,具体查看手册。

 7,Buffer:使能,如果不使能,需要自己编写相位同步电路(我一直使用buffer。buffer与相位对齐电路的主要区别:数据的latency!buffer的latency大,相位对齐电路的latency小。如果工程对延迟敏感,使用相位对齐电路)。

8,TXOUTCLK source:使用CLKPMA(个人习惯,这个没什么具体的区别,若要详细划分可以参考 ug576-p155,rx有对应的RX Fabric Clock)

 

9,后面的Advance模块,基本不用动 。

二、Physical Resources

物理配置,虽然这里可以配置,但是最后XDC中的物理物理约束具有最高优先级。这里可以随便点一点。DRP_CLK随便用一个时钟(基本不咋用),在范围内就行(这个范围测试过前面的配置会影响,根据自己的情况自行选择时钟)

三,Optional Features 

 这里是一些选项:

 1,receiver comma detection and alignment(接收端逗号检测与对齐)

该模块负责逗号检测与逗号对齐。因为我们本次编写的为64b/66b,是通过hear来区分数据与控制信号的。并不需要逗号。comma一般用于8b/10b中,所以这里是灰色。

2,received channel bonding

接受通道对齐,一般是在多通道GT中使用。

3,received clock correction

接受段时钟校正。

 在数据中每隔一段固定时间插入一个K码或者D码。在8b/10b开发中会使用。64b/66b中为灰色。因为使用gearbox。

4,buffer control

buffer控制,没用过

5,advanced clocking

qpll之类相关的,没用过

6,SATA

sata开发中使用。

四,structural options

1, helper_block

上半部分是控制生成example_prj时是否将COMMON_CLK,usesr_clocking,reset_controller等share_module放出来,这会改变ip的一些接口。推荐放在外面,可以更好的帮助我们学习控制这个IP。同时也可以更加快速的去搭建一个Quard中1-4个channel_module(因为common_clk被引出来了)。

 2,interface(接口模块)

        根据自身需求去选择对应接口是否开启。(xilinx非常贴心的在这个界面中,将相关的port在手册中的那一个部分进行了标注,根据自己所需去学习对应模块)

 一般常用的: 接受,发送的极性控制,发送端的摆幅,预加重,后加重。一般来说就是在测试眼图中的参数。如下图

 以上,ip配置完毕。

2.example_prj学习

生成例子如下:

 主要包含userclk模块,reset模块,去历程中跑仿真,链接对应端口。大概耗费了三天,最总搭建了gth_channel。主要是复位,common_clk之间的相互连接。

module gt_channel_64b66b
(
    input                               i_sys_clk                  ,
    input                               i_sys_rst                  ,
    input                               i_gtref_clk                ,

    input                               i_rx_rst                   ,
    input                               i_tx_rst                   ,

    output                              o_tx_done                  ,
    output                              o_rx_done                  ,

    input              [   2:0]         i_gt_loopback              ,

    input              [   3:0]         i_txdiffctrl_in            ,//摆幅
    input              [   0:0]         i_txpolarity_in            ,//极性
    input              [   4:0]         i_txpostcursor_in          ,//后加重
    input              [   4:0]         i_txprecursor_in           ,//预加重

    input              [   0:0]         i_rxpolarity_in            ,//极性

    //DRP接口
    input  wire        [   8:0]         i_drpaddr_in               ,
    input  wire        [   0:0]         i_drpclk_in                ,
    input  wire        [  15:0]         i_drpdi_in                 ,
    input  wire        [   0:0]         i_drpen_in                 ,
    input  wire        [   0:0]         i_drpwe_in                 ,
    output wire        [  15:0]         o_drpdo_out                ,
    output wire        [   0:0]         o_drprdy_out               ,

    //qpll 外部公用common模块传入
    input                               i_rx_qpll_lock             ,
    input                               i_tx_qpll_lock             ,

    input                               qpll0clk_in                ,
    input                               qpll0refclk_in             ,
    input                               qpll1clk_in                ,
    input                               qpll1refclk_in             ,

    output                              o_rx_clk                   ,
    output             [  63:0]         o_rx_data                  ,
    output                              o_rx_data_valid            ,
    output             [   1:0]         o_rx_header                ,
    output                              o_rx_header_valid          ,
    input                               i_rxgearboxslip            ,//手动对齐

    output                              o_tx_clk                   ,
    input              [  63:0]         i_tx_data                  ,
    input              [   1:0]         i_tx_header                ,
    input              [   6:0]         i_tx_seq                   ,//外部序列计数器


    input                               i_rx_gt_p                  ,
    input                               i_rx_gt_n                  ,
    output                              o_tx_gt_p                  ,
    output                              o_tx_gt_n                   
);

 这样构建channel的好处就是之后再构建一个gt_module模块,根据quad的原则,一个module模块最多可以例化四个channel,从而实现了快速开发,比如我就建立两通道进行回环测试。


module gt_module_64b_66b
(
    input                               i_sys_clk                  ,
    input                               i_sys_rst                  ,

    input                               i_mgtref_clk_p             ,
    input                               i_mgtref_clk_n             ,

//channel_0
    input                               i_c0_rx_rst                ,
    input                               i_c0_tx_rst                ,
    output                              o_c0_tx_done               ,
    output                              o_c0_rx_done               ,
    input              [   2:0]         i_c0_gt_loopback           ,
    input              [   3:0]         i_c0_txdiffctrl_in         ,
    input              [   0:0]         i_c0_txpolarity_in         ,
    input              [   4:0]         i_c0_txpostcursor_in       ,
    input              [   4:0]         i_c0_txprecursor_in        ,
    input              [   0:0]         i_c0_rxpolarity_in         ,

    input  wire        [   8:0]         i_c0_drpaddr_in            ,
    input  wire        [   0:0]         i_c0_drpclk_in             ,
    input  wire        [  15:0]         i_c0_drpdi_in              ,
    input  wire        [   0:0]         i_c0_drpen_in              ,
    input  wire        [   0:0]         i_c0_drpwe_in              ,
    output wire        [  15:0]         o_c0_drpdo_out             ,
    output wire        [   0:0]         o_c0_drprdy_out            ,

    output                              o_c0_rx_clk                ,
    output             [  63:0]         o_c0_rx_data               ,
    output                              o_c0_rx_data_valid         ,    
    output             [   1:0]         o_c0_rx_header             ,
    output                              o_c0_rx_header_valid       ,
    input                               i_c0_rxgearboxslip         ,//手动对齐
    output                              o_c0_tx_clk                ,
    input              [  63:0]         i_c0_tx_data               ,
    input              [   1:0]         i_c0_tx_header             ,
    input              [   6:0]         i_c0_tx_seq                ,//外部序列计数器
    input                               i_c0_rx_gt_p               ,
    input                               i_c0_rx_gt_n               ,
    output                              o_c0_tx_gt_p               ,
    output                              o_c0_tx_gt_n               ,

//channel_1
    input                               i_c1_rx_rst                ,
    input                               i_c1_tx_rst                ,
    output                              o_c1_tx_done               ,
    output                              o_c1_rx_done               ,
    input              [   2:0]         i_c1_gt_loopback           ,
    input              [   3:0]         i_c1_txdiffctrl_in         ,
    input              [   0:0]         i_c1_txpolarity_in         ,
    input              [   4:0]         i_c1_txpostcursor_in       ,
    input              [   4:0]         i_c1_txprecursor_in        ,
    input              [   0:0]         i_c1_rxpolarity_in         ,

    input  wire        [   8:0]         i_c1_drpaddr_in            ,
    input  wire        [   0:0]         i_c1_drpclk_in             ,
    input  wire        [  15:0]         i_c1_drpdi_in              ,
    input  wire        [   0:0]         i_c1_drpen_in              ,
    input  wire        [   0:0]         i_c1_drpwe_in              ,
    output wire        [  15:0]         o_c1_drpdo_out             ,
    output wire        [   0:0]         o_c1_drprdy_out            ,

    output                              o_c1_rx_clk                ,
    output             [  63:0]         o_c1_rx_data               ,
    output                              o_c1_rx_data_valid         ,
    output             [   1:0]         o_c1_rx_header             ,
    output                              o_c1_rx_header_valid       ,
    input                               i_c1_rxgearboxslip         ,//手动对齐
    output                              o_c1_tx_clk                ,
    input              [  63:0]         i_c1_tx_data               ,
    input              [   1:0]         i_c1_tx_header             ,
    input              [   6:0]         i_c1_tx_seq                ,//外部序列计数器
    input                               i_c1_rx_gt_p               ,
    input                               i_c1_rx_gt_n               ,
    output                              o_c1_tx_gt_p               ,
    output                              o_c1_tx_gt_n               
);

 3.整体工程搭建

我们需要自己实现64/66的phy层,进行phy的编写。

包含phy_rx,phy_tx模块,对gt收发器接受到的数据进行解包

phy_rx如下:

module phy_rx
(
    input                               i_rx_clk                   ,
    input                               i_rx_rst                   ,
    input              [  63:0]         i_rx_data                  ,
    input                               i_rx_valid                 ,
    input              [   1:0]         i_rx_header                ,
    input                               i_rx_header_valid          ,

    output             [  63:0]         m_axis_data                ,
    output             [   7:0]         m_axis_keep                ,
    output                              m_axis_last                ,
    output                              m_axis_valid                
);

 解包还需要控制rxgearboxslip,该信号用于控制gt收发器的接受端口的数据对齐,

module PHY_rx_bitsync#(
    parameter       P_HEARER_VALID_NUMNER = 64  ,
    parameter       P_SLIPBIT_GAP         = 40  
)(
    input           i_clk                       ,
    input           i_rst                       ,
   (* MARK_DEBUG="true" *)input  [1:0]    i_header                    ,
   (* MARK_DEBUG="true" *)input           i_headr_valid               ,
   (* MARK_DEBUG="true" *)output          o_slipbit                   ,
   (* MARK_DEBUG="true" *)output          o_sync                  
);

 参考了example_prj中的工程。

核心就是,检验头部header,在64/66b中:

控制头说明:00:帧错误;01:纯数据帧;10:控制帧;11:帧错误

 检测header是否一直为01或10。没有其他两种错误,即可认为链接建立完成。

若为满足预定时间的要求,即偶尔出现了00或者11,任然有错,发起一次o_slipbit。对拼接数据的位置进行移动。直到满足稳定要求。且o_slipbit的移动间隔必须大于32个周期,任然是使用了gearbox的原因。

last:上板验证 

虽然说是AXI接口,但是gearbox64b\66b的每次间隔32个周期传输数据需要暂停一个周期的要求依然存在,通过m_axi_ready来体现。在传递时注意编写条件,不然会少传递数据。如果恰好在m_axi_last拉高时,aurora64/66_ip返回来的ready恰好拉低,就会出错!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值