64B/66B GT Transceiver 配置

news2024/11/20 5:13:41

一、前言

前一篇文章已经讲述了64B/66B的编码原理,此篇文章来配置一下7系列GT的64B/66B编码。并讲述所对应的例子工程的架构,以及部分代码的含义。

二、IP核配置

1、打开7 Series FPGAs Transceiver Wizards,选择将共享逻辑放置在example design中

 2、线速率、参考时钟选择

(1)协议选择从0开始

(2)线速率选择10G,参考时钟选择156.25M

(3)PLL选择:当线速率大于6.6G,自动选择为QPLL

(4)Transceiver选择:保持默认就可以,在布局布线的时候,软件会根据管脚绑定自动选择Transceiver。

3、编码和时钟选择

(1)选择TX、RX外部数据带宽为64bit,选择编码方式为64B/66B with Ext Seq Ctr,内部数据带宽为32bit,DRP时钟为100M

这里的64B/66B with Ext Seq Ctr表示使用64B/66B编码,并使用外部计数器。关于这方面的知识可以去参考UG476中的Gearbox的章节,或者参考此篇文章:详解GearBox设计原理

(2)这里的选项几乎都是有关8B/10B编码的,不需要勾选

(3)这里使用弹性Buffer去做跨时钟域,选择TXUSERCLK的源为TXOUTCLK,TXOUTCLK的源为参考时钟。

(4)这里的选项大多关于PCS、PMA复位或者QPLL、CPLL掉电的,也不需要勾选

 4、逗号对齐和均衡

(1)这里的选项全部都是8B/10B所用到的,所以不能选择

(2)均衡方式这里选择DFE,接收端的阈值电压设置为800mv

(3)这里将TX极性转换、幅值控制、前加重、后加重选上,RX端将RX极性转换选上。

5、这是是使用PCIe或者SATA所用的选项,这里只将loopback勾选

6、通道绑定和时钟矫正

在这里使用序列长度为2的时钟矫正序列,并设置为BC507、总结,关注以下内部带宽、外部带宽,参考时钟频率、TXUSERCLK2就好

 三、例子工程

工程架构:

 Frame_gen模块:用来产生数据帧;

Scrambler模块:用来对所发送的数据进行加扰;

Descrambler模块:用来对接收的模块进行解扰;

Block_syn模块:用于进行块同步。

Frame_chck:用于检测接收到的数据正确性

四、加扰、解扰模块

64B/66B自同步扰码实现随机化,编码所使用的扰码器为: X58+X39+1

扰码的数学原理使用了多项式,多项式的选择通常是基于扰码的特性,包括生成数据的随机度,以及打乱连0和连1的能力。一个简单的扰码器包含一组排列好的触发器,用于移位数据流。大部分的触发器只需要简单地输出下一个比特流即可,但是在复杂的扰码电路中,触发器需要与数据流中的历史比特进行逻辑运算(与和或运算)。

例子工程中加扰、解扰模块是按照如下的示意图进行的:

加扰、解扰程序如下 

//加扰模块
module gtwizard_0_SCRAMBLER #
( 
    parameter TX_DATA_WIDTH = 32
)
(
    // User Interface
    input  wire  [(TX_DATA_WIDTH-1):0] UNSCRAMBLED_DATA_IN,
    input  wire                        DATA_VALID_IN,
    output reg   [(TX_DATA_WIDTH-1):0] SCRAMBLED_DATA_OUT,

    // System Interface
    input  wire          USER_CLK,
    input  wire          SYSTEM_RESET
);


//***************************Internal Register Declarations******************** 

    integer                        i;
    reg     [57:0]                 poly;
    reg     [(TX_DATA_WIDTH-1):0]  scrambled_data_i;
    reg     [57:0]                 scrambler;
    reg     [(TX_DATA_WIDTH-1):0]  tempData;
    reg                            xorBit;

//*********************************Main Body of Code***************************

    always @(scrambler,UNSCRAMBLED_DATA_IN)
    begin
        poly = scrambler;
        for (i=0;i<=(TX_DATA_WIDTH-1);i=i+1)
        begin
            xorBit = UNSCRAMBLED_DATA_IN[i] ^ poly[38] ^ poly[57];
            poly = {poly[56:0],xorBit};
            tempData[i] = xorBit;
        end
    end  

    //________________ Scrambled Data assignment to output port _______________    

    always @(posedge USER_CLK)
    begin
        if (SYSTEM_RESET)
        begin
            SCRAMBLED_DATA_OUT <= `DLY  'h0;
            scrambler          <= `DLY  58'h155_5555_5555_5555;
        end
        else if (DATA_VALID_IN)
        begin
            SCRAMBLED_DATA_OUT <= `DLY  tempData;
            scrambler          <= `DLY  poly;
        end
    end
         
