基于Ultrascale+系列GTY收发器8b/10b编码方式的数据传输(二)——数据收发及上板测试

  基于Ultrascale+系列GTY收发器8b/10b编码方式的数据传输(一)——GTY IP核介绍及配置 简单介绍了GTY收发器使用8B/10B编码所需的配置,本文继续利用前文配置的IP核进行数据收发。前文配置的GTY IP核引脚如下。

Image

复位逻辑

Image

  如前文所述,GTY使用前必须经过复位,GTY中TX、RX的复位可通过复位状态机进行。用户逻辑需要在时钟复位完成后(gtpowergood拉高)向TX、RX复位信号(gtwiz_userclk_tx_reset_in、gtwiz_userclk_rx_reset_in)提供使能。以TX复位为例,相关控制逻辑如下:

    logic gtpowergood_meta_r, gtpowergood_gtwiz_reset_clk_freerun_r;

    always_ff @(posedge gtwiz_reset_clk_freerun_in) begin // cdc async gtpowergood
        gtpowergood_meta_r <= gtpowergood_out;
        gtpowergood_gtwiz_reset_clk_freerun_r <= gtpowergood_meta_r;
    end

    enum logic [2:0] {
        RESETTX,
        IDLETX
    } txreset_fsm_r = RESETTX, txreset_fsm_s;

    always_ff @(posedge gtwiz_reset_clk_freerun_in) begin // async reset
        txreset_fsm_r <= txreset_fsm_s;
    end

    always_comb begin
        case (txreset_fsm_r)
        RESETTX: begin
            if (gtpowergood_gtwiz_reset_clk_freerun_r) begin
                txreset_fsm_s = IDLETX;
            end else begin
                txreset_fsm_s = RESETTX;
            end
        end
        IDLETX: begin
            txreset_fsm_s = IDLETX;
        end
        default: txreset_fsm_s = RESETTX;
        endcase
    end

    always_ff @(posedge gtwiz_reset_clk_freerun_in) begin
        case (txreset_fsm_s)
        RESETTX: begin
            gtwiz_userclk_tx_reset_in <= 1'b1;
        end
        IDLETX: begin
            gtwiz_userclk_tx_reset_in <= 1'b0;
        end
        default: begin
            gtwiz_userclk_tx_reset_in <= 1'b1;
        end
        endcase
    end

8B/10B数据帧格式

  本文采用的8B/10B数据帧采用K29.7作为数据帧起始位,K27.7作为数据帧停止位,数据帧传输前需传输4个字节的时钟纠正序列。

K28.5D16.2K28.5D16.2K29.7DATA…K27.7

用户逻辑

  在使用GTY的8B/10B编码时,8B/10B对应关系表已固化在GTY硬核中,用户不需要编写进行8B/10B转换的逻辑,只需要将需要的极性、数据字节值、是否为控制字符送到硬核进行发送,以及从硬核读取接收到的数据字节即可。

  下图展示了TX发送及RX接口的8B/10B转化过程,GTY硬核采用小端的方式,TX位于低位(LSB)的字节为优先发送的数据,RX位于低位(LSB)的字节为最早接收的数据。

Image

Image

发送逻辑

  GTY的8B/10B发送主要包含gtwiz_userdata_tx_in、txctrl0、txctrl1、txctrl2接口。

  gtwiz_userdata_tx_in为发送的原始数据,txctrl2用于指定发送的原始数据对应8bit字节是否为控制字符。

Image

