当前位置:首页 > 技术 > 正文内容

GTX 8B10B编码下的自定义PHY接收逻辑设计

访客 技术 2026年7月12日 2

在完成基于GTX高速收发器的发送路径开发后,本文聚焦于接收端模块的设计。相较于发送侧,接收部分需额外处理字节对齐与帧边界识别问题,复杂度更高。

设计原理分析

由于Xilinx GTX IP核未提供自动字对齐功能,用户必须自行实现帧同步机制。考虑到数据流中可能包含任意字节内容,起始标识(0xFB)和终止标识(0xFD)可出现在32位宽数据总线的任意字节位置。

本方案采用如下自定义帧结构:以24位特征码0xBC50FB作为帧头标志,帧尾仍使用单字节0xFD标记结束。实际传输过程中,部分逗号序列可能被用于时钟补偿,因此需在解析阶段予以排除。

由于未进行字对齐,接收端观测到的有效数据分布存在16种可能组合,如图所示:

帧头帧尾分布模式
图 帧头帧尾的16种分布情况

根据起始位与停止位所在字节索引的关系,可归纳出最终输出数据的有效字节掩码规则:

  • 若二者相差1个字节 → 所有4字节均有效
  • 若相差2个字节或反向差1个字节 → 仅最高1字节有效
  • 若相差3个字节或反向差1个字节 → 高2字节有效
  • 若位于同一字节位置 → 高3字节有效

设计核心思路为:利用移位寄存器缓存原始输入数据,通过多级流水线检测帧头,并记录起始位的位置偏移,从而动态生成后续数据的有效性掩码信号keep

关键逻辑实现

以下为核心模块的Verilog实现片段,已重构变量命名并优化判断逻辑结构:

// 多阶段帧头检测逻辑
reg header_detected;
always @(posedge clk or posedge rst) begin
    if (rst)
        header_detected <= 1'b0;
    else begin
        // 检测四种可能的帧头排列方式
        header_detected <= (
            (rx_data_pipe[1][15:0] == 16'h50bc && rx_kchar_pipe[1][1] == 1'b1 &&
             rx_data_pipe[0][7:0]   == 8'hfb   && rx_kchar_pipe[0][0] == 1'b1) ||
            (rx_data_pipe[1][23:16] == 8'hbc  && rx_kchar_pipe[1][2] == 1'b1 &&
             rx_data_pipe[0][15:0]  == 16'hfb50 && rx_kchar_pipe[0][1:0] == 2'b10) ||
            (rx_data_pipe[0][23:0]  == 24'hfb50bc && rx_kchar_pipe[0][2:0] == 3'b101) ||
            (rx_data_pipe[0][31:8]  == 24'hfb50bc && rx_kchar_pipe[0][3:1] == 3'b101)
        );
    end
end

// 数据输出使能控制
reg data_output_enable;
always @(posedge clk or posedge rst) begin
    if (rst)
        data_output_enable <= 1'b0;
    else if (eof_detected)
        data_output_enable <= 1'b0;
    else if (header_detected && byte_aligned)
        data_output_enable <= 1'b1;
end

// 起始位字节位置捕获
reg [1:0] start_byte_index;
always @(posedge clk or posedge rst) begin
    if (rst)
        start_byte_index <= 2'd0;
    else if (header_detected && byte_aligned) begin
        casez ({rx_kchar_pipe[1], rx_data_pipe[1]})
            {4'b??1?, 32'h???????fb} : start_byte_index = 2'd0;
            {4'b?1??, 32'h????fb???} : start_byte_index = 2'd1;
            {4'b1???, 32'h??fb?????} : start_byte_index = 2'd2;
            {4'b1???, 32'hfb??????} : start_byte_index = 2'd3;
            default: ;
        endcase
    end
end