endmodule
//解扰模块
module gtwizard_0_DESCRAMBLER #
( 
    parameter RX_DATA_WIDTH = 32
)
(
   // User Interface
    input  wire [(RX_DATA_WIDTH-1):0] SCRAMBLED_DATA_IN,
    input  wire                       DATA_VALID_IN,
    output reg  [(RX_DATA_WIDTH-1):0] UNSCRAMBLED_DATA_OUT,

      // System Interface
input  wire         USER_CLK,
input  wire         SYSTEM_RESET
);


//***************************Internal Register Declarations******************** 

    reg     [57:0]                 descrambler;
    integer                        i;
    reg     [57:0]                 poly;
    reg     [(RX_DATA_WIDTH-1):0]  tempData;
    reg     [(RX_DATA_WIDTH-1):0]  unscrambled_data_i;
    reg                            xorBit;

//*********************************Main Body of Code***************************

    always @(descrambler,SCRAMBLED_DATA_IN)
    begin
        poly = descrambler;
        for (i=0;i<=(RX_DATA_WIDTH-1);i=i+1)
        begin
            xorBit = SCRAMBLED_DATA_IN[i] ^ poly[38] ^ poly[57];
            poly = {poly[56:0],SCRAMBLED_DATA_IN[i]};
            tempData[i] = xorBit;
        end
    end

    //________________ Scrambled Data assignment to output port _______________    

    always @(posedge USER_CLK)
    begin
        if (SYSTEM_RESET)
        begin
            UNSCRAMBLED_DATA_OUT <= `DLY  'h0;
            descrambler          <= `DLY  58'h155_5555_5555_5555;
        end
        else if (DATA_VALID_IN)
        begin
            UNSCRAMBLED_DATA_OUT <= `DLY  tempData;
            descrambler          <= `DLY  poly;
        end
    end
         
endmodule

五、块对齐

64B/66B和64B/67B协议依赖于块同步来确定它们的块边界。块同步是必需的,因为在实现块锁定之前,所有传入的数据都未对齐。其目标是通过更改数据对齐方式来搜索有效的同步标头。RXGEARBOXSLIP输入端口用于改变Gearbox数据对齐,以便可以在正常模式下检查所有可能的对齐。RXGEARBOXSLIP输入端口用于改变变速箱数据对齐,以便可以在正常模式下检查所有可能的对齐。这个滑移和测试同步头的过程重复,直到实现块锁定。使用RXGearbox时,FPGA逻辑中需要块同步状态机。

整个过程按照如下的状态机进行:

例子工程的代码如下,将一些关键条件进行注释:

`timescale 1ns / 1ps
`define DLY #1

module gtwizard_0_BLOCK_SYNC_SM #
(
    parameter SH_CNT_MAX         = 64,
    parameter SH_INVALID_CNT_MAX = 16 
)
(
    // User Interface
    output reg          BLOCKSYNC_OUT,
    output reg          RXGEARBOXSLIP_OUT,
    input  wire [2:0]   RXHEADER_IN,
    input  wire         RXHEADERVALID_IN,

    // System Interface
    input  wire         USER_CLK,
    input  wire         SYSTEM_RESET
);
    

//**************************** Wire Declarations ******************************

    wire           slip_pulse_i;    
    wire           next_begin_c;
    wire           next_sh_invalid_c;    
    wire           next_sh_valid_c;    
    wire           next_slip_c;    
    wire           next_sync_done_c;    
    wire           next_test_sh_c;    
    wire           sh_count_equals_max_i;    
    wire           sh_invalid_cnt_equals_max_i;    
    wire           sh_invalid_cnt_equals_zero_i;    
    wire           slip_done_i;    
    wire           sync_found_i;    

//***************************External Register Declarations*************************** 

    reg            begin_r;
    reg            sh_invalid_r;    
    reg            sh_valid_r;    
    reg    [31:0]  slip_count_i; 
    reg            slip_r;    
    reg            sync_done_r;    
    reg    [9:0]   sync_header_count_i; 
    reg    [9:0]   sync_header_invalid_count_i;   
    reg            test_sh_r;    

