高速收发器:PHY层笔记(一)

笔记:

高速收发器的数据位宽通常有:2,4,8字节等;

PCIE喜欢的位宽是1DW = 4 Byte;

这里对高速收发器的设计为4 Byte也就是32位宽;

GT中PHY层的字对齐和掩码处理

高速收发器的数据流以SOT开始(和MIPI一样),GT的SOT一般就是K码,标志了开始,其也具有EOT,标志了结束;

但与MIPI有很大的不同,GT的K码可能会出现在数据端口的某一个字节上,接收端接收的顺序次序是随机的;

以32位宽违例:

{D0,D1,D2,D3} , SOT可能会出现在任何一个D的位置上;(EOT也需要处理这种情况)

我设置的是32/40的any边界,所以在四个字节的位置上出现都是有可能的。

 

这就意味着类似于MIPI的字对齐操作需要时刻进行;

    //Search_Byte_Offset
    reg [3:0]   i;
    always @(posedge I_CLK or negedge I_Rst_n) begin
        if(I_Rst_n == 1'b0) begin
            Byte_Offset <= 4'b0;
            Search_Locking <= 1'b0;
        end else if(!ReSearch_delay && I_ReSearch_Offset) begin
            Byte_Offset <= 4'b0;
            Search_Locking <= 1'b0;
        end else if(Search_Locking == 1'b0) begin
            for(i=8'h0;i<8;i=i+1) begin
                if(Concat_Byte_data[(i+1'b1)+:8] == SoT) begin
                    Byte_Offset <= i[2:0] + 1'b1;
                    Search_Locking <= 1'b1;
                end
            end
        end
    end

同时这还涉及掩码信号,其实就是AXI协议中的字节有效(PCIE中也有这种操作);

1.字对齐;

2.掩码处理;

我尝试用FOR来写,不好用;这个是错的,只是分享一下;

            for(r_looking_i=8'h0;r_looking_i < 32;r_looking_i = r_looking_i + 8) begin
                if(r_i_gt_rx_data[r_looking_i+:15] == P_Sync_Code[15:00]) begin
                    if(r_looking_i == 0 && r_i_gt_rx_data[16+:8] == P_SoT_Code[07:00]) begin
                        r_commoa_access == 1'b1;
                    end else if(r_looking_i == 0 && r_i_gt_rx_data[24+:8] == P_SoT_Code[07:00]) begin
                        r_commoa_access == 1'b1;
                    end else if(r_looking_i == 8 && r_i_gt_rx_data[24+:8] == P_SoT_Code[07:00]) begin
                        r_commoa_access == 1'b1;
                    end else if(r_looking_i == 8 && i_gt_rx_data[07:00] ==  P_SoT_Code[07:00])  begin
                        r_commoa_access == 1'b1;
                    end else if(r_looking_i == 16 && r_i_gt_rx_data[24+:8] == P_SoT_Code[07:00])  begin
                        r_commoa_access == 1'b1;
                    end
                end
            end

 这是我的现在写法:

    always @(posedge i_sys_clk) begin
        if(i_sys_rst == 1'b1) begin
            r_o_axi_s_keep <= 4'b0000;
        end else if((r_sof_check == 1'b1)||(r_data_process == 1'b1)) begin
            if(r_sof_mark == 4'b0001) begin
                if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1110;
                end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1111;
                end else if(r_eof_mark == 4'b0100 && r_d1_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1000;
                end else if(r_eof_mark == 4'b1000 && r_d1_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1100;
                end else begin
                    r_o_axi_s_keep <= 4'b1111;
                end
            end else if(r_sof_mark == 4'b0010) begin
                if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1100;
                end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1110;
                end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1111;
                end else if(r_eof_mark == 4'b1000 && r_d1_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1000;
                end else begin
                    r_o_axi_s_keep <= 4'b1111;
                end
            end else if(r_sof_mark == 4'b0100) begin
                if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1000;
                end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1100;
                end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1110;
                end else if(r_eof_mark == 4'b1000 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1111;
                end else begin
                    r_o_axi_s_keep <= 4'b1111;
                end
            end else if(r_sof_mark == 4'b1000) begin
                if(r_eof_mark == 4'b0001 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b0000;
                end else if(r_eof_mark == 4'b0010 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1000;
                end else if(r_eof_mark == 4'b0100 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1100;
                end else if(r_eof_mark == 4'b1000 && r_eof_check == 1'b1) begin
                    r_o_axi_s_keep <= 4'b1110;
                end else begin
                    r_o_axi_s_keep <= 4'b1111;
                end
            end
        end else begin
            r_o_axi_s_keep <= 4'b0000;
        end
    end

 

GT PHY到万兆网:万兆网MAC层的CRC处理

千兆网的CRC是8d32的:http://outputlogic.com/?page_id=321

但是如果选取了万兆网的32用户位宽,需要使用32d32,并且带掩码的CRC运算;

例如:

1.传输五个字节D0-D4;

2.D0-D3输入CRC模块进行校验;

3.D4就不能直接输入计算了,需要结合掩码完成;

发送数据所需要的数据流组成

同步码+SOT+DATA+EOF+LFSR
K28,5:1011 1100 (BC)
SOT:K27.7:8b/10B编码规定;111 11011(FB)
EOF:K29.7:111 11101(FD)

空闲:K23.7:111 10111(F7)并不用得到这个,而是直接使用LFSR;
同步码:一般需要多组同步码,才能保障稳定;
EMI问题:处于空闲状态的时候,如果一直在发送数值,会引起严重的尖峰问题,从而带来巨大的电磁辐射;
所以在空闲的时候,需要发送LFSP(伪随机码)序列,这是一种频谱近似于白噪声的序列,所以辐射较小,产生EMI问题的可能性很小。

 

 

 

posted @ 2024-07-22 20:28  NoNounknow  阅读(63)  评论(0编辑  收藏  举报