// 终止位检测及位置记录
reg eof_detected;
reg [1:0] end_byte_index;
always @(posedge clk or posedge rst) begin
    if (rst) begin
        eof_detected     <= 1'b0;
        end_byte_index   <= 2'd0;
    end else if (data_output_enable) begin
        casez ({rx_kchar_curr, rx_data_curr})
            {4'b??1?, 32'h???????fd} : {eof_detected, end_byte_index} = {1'b1, 2'd0};
            {4'b?1??, 32'h????fd???} : {eof_detected, end_byte_index} = {1'b1, 2'd1};
            {4'b1???, 32'h??fd?????} : {eof_detected, end_byte_index} = {1'b1, 2'd2};
            {4'b1???, 32'hfd??????} : {eof_detected, end_byte_index} = {1'b1, 2'd3};
            default: eof_detected <= 1'b0;
        endcase
    end else
        eof_detected <= 1'b0;
end

// 输出数据重组(大端优先)
always @(posedge clk) begin
    if (rst)
        output_data <= 32'd0;
    else if (data_output_enable)
        casex ({start_byte_index, rx_data_pipe[2], rx_data_pipe[1]})
            {2'd0, ?, ?}: output_data <= {rx_data_pipe[2][23:16], rx_data_pipe[2][31:24],
                                          rx_data_pipe[1][7:0],   rx_data_pipe[1][15:8]};
            {2'd1, ?, ?}: output_data <= {rx_data_pipe[2][31:24], rx_data_pipe[1][7:0],
                                          rx_data_pipe[1][15:8],  rx_data_pipe[1][23:16]};
            {2'd2, ?, ?}: output_data <= {rx_data_pipe[1][7:0],  rx_data_pipe[1][15:8],
                                          rx_data_pipe[1][23:16], rx_data_pipe[1][31:24]};
            {2'd3, ?, ?}: output_data <= {rx_data_pipe[1][15:8], rx_data_pipe[1][23:16],
                                          rx_data_pipe[1][31:24], rx_data_pipe[2][7:0]};
        endcase
end

// 最终数据有效性掩码生成
reg [3:0] keep_mask_reg;
always @(posedge clk or posedge rst) begin
    if (rst)
        keep_mask_reg <= 4'hF;
    else if (eof_detected) begin
        automatic int diff = $signed(end_byte_index - start_byte_index);
        case (diff)
            1:   keep_mask_reg <= 4'b1111;
            2,-2: keep_mask_reg <= 4'b1000;
            3,-1: keep_mask_reg <= 4'b1100;
            0:   keep_mask_reg <= 4'b1110;
        endcase
    end
end

系统级验证策略

构建顶层测试环境,将发送与接收模块闭环连接,通过参数化配置模拟不同帧对齐场景:

`define TX_KEEP_WIDTH 4'b1111
`define START_OFFSET  2'd0

module tb_phy_top();
    parameter CLK_PERIOD = 10;
    
    reg clk;
    reg reset_n;
    
    // DUT实例化
    phy_module dut (
        .i_tx_clk(clk),
        .i_tx_rst_n(reset_n),
        .i_rx_clk(clk),
        .i_rx_rst_n(reset_n),
        // ... 其他端口连接
    );

    // 输入延迟模拟
    generate
        case (`START_OFFSET)
            2'd0: assign processed_rx_data = raw_rx_data;
            2'd1: assign processed_rx_data = {raw_rx_data[23:0], delayed_data[31:24]};
            2'd2: assign processed_rx_data = {raw_rx_data[15:0], delayed_data[31:16]};
            2'd3: assign processed_rx_data = {raw_rx_data[7:0],  delayed_data[31:8]};
        endcase
    endgenerate

    // 时钟与复位生成
    initial begin
        clk = 0;
        forever #(CLK_PERIOD/2) clk = ~clk;
    end
    
    initial begin
        reset_n = 0;
        #20 reset_n = 1;
    end

通过遍历所有起始/终止位组合进行回归测试,结果表明各类边界条件下输出数据及其keep信号均符合预期,验证了设计的鲁棒性。

最终综合得到的RTL视图为典型的全双工架构,发送与接收通道独立运行:

PHY顶层结构
图 系统级结构示意图

该接收模块成功实现了非对齐数据流中的帧同步、字节重排与精确掩码控制,支持任意长度和内容的数据包接收。

标签: GTX

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。