//**************************** Main Body of Code *******************************

    // 
    assign sync_found_i   = (RXHEADER_IN[1:0] == 2'b01) || (RXHEADER_IN[1:0] == 2'b10);//寻找到数据头

    //________________________________ State machine __________________________    
    
    // State registers
    always @(posedge USER_CLK)
        if(SYSTEM_RESET)
            {begin_r,test_sh_r,sh_valid_r,sh_invalid_r,slip_r,sync_done_r}  <=  `DLY    6'b100000;
        else
        begin
            begin_r          <=  `DLY    next_begin_c;
            test_sh_r        <=  `DLY    next_test_sh_c;
            sh_valid_r       <=  `DLY    next_sh_valid_c;
            sh_invalid_r     <=  `DLY    next_sh_invalid_c;
            slip_r           <=  `DLY    next_slip_c;
            sync_done_r      <=  `DLY    next_sync_done_c;
        end

    // Next state logic
    //begin信号相当于一个复位信号,当同步 或者 滑动计数器已满 或者 同步计数器已经达到最大值但是无效同步计数器有值 或者 同步头无效,同步头的数量到达最大值 都要将计数器清0
    assign  next_begin_c     =   sync_done_r                                                                                    //已经同步
                                 | (slip_r && slip_done_i)                                                                      //slip的滑动计数器已满
                                 | (sh_valid_r && sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i)                        //同步头有效,同步头的数量到达最大值,无效同步头的数量也没有达到最大值
                                 | (sh_invalid_r && sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i && BLOCKSYNC_OUT);    //同步头无效,同步头的数量到达最大值,无效同步头的数量也没有达到最大值 快同步继续进行
                              
   assign  next_test_sh_c    =  begin_r                                                                                         //开始
                                | (test_sh_r && !RXHEADERVALID_IN)                                                              //正在检测同步头,并且没有有效的同步头输入,则下一个时钟周期继续检测头部
                                | (sh_valid_r && !sh_count_equals_max_i)                                                        //同步头有效,但是有效同步头的数量没有达到最大值
                                | (sh_invalid_r && !sh_count_equals_max_i && !sh_invalid_cnt_equals_max_i && BLOCKSYNC_OUT);    //同步头无效、同步头的数量没有到达最大值、无效同步头的数量也没有达到最大值、快同步继续进行
                             

   assign  next_sh_valid_c   =  (test_sh_r && RXHEADERVALID_IN && sync_found_i);                                                //同步头已经找到,并且输入头有效,并且正在处于查找输入头的状态

   assign  next_sh_invalid_c =  (test_sh_r && RXHEADERVALID_IN && !sync_found_i);                                               //正在处于查找输入头的状态,输入头有效,但是同步头没有找到,

   assign  next_slip_c       = (sh_invalid_r && (sh_invalid_cnt_equals_max_i || !BLOCKSYNC_OUT))                                                            //下一次滑动的条件:同步头无效,无效同步头计数达到最大值 或者 块同步输出为0
                               | (sh_valid_r && sh_count_equals_max_i && ! sh_invalid_cnt_equals_zero_i && (sh_invalid_cnt_equals_max_i || !BLOCKSYNC_OUT)) //同步头有效并且有效同步头计数器已达到最大值,但是无效同步计数器不为0,并且此时的无效同步计数器达到最大值或者块同步没有输出
                               | (slip_r && !slip_done_i);                                                                                                  //滑动信号有效并且滑动计数器没有计满

   assign  next_sync_done_c  =  (sh_valid_r && sh_count_equals_max_i && sh_invalid_cnt_equals_zero_i);                          //同步标志:输入的同步头有效并且有效同步头计数器达到最大值并且无效同步器计数为0
 
    //________________ Counter keep track of sync headers counted _____________    

    always @(posedge USER_CLK)
        if(begin_r)  
        begin
            sync_header_count_i   <=  `DLY    10'd0;
        end
        else if (sh_valid_r || sh_invalid_r)                                                                                  //同步计数器在有效同步头和无效同步头的时候都会加1
        begin
            sync_header_count_i  <=  `DLY    sync_header_count_i + 10'd1;
        end

    assign sh_count_equals_max_i = (sync_header_count_i==SH_CNT_MAX);
    
    //________________ Counter keep track of invalid sync headers  ____________    

    always @(posedge USER_CLK)
        if(begin_r)  
        begin
            sync_header_invalid_count_i   <=  `DLY    10'd0;
        end
        else if (sh_invalid_r)                                                                                              //记录无效同步头的数量
        begin
            sync_header_invalid_count_i  <=  `DLY    sync_header_invalid_count_i + 10'd1;
        end

    // signal to indicate max number of invalid sync headers has been reached
    assign sh_invalid_cnt_equals_max_i  = (sync_header_invalid_count_i==SH_INVALID_CNT_MAX);

    // signal to indicate no invalid sync headers
    assign sh_invalid_cnt_equals_zero_i = (sync_header_invalid_count_i==0);

    //_______ Counter wait for 16 cycles to ensure that slip is complete _______    

    assign slip_pulse_i = next_slip_c && !slip_r;                                                                           //滑动信号输出

    always @(posedge USER_CLK)
        RXGEARBOXSLIP_OUT   <=  slip_pulse_i;

    //_____________ Ouput assignment to indicate block sync complete  _________     

    always @(posedge USER_CLK)
        if(!slip_r) slip_count_i   <=  `DLY    32'h00000000;
        else        slip_count_i   <=  `DLY    {slip_count_i[30:0],RXGEARBOXSLIP_OUT};                                      //滑动计数器

    assign slip_done_i = slip_count_i[31];


    //_____________ Pulse GEARBOXSLIP port to slip the data by 1 bit  _________    

    always @(posedge USER_CLK)
        if(SYSTEM_RESET || slip_r)  BLOCKSYNC_OUT   <=  `DLY    1'b0;
        else if (sync_done_r)       BLOCKSYNC_OUT   <=  `DLY    1'b1;                                                       //当同步时,证明块同步已完成


        
        
endmodule

六、总结

具体的块对齐过程可以结合仿真看一下,由于过程比较复杂,这里就不细说了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1593746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.Hexo主题安装和自定义

一个Hexo主题&#xff0c;基本上只是一组HTML、CSS和JavaScript文件来定义布局的外观和感觉 在默认情况下&#xff0c;Hexo会附带一个主题&#xff0c;landscape主题 这个主题就比较可靠&#xff0c;确实有效 如果想要使用不同的主题&#xff0c;可以下载并安装一个主题&…

OpenHarmony开源三方库的cmake在IDE上直接引用的问题

前言 DevEco Studio的native工程的C/C部分当前只支持cmake脚本的编译&#xff0c;工程的目录结构如下图所示 在工程中引用第三方库有如下三种方式&#xff0c; 一、find_package模式 通过find_package&#xff0c;可以在指定目录下去搜索已安装的库&#xff08;三方库构建完后…

从零实现诗词GPT大模型:专栏内容规划

一、前情介绍 本系列文章将从头编写一个类GPT的深度学习模型&#xff0c;并在诗词数据集上进行训练&#xff0c;从而可以进行诗词创作。 本次实现的类GPT模型&#xff0c;可以在kaggle上使用免费GPU进行训练&#xff0c;并可以在自己的电脑上进行推理&#xff0c;整个学习过程…

申请OV SSL证书

OV证书&#xff0c;即Organization Validation证书&#xff0c;是一种SSL/TLS证书类型&#xff0c;主要用于企业级应用&#xff0c;例如教育、政府、互联网等行业的大型企业和政府机关部门。与基础的域名验证&#xff08;DV&#xff09;证书相比&#xff0c;OV证书的验证过程更…

入门:多层感知器Multiple-Layer Perceiver, MLP

本文将简单介绍多层感知器&#xff08;MLP&#xff09;的基本概念、原理和应用。MLP是一种前馈人工神经网络&#xff0c;由多层节点组成&#xff0c;每层节点通过权重和偏置与下一层节点相连。MLP在许多领域都有广泛的应用&#xff0c;如分类、回归、自然语言处理等。 本文将分…

Android Studio引入framework.jar包

一. 前言 Android Studio 引入framework.jar 步骤&#xff0c;记录笔记 Android源码编译产生的framework.jar 在不同的版本上生成路径是不同的 Android N/O: 7 和 8 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar Android P/Q: 9 和 10 out/s…

格式化D盘后C盘内的文件会受影响吗?深度解析

在计算机的日常使用中&#xff0c;磁盘格式化是一个常见的操作&#xff0c;它能帮助我们清除磁盘上的数据&#xff0c;为新的数据腾出空间。然而&#xff0c;当涉及到系统盘和其他存储盘时&#xff0c;许多用户会担心一个问题&#xff1a;如果我格式化了非系统盘&#xff0c;比…

SRIO学习(3)使用SRIO IP核进行设计

文章目录 前言一、设计框图二、模块介绍三、上板验证总结 前言 本文将通过使用SRIO IP核实现数据通信&#xff0c;重点在于打通数据链路&#xff0c;具体的协议内容设计并非重点&#xff0c;打通了链路大家自己根据设计需求来即可。 一、设计框图 看了前面高速接口的一些设计…

Linux 秋招必知必会(六、Socket 网络编程)

二、Socket 编程 13. 什么是 Socket&#xff1f; Socket 本身有 “插座” 的意思&#xff0c;在 Linux 环境下&#xff0c;用于表示进程间网络通信的特殊文件类型 本质为内核借助缓冲区形成的伪文件 既然是文件&#xff0c;那么可以使用文件描述符引用套接字 与管道类似&…

机器人路径规划:基于Q-learning算法的移动机器人路径规划(可以更改地图,起点,终点),MATLAB代码

一、Q-learning算法 Q-learning算法是强化学习算法中的一种&#xff0c;该算法主要包含&#xff1a;Agent、状态、动作、环境、回报和惩罚。Q-learning算法通过机器人与环境不断地交换信息&#xff0c;来实现自我学习。Q-learning算法中的Q表是机器人与环境交互后的结果&#…

AIGC 探究:人工智能生成内容的技术原理、广泛应用、创新应用、版权问题与未来挑战

AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;即人工智能生成内容&#xff0c;其核心在于利用深度学习技术&#xff0c;尤其是基于神经网络的模型&#xff0c;来模拟人类创作过程&#xff0c;自主生成高质量的文本、图像、音频、视频等各类内容。神经…

MySQL8.0的下载、安装配置教程、连接数据可视图形化界面和卸载及MySQL基本使用教程

文章目录 MySQL8.0下载安装MySQL卸载常见问题解决方式MySQL基本使用教程&#xff08;使用MySQLworkbench&#xff09; 1、创建数据库2、创建表、删除表3、修改表的名字4、为数据表增加、修改、删除字段5、关于修改数据库名字6、拓展&#xff1a;pycharm操作MySQL 首先&#…

Diagrams:Show Me​

大家好&#xff0c;今天给大家介绍的 GPTs 叫 Diagrams:Show Me。 首先&#xff0c;让Diagrams:Show Me介绍一下自己&#xff0c;了解一下他的基本功能 然后&#xff0c;让他告诉我们&#xff0c;我们要怎么与他进行交互。 按照他给出的例子来体验一下他的功能。先来第一个例子…

cog predict docker unknown flag: --file

如图&#xff1a; 使用cog predict -i image“link-to-image” 出现docker unknown flag: --file的问题。 解决方法&#xff08;对我可行&#xff09;&#xff1a;切换cog版本。 这个是我一开始的cog安装命令&#xff08;大概是下的最新版&#xff1f;&#xff09;&#xff1…

StarUML笔记之从UML图生成C++代码

StarUML笔记之从UML图生成C代码 —— 2024-04-14 文章目录 StarUML笔记之从UML图生成C代码1.Add Diagram2.在TOOLBOX中左键点击Class,松开,然后在中间画面再左键点击&#xff0c;即可出现UML3.修改类图&#xff0c;并添加接口&#xff0c;方法&#xff0c;属性&#xff0c;我…

12-LINUX--进程间的通信

进程间通信&#xff1a;采用IPC机制&#xff08;进程间的用户空间相互独立&#xff0c;内核空间共享&#xff09;&#xff0c;有管道&#xff0c;信号量&#xff0c;共享内存&#xff0c;消息队列&#xff0c;套接字。 一.管道 管道可以用来在两个进程之间传递数据&#xff0c…

C语言入门(第三天:函数、指针)

一、函数 1.1 函数概述 作用&#xff1a;提高代码的编写效率&#xff0c;实现对代码的重用 函数使用步骤 定义函数 理解为制作工具&#xff0c;工具只需要制作1次即可 调用函数 理解为使用工具 1.2 无参无返回值 1.3 有参无返回值(重点) 函数参数的作用&#xff1a;增加…

怎么提升公众号上限

正常可以申请多少个公众号&#xff1f;目前如果我们是企业主体的话&#xff08;包括个体户&#xff09;&#xff0c;申请公众号默认是可以申请2个公众号数量的。不过对于很多公司来说&#xff0c;2个公众号的数量肯定是远远不够用的&#xff0c;不同的产品不同品牌不同部门都可…

基于R语言实现的beta二项回归模型【理解与实现】

本实验&#xff0c;创建一组使用二项分布模拟的数据&#xff08;不带额外的随机性&#xff09;&#xff0c;和另一组使用Beta二项分布模拟的数据&#xff08;引入了随机成功概率 p&#xff0c;从而增加了数据的离散性。 现在假设我们站在上帝视角&#xff0c;有两组不知道分布…

【可能是全网最丝滑的LangChain教程】七、LCEL表达式语言

系列文章地址 【可能是全网最丝滑的LangChain教程】一、LangChain介绍-CSDN博客 【可能是全网最丝滑的LangChain教程】二、LangChain安装-CSDN博客 【可能是全网最丝滑的LangChain教程】三、快速入门LLM Chain-CSDN博客 【可能是全网最丝滑的LangChain教程】四、快速入门Re…