Image

  txctrl0、txctrl1用于指定待发送的原始数据采用正极性还是负极性编码,当设置为0时,由GTY硬核自动计算编码。

  发送8B/10B的数据帧的方式如下,在gtwiz_reset_tx_done_out信号拉高后,tx部分结束复位状态,通过SEND_HDR发送纠正序列、SEND_DATA发送帧起始位及三个数据字符、SEND_EOF发送三个数据字符及帧结束位,依次往复。

    assign txctrl1_in = 16'h0; // 5bit disparity
    assign txctrl0_in = 16'h0; // 3bit disparity

    enum logic [3:0] {
        SEND_RESET,
        SEND_LFSR,
        SEND_HDR,
        SEND_DATA,
        SEND_EOF
    } send_fsm_r, send_fsm_s;

    always_ff @(posedge gtwiz_userclk_tx_usrclk2_out) begin
        if (gtwiz_reset_tx_done_out) begin
            send_fsm_r <= send_fsm_s;
        end else begin
            send_fsm_r <= SEND_RESET;
        end
    end

    always_comb begin
        case (send_fsm_r)
        SEND_RESET: begin
            if (gtwiz_reset_tx_done_out) begin
                send_fsm_s = SEND_LFSR;
            end else begin
                send_fsm_s = SEND_RESET;
            end
        end
        SEND_LFSR: send_fsm_s = SEND_HDR;
        SEND_HDR: send_fsm_s = SEND_DATA;
        SEND_DATA: send_fsm_s = SEND_EOF;
        SEND_EOF: send_fsm_s = SEND_LFSR;
        default: send_fsm_s = SEND_RESET;
        endcase
    end

    always_ff @(posedge gtwiz_userclk_tx_usrclk2_out) begin
        case (send_fsm_s)
        SEND_RESET, SEND_LFSR: begin
            gtwiz_userdata_tx_in <= 32'h0;
            txctrl2_in <= 4'b0000;
        end
        SEND_HDR: begin
            gtwiz_userdata_tx_in <= {8'h50, 8'hbc, 8'h50, 8'hbc}; // bc50bc50
            txctrl2_in <= 4'b0101;
        end
        SEND_DATA: begin // sof + 3 data
            gtwiz_userdata_tx_in <= {8'h03, 8'h02, 8'h01, FRAME_SOF};
            txctrl2_in <= 4'b0001;
        end
        SEND_EOF: begin  // eof + 3 data / LFSR
            gtwiz_userdata_tx_in <= {FRAME_EOF, 8'h06, 8'h05, 8'h04};
            txctrl2_in <= 4'b1000;
        end
        endcase
    end

接收逻辑

  GTY的8B/10B接收主要包含gtwiz_userdata_rx_out、rxctrl0、rxctrl1、txctrl2、rxctrl3接口。

  gtwiz_userdata_rx_out为接收到的原始数据,rxctrl0用于表明接收的对应8bit数据是否为控制字符。rxctrl1用于表明对应的8bit字节极性错误、rxctrl2用于表明对应8bit字节为逗号标志、rxctrl3用于表明接收的10bit不对应任何8bit数据,即这里对应的8bit数据无效。

  在接收逻辑部分,帧起始位与帧结束位可能出现在4字节gtwiz_userdata_rx_out的任意一个字节,因此状态机需要对任何一个字节作为帧起始位或结束位的情况进行处理。

    enum logic [3:0] {
        RECV_RESET,
        RECV_DET,
        RECV_HDR,
        RECV_DATA
    } recv_fsm_r, recv_fsm_s;

    always_ff @(posedge gtwiz_userclk_rx_usrclk2_out) begin
        if (gtwiz_reset_rx_done_out) begin
            recv_fsm_r <= recv_fsm_r;
        end else begin
            recv_fsm_r <= RECV_RESET;
        end
    end

    always_comb begin
        case (recv_fsm_r)
        RECV_RESET: begin
            if (gtwiz_reset_rx_done_out) begin
                recv_fsm_s = RECV_DET;
            end else begin
                recv_fsm_s = RECV_RESET;
            end
        end
        RECV_DET: begin
            recv_fsm_s = RECV_DET;
        end
        default: recv_fsm_s = RECV_RESET;
        endcase
    end

    (* MARK_DEBUG="true" *) logic [31:0] rx_data;
    (* MARK_DEBUG="true" *) logic [3:0]  rx_keep;
    (* MARK_DEBUG="true" *) logic        rx_valid;
    logic        rx_valid_next, rx_valid_next_next;

    always_ff @(posedge gtwiz_userclk_rx_usrclk2_out) begin
        case (recv_fsm_s)
        RECV_RESET: begin
            rx_valid <= 1'b0; 
        end
        RECV_DET: begin
            // clock correction need 4byte, sof must before than eof in 32bit
            if (rxframe_eof_flag_rr && rxframe_eof_rest_cnt_r + rxframe_sof_rest_cnt_r > 4) begin
                rx_valid <= 1;
            end else begin
                rx_valid <= rx_valid_next;
            end

            if (rxframe_eof_flag_r) begin
                case ({1'b0, rxframe_eof_rest_cnt_r[1:0]} + {1'b0, rxframe_sof_rest_cnt_r[1:0]})
                default: rx_keep <= 4'b1111;
                3'd3: rx_keep <= 4'b0111;
                3'd2: rx_keep <= 4'b0011;
                3'd1: rx_keep <= 4'b0001;
                3'd0: rx_keep <= 4'b0000;
                endcase
            end
            else if (rxframe_eof_flag_rr) begin
                case (rxframe_eof_rest_cnt_r[1:0] + rxframe_sof_rest_cnt_r[1:0])
                2'd3: rx_keep <= 4'b0111;
                2'd2: rx_keep <= 4'b0011;
                2'd1: rx_keep <= 4'b0001;
                2'd0: rx_keep <= 4'b0000;
                endcase
            end else if (rx_valid_next) begin
                rx_keep <= 4'b1111;
            end

            case (rxframe_sof_rest_cnt_s)
            2'd3: rx_data <= {gtwiz_userdata_rx_out_r[7:0], gtwiz_userdata_rx_out_rr[31:8]};
            2'd2: rx_data <= {gtwiz_userdata_rx_out_r[15:0], gtwiz_userdata_rx_out_rr[31:16]};                                                        
            2'd1: rx_data <= {gtwiz_userdata_rx_out_r[23:0],  gtwiz_userdata_rx_out_rr[31:24]};
            2'd0: rx_data <= gtwiz_userdata_rx_out_r;            end
            endcase
        end
        endcase
    end

仿真测试

  本工程对发送端发送帧长(不包含帧开始结束位)为0-6位进行了测试,这里以帧长为6的仿真结果举例。

Image

上板测试

Image

工程代码

  本文所涉及的工程代码可于同名公众号回复GTY_8B10B_SIMPLE下载。

  • 22
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjh776a68

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值