GTX_check 模块代码学习

GTX CHECK学习

全部的例程

check模块的全部代码如下:

///////////////////////////////////////////////////////////////////////////////
//   ____  ____
//  /   /\/   /
// /___/  \  /    Vendor: Xilinx
// \   \   \/     Version : 3.6
//  \   \         Application : 7 Series FPGAs Transceivers Wizard
//  /   /         Filename : ber_gt_frame_check.v
// /___/   /\
// \   \  /  \
//  \___\/\___\
//
//
// Module BER_GT_FRAME_CHECK
// Generated by Xilinx 7 Series FPGAs Transceivers Wizard
//
//
// (c) Copyright 2010-2012 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.


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

//***********************************Entity Declaration************************
(* DowngradeIPIdentifiedWarnings="yes" *)
module BER_GT_FRAME_CHECK #
(
    // parameter to set the number of words in the BRAM
    parameter   RX_DATA_WIDTH            =  64,
    parameter   RXCTRL_WIDTH             =  2,
    parameter   WORDS_IN_BRAM            =  512,
    parameter   CHANBOND_SEQ_LEN         =  1,
    parameter   COMMA_DOUBLE             =  16'hf628,
    parameter   START_OF_PACKET_CHAR     =  64'h00000000000000fb
)                      
(
    // User Interface
    input  wire [(RX_DATA_WIDTH-1):0] RX_DATA_IN,
    input  wire [(RXCTRL_WIDTH-1):0] RXCTRL_IN,

    output reg          RXENPCOMMADET_OUT,
    output reg          RXENMCOMMADET_OUT,
    output reg          RX_ENCHAN_SYNC_OUT,
    input  wire         RX_CHANBOND_SEQ_IN,

    // Control Interface
    input  wire         INC_IN,
    output wire         INC_OUT,
    output wire         PATTERN_MATCHB_OUT,
    input  wire         RESET_ON_ERROR_IN,


    // Error Monitoring
    output wire [7:0]   ERROR_COUNT_OUT,

    // Track Data
    output wire         TRACK_DATA_OUT,

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


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

reg             reset_on_error_in_r;
reg             reset_on_error_in_r2;
(* ASYNC_REG = "TRUE" *) (* keep = "true" *)reg             system_reset_r;
(* ASYNC_REG = "TRUE" *) (* keep = "true" *)reg             system_reset_r2;

reg             begin_r;
reg             data_error_detected_r;
reg     [8:0]   error_count_r;
reg             error_detected_r;
reg     [9:0]   read_counter_i;

    reg     [79:0] rom [0:511];

    reg     [(RX_DATA_WIDTH-1):0] rx_data_r;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r_track;

reg             start_of_packet_detected_r;
reg             track_data_r;
reg             track_data_r2;
reg             track_data_r3;
reg     [79:0]  rx_data_ram_r;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r2;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r3;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r4;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r5;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r6;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r2;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r3;

reg             rx_chanbond_seq_r;
reg             rx_chanbond_seq_r2;
reg             rx_chanbond_seq_r3;


    reg     [1:0]   sel;
//*********************************Wire Declarations***************************

    wire    [(RX_DATA_WIDTH-1):0] bram_data_r;
wire            error_detected_c;
wire            next_begin_c;
wire            next_data_error_detected_c;
wire            next_track_data_c;
wire            start_of_packet_detected_c;
wire            chanbondseq_in_data;
wire            input_to_chanbond_data_i;
wire            input_to_chanbond_reg_i;
wire    [(CHANBOND_SEQ_LEN-1):0]  rx_chanbond_reg;
    wire    [(RX_DATA_WIDTH-1):0]  rx_data_aligned;
wire            rx_data_has_start_char_c;
wire            tied_to_ground_i;
wire    [31:0]  tied_to_ground_vec_i;
wire            tied_to_vcc_i;

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

    //_______________________  Static signal Assigments _______________________

    assign tied_to_ground_i             = 1'b0;
    assign tied_to_ground_vec_i         = 32'h0000;
    assign tied_to_vcc_i                = 1'b1;

    //___________ synchronizing the async reset for ease of timing simulation ________
    always@(posedge USER_CLK)
      begin
       system_reset_r <= `DLY SYSTEM_RESET;
       system_reset_r2 <= `DLY system_reset_r;
     end
    always@(posedge USER_CLK)
      begin
       reset_on_error_in_r <= `DLY RESET_ON_ERROR_IN;
       reset_on_error_in_r2 <= `DLY reset_on_error_in_r;
     end

    //______________________ Register RXDATA once to ease timing ______________

    always @(posedge USER_CLK)
    begin
        rx_data_r  <= `DLY    RX_DATA_IN;
        rx_data_r2 <= `DLY    rx_data_r;

    end

    always @(posedge USER_CLK)
    begin
        rxctrl_r  <= `DLY    RXCTRL_IN;
    end

    //________________________________ State machine __________________________

    // State registers
    always @(posedge USER_CLK)
        if(system_reset_r2)
            {begin_r,track_data_r,data_error_detected_r}  <=  `DLY    3'b100;
        else
        begin
            begin_r                <=  `DLY    next_begin_c;
            track_data_r           <=  `DLY    next_track_data_c;
            data_error_detected_r  <=  `DLY    next_data_error_detected_c;
        end

    // Next state logic
    assign  next_begin_c                =   (begin_r && !start_of_packet_detected_r)
                                            || data_error_detected_r ;

    assign  next_track_data_c           =   (begin_r && start_of_packet_detected_r)
                                            || (track_data_r && !error_detected_r);

    assign  next_data_error_detected_c  =   (track_data_r && error_detected_r);                         

    assign  start_of_packet_detected_c  =   rx_data_has_start_char_c;

    always @(posedge USER_CLK)
        start_of_packet_detected_r    <=   `DLY  start_of_packet_detected_c;

    // Registering for timing
    always @(posedge USER_CLK)
        track_data_r2    <=   `DLY  track_data_r;

    always @(posedge USER_CLK)
        track_data_r3    <=   `DLY  track_data_r2;

    //______________________________ Capture incoming data ____________________

    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/2 - 1):0],rx_data_r2[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2]};
            end
        else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end

    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)
        begin
            rx_data_r4      <=  `DLY   'h0;
            rx_data_r5      <=  `DLY   'h0;
            rx_data_r6      <=  `DLY   'h0;
            rx_data_r_track <=  `DLY   'h0;
        end
        else
        begin
            rx_data_r4      <=  `DLY    rx_data_r3;
            rx_data_r5      <=  `DLY    rx_data_r4;
            rx_data_r6      <=  `DLY    rx_data_r5;
            rx_data_r_track <=  `DLY    rx_data_r6;
        end
    end

    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)
        begin
            rxctrl_r2      <=  `DLY   'h0;
            rxctrl_r3      <=  `DLY   'h0;
        end
        else
        begin
            rxctrl_r2      <=  `DLY   rxctrl_r;
            rxctrl_r3      <=  `DLY   rxctrl_r2;
        end
    end
    assign rx_data_aligned = rx_data_r3;

    //___________________________ Code for Channel bonding ____________________
    // code to prevent checking of clock correction sequences for the start of packet char
    always @(posedge USER_CLK)
    begin
        rx_chanbond_seq_r  <=  `DLY    RX_CHANBOND_SEQ_IN;
        rx_chanbond_seq_r2 <=  `DLY    rx_chanbond_seq_r;
        rx_chanbond_seq_r3 <=  `DLY    rx_chanbond_seq_r2;
    end

    assign input_to_chanbond_reg_i  = rx_chanbond_seq_r2;
    assign input_to_chanbond_data_i = tied_to_ground_i;





    // In 2 Byte scenario, when align_comma_word=1, Comma can appear on any of the two bytes
    // The comma is moved to the lower byte so that error checking can start
    always @(posedge USER_CLK)
    begin
        if(reset_on_error_in_r2 || system_reset_r2)    sel <= 2'b00;
        else if (begin_r && !rx_chanbond_seq_r)
        begin
            // if Comma appears on BYTE0 ..
            if((rx_data_r[(RX_DATA_WIDTH/2 - 1):0] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[0])
                sel <= 2'b00;
            // if Comma appears on BYTE1 ..      
            else if((rx_data_r[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[1])
            begin
                sel <= 2'b01;
            end
        end
    end

    //___________________________ Code for Channel bonding ____________________
    // code to prevent checking of clock correction sequences for the start of packet char
    genvar i;
    generate
    for (i=0;i<CHANBOND_SEQ_LEN ;i=i+1)
    begin:register_chan_seq
    if(i==0)
        FD rx_chanbond_reg_0  ( .Q (rx_chanbond_reg[i]), .D (input_to_chanbond_reg_i), .C(USER_CLK));
    else
        FD rx_chanbond_reg_i  ( .Q (rx_chanbond_reg[i]), .D (rx_chanbond_reg[i-1]), .C(USER_CLK));
    end
    endgenerate

    assign chanbondseq_in_data = |rx_chanbond_reg || input_to_chanbond_data_i;


    assign rx_data_has_start_char_c = (rx_data_aligned[7:0] == START_OF_PACKET_CHAR[7:0]) && !chanbondseq_in_data && (|rxctrl_r3);


    //_____________________________ Assign output ports _______________________
    //assign TRACK_DATA_OUT = track_data_r;


    // Drive the enpcommaalign port of the gt for alignment
    always @(posedge USER_CLK)
        if(system_reset_r2)  RXENPCOMMADET_OUT   <=  `DLY    1'b0;
        else              RXENPCOMMADET_OUT   <=  `DLY    1'b1;

    // Drive the enmcommaalign port of the gt for alignment
    always @(posedge USER_CLK)
        if(system_reset_r2)  RXENMCOMMADET_OUT   <=  `DLY    1'b0;
        else              RXENMCOMMADET_OUT   <=  `DLY    1'b1;

    assign INC_OUT =  start_of_packet_detected_c;

    assign PATTERN_MATCHB_OUT =  data_error_detected_r;

    // Drive the enchansync port of the mgt for channel bonding
    always @(posedge USER_CLK)
        if(system_reset_r2)  RX_ENCHAN_SYNC_OUT   <=  `DLY    1'b0;
        else              RX_ENCHAN_SYNC_OUT   <=  `DLY    1'b1;

    //___________________________ Check incoming data for errors ______________

    //An error is detected when data read for the BRAM does not match the incoming data
    assign  error_detected_c    =  track_data_r3 && (rx_data_r_track != bram_data_r);

    //We register the error_detected signal for use with the error counter logic
    always @(posedge USER_CLK)
        if(!track_data_r)
            error_detected_r    <=  `DLY    1'b0;
        else
            error_detected_r    <=  `DLY    error_detected_c;

    //We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
    //errors we did not directly observe.
    always @(posedge USER_CLK)
        if(system_reset_r2)
            error_count_r       <=  `DLY    9'd0;
        else if(error_detected_r)
            error_count_r       <=  `DLY    error_count_r + 1;

    //Here we connect the lower 8 bits of the count (the MSbit is used only to check when the counter reaches
    //max value) to the module output
    assign  ERROR_COUNT_OUT =   error_count_r[7:0];

  localparam ST_LINK_DOWN = 1'b0;
  localparam ST_LINK_UP   = 1'b1;
  reg        sm_link      = ST_LINK_DOWN;
  reg [6:0]  link_ctr     = 7'd0;

  always @(posedge USER_CLK) begin
        if(!track_data_r)
              sm_link  <= ST_LINK_DOWN;
        else 
    case (sm_link)
      // The link is considered to be down when the link counter initially has a value less than 67. When the link is
      // down, the counter is incremented on each cycle where all PRBS bits match, but reset whenever any PRBS mismatch
      // occurs. When the link counter reaches 67, transition to the link up state.
      ST_LINK_DOWN: begin
        if (error_detected_r !== 1'b0) begin
          link_ctr <= 7'd0;
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
          else
            sm_link <= ST_LINK_UP;
        end
      end

      // When the link is up, the link counter is decreased by 34 whenever any PRBS mismatch occurs, but is increased by
      // only 1 on each cycle where all PRBS bits match, up to its saturation point of 67. If the link counter reaches
      // 0 (including rollover protection), transition to the link down state.
      ST_LINK_UP: begin
        if (error_detected_r !== 1'b0) begin
          if (link_ctr > 7'd33) begin
            link_ctr <= link_ctr - 7'd34;
            if (link_ctr == 7'd34)
              sm_link  <= ST_LINK_DOWN;
          end
          else begin
            link_ctr <= 7'd0;
            sm_link  <= ST_LINK_DOWN;
          end
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
        end
      end
    endcase
  end

assign TRACK_DATA_OUT = sm_link;
    //____________________________ Counter to read from BRAM __________________________
    always @(posedge USER_CLK)
        if(system_reset_r2 ||  (read_counter_i == (WORDS_IN_BRAM-1)))
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else if (start_of_packet_detected_r && !track_data_r)
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else
        begin
            read_counter_i  <=  `DLY    read_counter_i + 10'd1;
        end

    //________________________________ BRAM Inference Logic _____________________________

//Array slice from dat file to compare against receive data
generate
if(RX_DATA_WIDTH==80)
begin : datapath_80
    assign bram_data_r      = rx_data_ram_r[(RX_DATA_WIDTH-1):0];
end
else
begin : datapath_16_20_32_40_64
    assign bram_data_r = rx_data_ram_r[(16+RX_DATA_WIDTH-1):16];
end
endgenerate

    initial
    begin
           $readmemh("gt_rom_init_rx.dat",rom,0,511);
    end

    always @(posedge USER_CLK)
           rx_data_ram_r <= `DLY  rom[read_counter_i];


endmodule     

check 模块的数据输入

顶层模块调用的代码

gtx_ber_GT_FRAME_CHECK #
    (
.RX_DATA_WIDTH ( 16 ),
.RXCTRL_WIDTH ( 2 ),
.COMMA_DOUBLE ( 16'h02bc ),
        .WORDS_IN_BRAM(EXAMPLE_WORDS_IN_BRAM),
.START_OF_PACKET_CHAR ( 16'h02bc )
    )
    gt0_frame_check
    (
        // GT Interface
        .RX_DATA_IN                     (gt0_rxdata_i),
        .RXCTRL_IN                      (gt0_rxcharisk_i),
        // 未用,高电平有效信号,可实现字节边界对齐检测到plus COMMA模式时进行处理。output  长1
        .RXENMCOMMADET_OUT              (gt0_rxmcommaalignen_i),
         // 未用,高电平有效信号,可实现字节边界对齐检测到minus COMMA模式时进行处理。 output 长1
        .RXENPCOMMADET_OUT              (gt0_rxpcommaalignen_i),
        // 未用,驱动mgt的enchansync端口进行通道绑定output 长1
        .RX_ENCHAN_SYNC_OUT             ( ),
        // 输入通道绑定序列,不绑定时为0    input
        .RX_CHANBOND_SEQ_IN             (tied_to_ground_i),
        // Control Interface
        // 未用  input   长期是0
        .INC_IN                         (gt0_inc_in_i),
        // 非独立的收发测试时输出已开始进行COMMA检测,指示发送端地址递增 output  //每一帧有一个高电平
        .INC_OUT                        (gt0_inc_out_i),
        // COMMA不匹配    output  和ROM核不匹配的时候 延时两个周期置高电平
        .PATTERN_MATCHB_OUT             (gt0_matchn_i),
        // 通过将PATTERN_MATCHB_OUT 输出给外部,由此产生出错后的复位   input
        //assign gt0_frame_check_reset_i =gt0_matchn_i;  也就是错误复位
        .RESET_ON_ERROR_IN              (gt0_frame_check_reset_i),
        // System Interface
        .USER_CLK                       (gt0_rxusrclk2_i),
        .SYSTEM_RESET                   (gt0_rx_system_reset_c),//全局复位  in
        .ERROR_COUNT_OUT                (gt0_error_count_i), //错误的个数 out
        .TRACK_DATA_OUT                 (gt0_track_data_i) //错了变0 第二帧重新变1
    );

输入输出的电平情况

image-20220516143537224

RXENPCOMMADET_OUT、RXENMCOMMADET_OUT、RX_ENCHAN_SYNC_OUT ——一直是高电平
RX_CHANBOND_SEQ_IN —— 一直是低电平 长0

PATTERN_MATCHB_OUT、RESET_ON_ERROR_IN ———— 检测到数据出现错误时候是高电平 没有错误是低电平

rx_data_r_track <= `DLY rx_data_r6;

基本的知识

首先进行了参数的重新定义

  • 把RX_DATA_WIDTH变成了16位
  • 把COMMA_DOUBLE对齐信号变成了16'h02bc
  • 把START_OF_PACKET_CHAR 信号也变成16'h02bc

重要的数据线

  1. RX_DATA_IN ----------16位
  2. RXCTRL_IN ----------2位

时钟与复位

gt0_rxusrclk2_i 时钟

gt0_rx_system_reset_c ——SYSTEM_RESET 复位

`define DLY #1 定义了1ns的延迟,防止时序问题

有用的信号线

数据线

  1. error_detected_c // error_detected_r ——-错误拉高信号 打了一拍(不知道为啥)
  2. track_data_r3 ---输出有效 一直是高电平
  3. bram_data_r ---可变寄存器 本例程中是16位
  4. rx_data_r ——RX_DATA_IN延时出来的 延时几个数字就是几
  5. rxctrl_r ——RXCTRL_IN延时出来的 延时几个数字就是几
  6. rx_data_r_track -------- rx_data_r6也就是延迟了6拍的rxdata // rx_data_r_track <= `DLY rx_data_r6;
  7. rx_data_aligned ——就是rx_data_r3 代码: assign rx_data_aligned = rx_data_r3; 这也就可以对齐了

选择控制线

基本的控制线

  1. system_reset_r2 全局使用的复位信号 SYSTEM_RESET 延时两拍
  2. reset_on_error_in_r2 错误复位信号 RESET_ON_ERROR_IN 延时两拍

状态机控制信号线

  1. begin_r 启动请求信号,在该信号复位为高后且未收到已开始数据检测的指示时保持为高,或数据出错时
  2. track_data_r // 产生检测数据跟踪请求,在启动为高后且收到开始检测到有效数据的指示时保持为高,或者已启动数据跟踪且未出错时
  3. data_error_detected_r // 已启动跟踪,且检测到了错误
  4. start_of_packet_detected_r // 已开始检测到有效数据 //02bc对齐的时候 是高电平 也就是每过一帧数据 又一次升高的情况 可以用来做整体的cnt的使能信号 start_of_packet_detected_c延时一拍得到的
  5. error_detected_c //assign error_detected_c = track_data_r3 && (rx_data_r_track != bram_data_r);
  6. rx_data_has_start_char_c rx_data_r3 =bc 变成高电平
  7. start_of_packet_detected_c // assign start_of_packet_detected_c = rx_data_has_start_char_c;

image-20220516150942828

    always @(posedge USER_CLK)
        if(system_reset_r2)
            {begin_r,track_data_r,data_error_detected_r}  <=  `DLY    3'b100;
        else
        begin
            begin_r                <=  `DLY    next_begin_c;
            track_data_r           <=  `DLY    next_track_data_c;
            data_error_detected_r  <=  `DLY    next_data_error_detected_c;
        end

    // Next state logic
    assign  next_begin_c                =   (begin_r && !start_of_packet_detected_r)
                                            || data_error_detected_r ;

    assign  next_track_data_c           =   (begin_r && start_of_packet_detected_r)
                                            || (track_data_r && !error_detected_r);

    assign  next_data_error_detected_c  =   (track_data_r && error_detected_r);                       

    assign  start_of_packet_detected_c  =   rx_data_has_start_char_c;

    always @(posedge USER_CLK)
        start_of_packet_detected_r    <=   `DLY  start_of_packet_detected_c;

关键的步骤

判断数值是否正确的代码

359行:

assign  error_detected_c    =  track_data_r3 && (rx_data_r_track != bram_data_r);

代码解释:

当为BRAM读取的数据与传入的数据不匹配时,将检测到错误。

自己写的误码率计算在362行

bram_data_r的由来

assign bram_data_r = rx_data_ram_r[(16+RX_DATA_WIDTH-1):16]

rx_data_ram_r 是80位的数据

所以bram_data_r 就是第16位到第32位数据 也就是如下图所示的数据

image-20220513163258571

SEL信号的情况

// In 2 Byte scenario, when align_comma_word=1, Comma can appear on any of the two bytes
// The comma is moved to the lower byte so that error checking can start

//在2字节场景中,当align_comma_word=1时,逗号可以出现在任何两个字节上

//逗号被移到低字节,以便开始错误检查

always @(posedge USER_CLK)
    begin
        if(reset_on_error_in_r2 || system_reset_r2)    sel <= 2'b00;
        else if (begin_r && !rx_chanbond_seq_r)
        begin
            // if Comma appears on BYTE0 ..
            if((rx_data_r[(RX_DATA_WIDTH/2 - 1):0] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[0])
                sel <= 2'b00;
            // if Comma appears on BYTE1 ..  
            else if((rx_data_r[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[1])
            begin
                sel <= 2'b01;
            end
        end
    end

rx_chanbond_seq_r 永远是0

START_OF_PACKET_CHAR 是02bc

RX_DATA_WIDTH 是16

rxctrl_r 是charisk信号

chanbondseq_in_data 长0

低字节 也就是数据正确的时候 sel 为0

高字节 也就是数据错误的时候 sel 为1

链路的状态机

文件程序如下:

DOWN状态:

当链路计数器的初始值小于67时,链路被认为是断开的。当链路down时,计数器在所有PRBS位匹配的每一个周期递增,但当PRBS不匹配发生时复位。当链路计数达到67时(中间错一次就计数清零),切换到up状态。

UP状态:

当链路连通时,当出现PRBS失配时,链路计数器减少34,但当所有PRBS位都匹配时,链路计数器在每个周期只增加1,直到饱和点67。当链路计数器达到0(包括翻转保护)时,切换到链路down状态。

状态机转换图:

image-20220516160142294

always @(posedge USER_CLK) begin
        if(!track_data_r)
              sm_link  <= ST_LINK_DOWN;
        else    
    case (sm_link)
      // The link is considered to be down when the link counter initially has a value less than 67. When the link is
      // down, the counter is incremented on each cycle where all PRBS bits match, but reset whenever any PRBS mismatch
      // occurs. When the link counter reaches 67, transition to the link up state.
      ST_LINK_DOWN: begin
        if (error_detected_r !== 1'b0) begin
          link_ctr <= 7'd0;
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
          else
            sm_link <= ST_LINK_UP;
        end
      end

      // When the link is up, the link counter is decreased by 34 whenever any PRBS mismatch occurs, but is increased by
      // only 1 on each cycle where all PRBS bits match, up to its saturation point of 67. If the link counter reaches
      // 0 (including rollover protection), transition to the link down state.
      ST_LINK_UP: begin
        if (error_detected_r !== 1'b0) begin
          if (link_ctr > 7'd33) begin
            link_ctr <= link_ctr - 7'd34;
            if (link_ctr == 7'd34)
              sm_link  <= ST_LINK_DOWN;
          end
          else begin
            link_ctr <= 7'd0;
            sm_link  <= ST_LINK_DOWN;
          end
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
        end
      end
    endcase
  end

assign TRACK_DATA_OUT = sm_link;

状态机的作用:

TRACK_DATA_OUT ———输出链路有效信号 有效时候该信号为高电平

目前的问题

这个通道选择的模块没看懂

/___________________________ Code for Channel bonding ____________________
    // code to prevent checking of clock correction sequences for the start of packet char
    genvar i;
    generate
    for (i=0;i<CHANBOND_SEQ_LEN ;i=i+1)
    begin:register_chan_seq
    if(i==0)
        FD rx_chanbond_reg_0  ( .Q (rx_chanbond_reg[i]), .D (input_to_chanbond_reg_i), .C(USER_CLK));
    else
        FD rx_chanbond_reg_i  ( .Q (rx_chanbond_reg[i]), .D (rx_chanbond_reg[i-1]), .C(USER_CLK));
    end
    endgenerate

    assign chanbondseq_in_data = |rx_chanbond_reg || input_to_chanbond_data_i;


    assign rx_data_has_start_char_c = (rx_data_aligned[7:0] == START_OF_PACKET_CHAR[7:0]) && !chanbondseq_in_data && (|rxctrl_r3);

数据对齐模块

   always @(posedge USER_CLK)
    begin
        if(system_reset_r2)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/2 - 1):0],rx_data_r2[(RX_DATA_WIDTH-1):RX_DATA_WIDTH/2]};
            end
        else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end

rx_data_r3 这个数据就是对齐后的数据

自己修改的代码模块

16位同时检测,计算错误的比特点

把原来的代码16位一检测改成 每一位对应检测

//自己的误码率计算
    wire error_detected_c0;
    wire error_detected_c1;
    wire error_detected_c2;
    wire error_detected_c3;
    wire error_detected_c4;
    wire error_detected_c5;
    wire error_detected_c6;
    wire error_detected_c7;
    wire error_detected_c8;
    wire error_detected_c9;
    wire error_detected_c10;
    wire error_detected_c11;
    wire error_detected_c12;
    wire error_detected_c13;
    wire error_detected_c14;
    wire error_detected_c15;
    reg error_detected_r0;
    reg error_detected_r1;
    reg error_detected_r2;
    reg error_detected_r3;
    reg error_detected_r4;
    reg error_detected_r5;
    reg error_detected_r6;
    reg error_detected_r7;
    reg error_detected_r8;
    reg error_detected_r9;
    reg error_detected_r10;
    reg error_detected_r11;
    reg error_detected_r12;
    reg error_detected_r13;
    reg error_detected_r14;
    reg error_detected_r15;
    assign  error_detected_c0    =  track_data_r3 && (rx_data_r_track[0] != bram_data_r[0]);
    assign  error_detected_c1    =  track_data_r3 && (rx_data_r_track[1] != bram_data_r[1]);
    assign  error_detected_c2    =  track_data_r3 && (rx_data_r_track[2] != bram_data_r[2]);
    assign  error_detected_c3    =  track_data_r3 && (rx_data_r_track[3] != bram_data_r[3]);
    assign  error_detected_c4    =  track_data_r3 && (rx_data_r_track[4] != bram_data_r[4]);
    assign  error_detected_c5    =  track_data_r3 && (rx_data_r_track[5] != bram_data_r[5]);
    assign  error_detected_c6    =  track_data_r3 && (rx_data_r_track[6] != bram_data_r[6]);
    assign  error_detected_c7    =  track_data_r3 && (rx_data_r_track[7] != bram_data_r[7]);
    assign  error_detected_c8    =  track_data_r3 && (rx_data_r_track[8] != bram_data_r[8]);
    assign  error_detected_c9    =  track_data_r3 && (rx_data_r_track[9] != bram_data_r[9]);
    assign  error_detected_c10    =  track_data_r3 && (rx_data_r_track[10] != bram_data_r[10]);
    assign  error_detected_c11    =  track_data_r3 && (rx_data_r_track[11] != bram_data_r[11]);
    assign  error_detected_c12    =  track_data_r3 && (rx_data_r_track[12] != bram_data_r[12]);
    assign  error_detected_c13    =  track_data_r3 && (rx_data_r_track[13] != bram_data_r[13]);
    assign  error_detected_c14    =  track_data_r3 && (rx_data_r_track[14] != bram_data_r[14]);
    assign  error_detected_c15    =  track_data_r3 && (rx_data_r_track[15] != bram_data_r[15]);

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r0    <=  `DLY    1'b0;
            else
                error_detected_r0    <=  `DLY    error_detected_c0;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r1    <=  `DLY    1'b0;
            else
                error_detected_r1    <=  `DLY    error_detected_c1;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r2    <=  `DLY    1'b0;
             else
                error_detected_r2    <=  `DLY    error_detected_c2;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r3    <=  `DLY    1'b0;
             else
                error_detected_r3    <=  `DLY    error_detected_c3;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r4    <=  `DLY    1'b0;
             else
                error_detected_r4    <=  `DLY    error_detected_c4;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r5    <=  `DLY    1'b0;
             else
                error_detected_r5    <=  `DLY    error_detected_c5;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r6    <=  `DLY    1'b0;
             else
                error_detected_r6    <=  `DLY    error_detected_c6;



    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r7    <=  `DLY    1'b0;
             else
                error_detected_r7    <=  `DLY    error_detected_c7;



    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r8    <=  `DLY    1'b0;
             else
                error_detected_r8    <=  `DLY    error_detected_c8;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r9    <=  `DLY    1'b0;
             else
                error_detected_r9    <=  `DLY    error_detected_c9;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r10    <=  `DLY    1'b0;
             else
                error_detected_r10    <=  `DLY    error_detected_c10;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r11    <=  `DLY    1'b0;
             else
                error_detected_r11    <=  `DLY    error_detected_c11;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r12    <=  `DLY    1'b0;
             else
                error_detected_r12    <=  `DLY    error_detected_c12;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r12    <=  `DLY    1'b0;
             else
                error_detected_r12    <=  `DLY    error_detected_c12;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r13    <=  `DLY    1'b0;
             else
                error_detected_r13    <=  `DLY    error_detected_c13;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r14    <=  `DLY    1'b0;
             else
                error_detected_r14    <=  `DLY    error_detected_c14;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r15    <=  `DLY    1'b0;
             else
                error_detected_r15    <=  `DLY    error_detected_c15;

 //误码率控制信号      
 reg [WIDTH_ERR-1 : 0]  error_count_r0;
 reg [WIDTH_ERR-1 : 0]  error_count_r1;
 reg [WIDTH_ERR-1 : 0]  error_count_r2;
 reg [WIDTH_ERR-1 : 0]  error_count_r3;
 reg [WIDTH_ERR-1 : 0]  error_count_r4;
 reg [WIDTH_ERR-1 : 0]  error_count_r5;
 reg [WIDTH_ERR-1 : 0]  error_count_r6;
 reg [WIDTH_ERR-1 : 0]  error_count_r7;
 reg [WIDTH_ERR-1 : 0]  error_count_r8;
 reg [WIDTH_ERR-1 : 0]  error_count_r9;
 reg [WIDTH_ERR-1 : 0]  error_count_r10;
 reg [WIDTH_ERR-1 : 0]  error_count_r11;
 reg [WIDTH_ERR-1 : 0]  error_count_r12;
 reg [WIDTH_ERR-1 : 0]  error_count_r13;
 reg [WIDTH_ERR-1 : 0]  error_count_r14;
 reg [WIDTH_ERR-1 : 0]  error_count_r15;       

//BER 的16位的计算
  always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r0       <=  `DLY    0;
else if(error_detected_r0)
   error_count_r0       <=  `DLY    error_count_r0 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r1       <=  `DLY    0;
else if(error_detected_r1)
   error_count_r1       <=  `DLY    error_count_r1 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r2       <=  `DLY    0;
else if(error_detected_r2)
   error_count_r2       <=  `DLY    error_count_r2 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r3       <=  `DLY    0;
else if(error_detected_r3)
   error_count_r3       <=  `DLY    error_count_r3 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r4       <=  `DLY    0;
else if(error_detected_r4)
   error_count_r4       <=  `DLY    error_count_r4 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r5       <=  `DLY    0;
else if(error_detected_r5)
   error_count_r5       <=  `DLY    error_count_r5 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r6       <=  `DLY    0;
else if(error_detected_r6)
   error_count_r6       <=  `DLY    error_count_r6 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r7       <=  `DLY    0;
else if(error_detected_r7)
   error_count_r7       <=  `DLY    error_count_r7 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r8       <=  `DLY    0;
else if(error_detected_r8)
   error_count_r8       <=  `DLY    error_count_r8 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r9       <=  `DLY    0;
else if(error_detected_r9)
   error_count_r9       <=  `DLY    error_count_r9 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r10       <=  `DLY    0;
else if(error_detected_r10)
   error_count_r10       <=  `DLY    error_count_r10 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r11       <=  `DLY    0;
else if(error_detected_r11)
   error_count_r11       <=  `DLY    error_count_r11 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r12       <=  `DLY    0;
else if(error_detected_r12)
   error_count_r12       <=  `DLY    error_count_r12 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r13       <=  `DLY    0;
else if(error_detected_r13)
   error_count_r13       <=  `DLY    error_count_r13 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r14       <=  `DLY    0;
else if(error_detected_r14)
   error_count_r14       <=  `DLY    error_count_r14 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r15       <=  `DLY    0;
else if(error_detected_r15)
   error_count_r15       <=  `DLY    error_count_r15 + 1;

 //如果时序有问题  就在中间插入寄存器
wire [35:0]  error_num;
assign error_num =  error_count_r0 + error_count_r1 + error_count_r2 + error_count_r3 + error_count_r4 + error_count_r5 + error_count_r6 + error_count_r7 + error_count_r8 + error_count_r9 + error_count_r10 + error_count_r11 + error_count_r12 + error_count_r13 + error_count_r14 + error_count_r15 ;

计算一共出现了多少帧

利用rx_data_r_track 这个信号,统计一共出现了多少02bc 就可以刚好算出 整体的帧的数值

结果验证

02BC 0010 1011 1100

0304 0011 0000 0010

0504 0101 0000 0100

0100 0000 0001 0000 0000

bc00 1011 1100 0000 0000

几个重要的节点

计算误码率的节点

always @(posedge USER_CLK)
    if(!track_data_r) 
        error_detected_r    <=  `DLY    1'b0;
    else
        error_detected_r    <=  `DLY    error_detected_c; 

//We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
//errors we did not directly observe.
always @(posedge USER_CLK)
    if(system_reset_r2)
        error_count_r       <=  `DLY    9'd0;
    else if(error_detected_r)
        error_count_r       <=  `DLY    error_count_r + 1;  



assign  error_detected_c    =  track_data_r3 && (rx_data_r_track != bram_data_r);

读取RAM的节点

    always @(posedge USER_CLK)
        if(system_reset_r2 ||  (read_counter_i == (WORDS_IN_BRAM-1)))
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else if (start_of_packet_detected_r && !track_data_r) //sel 延时6拍子   延时之后是0 之前是1  也就是&&sel
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else
        begin
            read_counter_i  <=  `DLY    read_counter_i + 10'd1;
        end

data_error_detected_r

最重要的几条线:

  1. sel
  2. track_data_r
  3. error_detected_c
  4. error_detected_r

需要修改的地方

重要发现:

track_data_r 要长1就好办了

自己的修改

自己写一个计数器:start_of_packet_detected_c 是高电平时加一,然后最大是3

所以cnt ==3是真

第一个地方:434行 保证对齐之后 不再清零

else if (start_of_packet_detected_r && !track_data_r)
    //sel 延时6拍子   延时之后是0 之前是1  也就是&&sel
begin
    read_counter_i   <=  `DLY    10'd0;
end

第二个地方:214行

    assign  next_track_data_c           =   (begin_r && start_of_packet_detected_r)
                                            || (track_data_r && !error_detected_r);

后面||上!sel 让它变成长1

自己修改的代码

上面的改动

777行:else if (start_of_packet_detected_r && !track_data_r&&(cnt!=3))

557行: assign next_track_data_c = (begin_r && start_of_packet_detected_r)
|| (track_data_r && !error_detected_r)||(cnt==3);

其它的改动:

//参数
localparam  WIDTH_ERR = 31;

//三个模块
//_______________________aligned_cnt_______________________

//buff 3 frame and keep its state
wire add_cnt;
wire end_cnt;
reg [2:0] cnt;
always @(posedge USER_CLK)begin
     if(system_reset_r2)begin
         cnt <= 0;
     end
     else if(add_cnt)begin
         if(end_cnt)
             cnt <= 3;
         else
             cnt <= cnt + 1;
     end
end

 assign add_cnt = start_of_packet_detected_c;      
 assign end_cnt = add_cnt && cnt==4-1 ;  



   //_______________________frame_num cnt_______________________

   wire add_cnt1;
   wire end_cnt1;
   reg [31:0] frame_num;
   always @(posedge USER_CLK)begin
       if(system_reset_r2)begin
           frame_num <= 0;
       end
       else if(add_cnt1)begin
           if(end_cnt1)
               frame_num <= 0;
           else
               frame_num <= frame_num + 1;
       end
   end

   assign add_cnt1 = start_of_packet_detected_c;      
   assign end_cnt1 = add_cnt1 && frame_num==32'hffffffff ;  


//_______________________  error_num  one  bit check  _______________________  
//自己的误码率计算
    wire error_detected_c0;
    wire error_detected_c1;
    wire error_detected_c2;
    wire error_detected_c3;
    wire error_detected_c4;
    wire error_detected_c5;
    wire error_detected_c6;
    wire error_detected_c7;
    wire error_detected_c8;
    wire error_detected_c9;
    wire error_detected_c10;
    wire error_detected_c11;
    wire error_detected_c12;
    wire error_detected_c13;
    wire error_detected_c14;
    wire error_detected_c15;
    reg error_detected_r0;
    reg error_detected_r1;
    reg error_detected_r2;
    reg error_detected_r3;
    reg error_detected_r4;
    reg error_detected_r5;
    reg error_detected_r6;
    reg error_detected_r7;
    reg error_detected_r8;
    reg error_detected_r9;
    reg error_detected_r10;
    reg error_detected_r11;
    reg error_detected_r12;
    reg error_detected_r13;
    reg error_detected_r14;
    reg error_detected_r15;
    assign  error_detected_c0    =  track_data_r3 && (rx_data_r_track[0] != bram_data_r[0]);
    assign  error_detected_c1    =  track_data_r3 && (rx_data_r_track[1] != bram_data_r[1]);
    assign  error_detected_c2    =  track_data_r3 && (rx_data_r_track[2] != bram_data_r[2]);
    assign  error_detected_c3    =  track_data_r3 && (rx_data_r_track[3] != bram_data_r[3]);
    assign  error_detected_c4    =  track_data_r3 && (rx_data_r_track[4] != bram_data_r[4]);
    assign  error_detected_c5    =  track_data_r3 && (rx_data_r_track[5] != bram_data_r[5]);
    assign  error_detected_c6    =  track_data_r3 && (rx_data_r_track[6] != bram_data_r[6]);
    assign  error_detected_c7    =  track_data_r3 && (rx_data_r_track[7] != bram_data_r[7]);
    assign  error_detected_c8    =  track_data_r3 && (rx_data_r_track[8] != bram_data_r[8]);
    assign  error_detected_c9    =  track_data_r3 && (rx_data_r_track[9] != bram_data_r[9]);
    assign  error_detected_c10    =  track_data_r3 && (rx_data_r_track[10] != bram_data_r[10]);
    assign  error_detected_c11    =  track_data_r3 && (rx_data_r_track[11] != bram_data_r[11]);
    assign  error_detected_c12    =  track_data_r3 && (rx_data_r_track[12] != bram_data_r[12]);
    assign  error_detected_c13    =  track_data_r3 && (rx_data_r_track[13] != bram_data_r[13]);
    assign  error_detected_c14    =  track_data_r3 && (rx_data_r_track[14] != bram_data_r[14]);
    assign  error_detected_c15    =  track_data_r3 && (rx_data_r_track[15] != bram_data_r[15]);

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r0    <=  `DLY    1'b0;
            else
                error_detected_r0    <=  `DLY    error_detected_c0;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r1    <=  `DLY    1'b0;
            else
                error_detected_r1    <=  `DLY    error_detected_c1;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r2    <=  `DLY    1'b0;
             else
                error_detected_r2    <=  `DLY    error_detected_c2;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r3    <=  `DLY    1'b0;
             else
                error_detected_r3    <=  `DLY    error_detected_c3;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r4    <=  `DLY    1'b0;
             else
                error_detected_r4    <=  `DLY    error_detected_c4;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r5    <=  `DLY    1'b0;
             else
                error_detected_r5    <=  `DLY    error_detected_c5;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r6    <=  `DLY    1'b0;
             else
                error_detected_r6    <=  `DLY    error_detected_c6;



    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r7    <=  `DLY    1'b0;
             else
                error_detected_r7    <=  `DLY    error_detected_c7;



    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r8    <=  `DLY    1'b0;
             else
                error_detected_r8    <=  `DLY    error_detected_c8;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r9    <=  `DLY    1'b0;
             else
                error_detected_r9    <=  `DLY    error_detected_c9;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r10    <=  `DLY    1'b0;
             else
                error_detected_r10    <=  `DLY    error_detected_c10;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r11    <=  `DLY    1'b0;
             else
                error_detected_r11    <=  `DLY    error_detected_c11;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r12    <=  `DLY    1'b0;
             else
                error_detected_r12    <=  `DLY    error_detected_c12;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r12    <=  `DLY    1'b0;
             else
                error_detected_r12    <=  `DLY    error_detected_c12;


    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r13    <=  `DLY    1'b0;
             else
                error_detected_r13    <=  `DLY    error_detected_c13;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r14    <=  `DLY    1'b0;
             else
                error_detected_r14    <=  `DLY    error_detected_c14;

    always @(posedge USER_CLK)
            if(!track_data_r)
                error_detected_r15    <=  `DLY    1'b0;
             else
                error_detected_r15    <=  `DLY    error_detected_c15;

 //误码率控制信号      
 reg [WIDTH_ERR-1 : 0]  error_count_r0;
 reg [WIDTH_ERR-1 : 0]  error_count_r1;
 reg [WIDTH_ERR-1 : 0]  error_count_r2;
 reg [WIDTH_ERR-1 : 0]  error_count_r3;
 reg [WIDTH_ERR-1 : 0]  error_count_r4;
 reg [WIDTH_ERR-1 : 0]  error_count_r5;
 reg [WIDTH_ERR-1 : 0]  error_count_r6;
 reg [WIDTH_ERR-1 : 0]  error_count_r7;
 reg [WIDTH_ERR-1 : 0]  error_count_r8;
 reg [WIDTH_ERR-1 : 0]  error_count_r9;
 reg [WIDTH_ERR-1 : 0]  error_count_r10;
 reg [WIDTH_ERR-1 : 0]  error_count_r11;
 reg [WIDTH_ERR-1 : 0]  error_count_r12;
 reg [WIDTH_ERR-1 : 0]  error_count_r13;
 reg [WIDTH_ERR-1 : 0]  error_count_r14;
 reg [WIDTH_ERR-1 : 0]  error_count_r15;       

//BER 的16位的计算
  always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r0       <=  `DLY    0;
else if(error_detected_r0)
   error_count_r0       <=  `DLY    error_count_r0 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r1       <=  `DLY    0;
else if(error_detected_r1)
   error_count_r1       <=  `DLY    error_count_r1 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r2       <=  `DLY    0;
else if(error_detected_r2)
   error_count_r2       <=  `DLY    error_count_r2 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r3       <=  `DLY    0;
else if(error_detected_r3)
   error_count_r3       <=  `DLY    error_count_r3 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r4       <=  `DLY    0;
else if(error_detected_r4)
   error_count_r4       <=  `DLY    error_count_r4 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r5       <=  `DLY    0;
else if(error_detected_r5)
   error_count_r5       <=  `DLY    error_count_r5 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r6       <=  `DLY    0;
else if(error_detected_r6)
   error_count_r6       <=  `DLY    error_count_r6 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r7       <=  `DLY    0;
else if(error_detected_r7)
   error_count_r7       <=  `DLY    error_count_r7 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r8       <=  `DLY    0;
else if(error_detected_r8)
   error_count_r8       <=  `DLY    error_count_r8 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r9       <=  `DLY    0;
else if(error_detected_r9)
   error_count_r9       <=  `DLY    error_count_r9 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r10       <=  `DLY    0;
else if(error_detected_r10)
   error_count_r10       <=  `DLY    error_count_r10 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r11       <=  `DLY    0;
else if(error_detected_r11)
   error_count_r11       <=  `DLY    error_count_r11 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r12       <=  `DLY    0;
else if(error_detected_r12)
   error_count_r12       <=  `DLY    error_count_r12 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r13       <=  `DLY    0;
else if(error_detected_r13)
   error_count_r13       <=  `DLY    error_count_r13 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r14       <=  `DLY    0;
else if(error_detected_r14)
   error_count_r14       <=  `DLY    error_count_r14 + 1;


always @(posedge USER_CLK)
  if(system_reset_r2)
   error_count_r15       <=  `DLY    0;
else if(error_detected_r15)
   error_count_r15       <=  `DLY    error_count_r15 + 1;

 //如果时序有问题  就在中间插入寄存器
wire [34:0]  error_num;
assign error_num =  error_count_r0 + error_count_r1 + error_count_r2 + error_count_r3 + error_count_r4 + error_count_r5 + error_count_r6 + error_count_r7 + error_count_r8 + error_count_r9 + error_count_r10 + error_count_r11 + error_count_r12 + error_count_r13 + error_count_r14 + error_count_r15 ;

测试

仿真文件

共错4行5bit

16--1bit 36--2bit 423--1bit 507-----1bit

16行 1e1d ----1e3d

36行 110 0000 0101 0605 、、、、110 0000 1111 060f

423行 0c0b ----0c1b

507行 1413 ----- 1403

总体思路

帧计数器32位 2^32^个数据,所以总比特数是 2^32^×16×16 约等于10^12^个比特

一帧错5bit ,一共是2^32^帧 约为2.1×10^10^比特,所以log~2~(2.1×10^10^) = 34.32

所以总error的位数是35位 共分为16个单个比特计数器,每一个单个比特计数器是31位。

最后的结果

由图我们可以发现 每32帧也就是16*32=512 错了6bit ,仿真测试时候是6bit的tx文件

image-20220517220221451

参考资料

(7条消息) xilinx A7 (artix 7)serdes GTP 生成的example例程注释解析_Shawge的博客-CSDN博客

///
//   ____  ____
//  /   /\/   /
// /___/  \  /    Vendor: Xilinx
// \   \   \/     Version : 3.6
//  \   \         Application : 7 Series FPGAs Transceivers Wizard
//  /   /         Filename : gtwizard_0_gt_frame_check.v
// /___/   /\
// \   \  /  \
//  \___\/\___\
//
//
// Module gtwizard_0_GT_FRAME_CHECK
// Generated by Xilinx 7 Series FPGAs Transceivers Wizard
//
//
// (c) Copyright 2010-2012 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.


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

//***********************************Entity Declaration************************
(* DowngradeIPIdentifiedWarnings="yes" *)
module gtwizard_0_GT_FRAME_CHECK #
(
    // parameter to set the number of words in the BRAM
    parameter   RX_DATA_WIDTH            =  64,
    parameter   RXCTRL_WIDTH             =  2,
    parameter   WORDS_IN_BRAM            =  512,
    parameter   CHANBOND_SEQ_LEN         =  1,
    parameter   COMMA_DOUBLE             =  16'hf628,
    parameter   START_OF_PACKET_CHAR     =  64'h00000000000000fb
)                     
(
    // User Interface
    input  wire [(RX_DATA_WIDTH-1):0] RX_DATA_IN,
    input  wire [(RXCTRL_WIDTH-1):0] RXCTRL_IN,

    output reg          RXENPCOMMADET_OUT,      // 未用,高电平有效信号,可实现字节边界对齐检测到plus COMMA模式时进行处理。
    output reg          RXENMCOMMADET_OUT,      // 未用,高电平有效信号,可实现字节边界对齐检测到minus COMMA模式时进行处理。
    output reg          RX_ENCHAN_SYNC_OUT,     // 未用,驱动mgt的enchansync端口进行通道绑定
    input  wire         RX_CHANBOND_SEQ_IN,     // 输入通道绑定序列,不绑定时为0

    // Control Interface
    input  wire         INC_IN,             // 未用
    output wire         INC_OUT,            // 非独立的收发测试时输出已开始进行COMMA检测,指示发送端地址递增
    output wire         PATTERN_MATCHB_OUT, // COMMA不匹配
    input  wire         RESET_ON_ERROR_IN,  // 通过将PATTERN_MATCHB_OUT输出给外部,由此产生出错后的复位


    // Error Monitoring
    output wire [7:0]   ERROR_COUNT_OUT,    // 错误数

    // Track Data
    output wire         TRACK_DATA_OUT,     // 指示接收到的数据是否符合预期

    output wire RX_SLIDE,                   // 在对齐时要求GT滑动
    // System Interface
    input  wire         USER_CLK,
    input  wire         SYSTEM_RESET
);


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

reg             reset_on_error_in_r;
reg             reset_on_error_in_r2;
(* ASYNC_REG = "TRUE" *) (* keep = "true" *)reg             system_reset_r;
(* ASYNC_REG = "TRUE" *) (* keep = "true" *)reg             system_reset_r2;

reg             begin_r;
reg             data_error_detected_r;
reg     [8:0]   error_count_r;
reg             error_detected_r;
reg     [9:0]   read_counter_i;

    reg     [79:0] rom [0:511];

    reg     [(RX_DATA_WIDTH-1):0] rx_data_r;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r_track;

reg             start_of_packet_detected_r;
reg             track_data_r;
reg             track_data_r2;
reg             track_data_r3;
reg     [79:0]  rx_data_ram_r;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r2;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r3;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r4;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r5;
    reg     [(RX_DATA_WIDTH-1):0] rx_data_r6;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r2;
    reg     [(RXCTRL_WIDTH-1):0]  rxctrl_r3;

reg             rx_chanbond_seq_r;
reg             rx_chanbond_seq_r2;
reg             rx_chanbond_seq_r3;

    reg             idle_slip_r;
    reg             slip_assert_r;
    reg             wait_state_r;
    reg             bit_align_r;
    reg     [6:0]   wait_before_slip_r;
    reg     [6:0]   wait_before_init_r;

    reg     [1:0]   sel;
//*********************************Wire Declarations***************************

    wire    [(RX_DATA_WIDTH-1):0] bram_data_r;
wire            error_detected_c;
wire            next_begin_c;
wire            next_data_error_detected_c;
wire            next_track_data_c;
wire            start_of_packet_detected_c;
wire            chanbondseq_in_data;
wire            input_to_chanbond_data_i;
wire            input_to_chanbond_reg_i;
wire    [(CHANBOND_SEQ_LEN-1):0]  rx_chanbond_reg;
wire            rxdata_or;
wire            count_slip_complete_c;
wire            next_idle_slip_c;
wire            next_slip_assert_c;
wire            wait_state_c;
    wire    [(RX_DATA_WIDTH-1):0]  rx_data_aligned;
wire            rx_data_has_start_char_c;
wire            tied_to_ground_i;
wire    [31:0]  tied_to_ground_vec_i;
wire            tied_to_vcc_i;

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

    //_______________________  Static signal Assigments _______________________

    assign tied_to_ground_i             = 1'b0;
    assign tied_to_ground_vec_i         = 32'h0000;
    assign tied_to_vcc_i                = 1'b1;

    //___________ synchronizing the async reset for ease of timing simulation ________
    always@(posedge USER_CLK)
      begin
       system_reset_r <= `DLY SYSTEM_RESET;
       system_reset_r2 <= `DLY system_reset_r;
     end
    always@(posedge USER_CLK)
      begin
       reset_on_error_in_r <= `DLY RESET_ON_ERROR_IN;
       reset_on_error_in_r2 <= `DLY reset_on_error_in_r;
     end

    //______________________ Register RXDATA once to ease timing ______________

    always @(posedge USER_CLK)
    begin
        rx_data_r  <= `DLY    RX_DATA_IN;
        rx_data_r2 <= `DLY    rx_data_r;
    end

    always @(posedge USER_CLK)
    begin
        rxctrl_r  <= `DLY    RXCTRL_IN;
    end

    //________________________________ State machine __________________________

    // State registers
    always @(posedge USER_CLK)
        if(system_reset_r2)
            {begin_r,track_data_r,data_error_detected_r}  <=  `DLY    3'b100;
        else
        begin
            begin_r                <=  `DLY    next_begin_c;
            track_data_r           <=  `DLY    next_track_data_c;
            data_error_detected_r  <=  `DLY    next_data_error_detected_c;
        end

    // Next state logic
    assign  next_begin_c                =   (begin_r && !start_of_packet_detected_r) // 产生启动请求信号,在该信号复位为高后且未收到已开始数据检测的指示时保持为高,或数据出错时
                                            || data_error_detected_r ;

    assign  next_track_data_c           =   (begin_r && start_of_packet_detected_r)  // 产生检测数据跟踪请求,在启动为高后且收到开始检测到有效数据的指示时保持为高,或者已启动数据跟踪且未出错时
                                            || (track_data_r && !error_detected_r);

    assign  next_data_error_detected_c  =   (track_data_r && error_detected_r);      // 已启动跟踪,且检测到了错误                 

    assign  start_of_packet_detected_c  =   rx_data_has_start_char_c;                // 已开始检测到有效数据    //02bc对齐的时候 是高电平

    always @(posedge USER_CLK)
        start_of_packet_detected_r    <=   `DLY  start_of_packet_detected_c;

    // Registering for timing
    always @(posedge USER_CLK)
        track_data_r2    <=   `DLY  track_data_r;

    always @(posedge USER_CLK)
        track_data_r3    <=   `DLY  track_data_r2;

    //______________________________ Capture incoming data ____________________
    // 根据COMMA出现的位置将32b重新对齐
    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)    rx_data_r3 <= 'h0;
        else
        begin
            if(sel == 2'b01)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(RX_DATA_WIDTH/4-1):0],rx_data_r2[(RX_DATA_WIDTH - 1):RX_DATA_WIDTH/4]};
            end
            else if(sel == 2'b10)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(2*RX_DATA_WIDTH/4-1):0],rx_data_r2[(RX_DATA_WIDTH - 1):2*RX_DATA_WIDTH/4]};
            end
            else if(sel == 2'b11)
            begin
                rx_data_r3   <=  `DLY    {rx_data_r[(3*RX_DATA_WIDTH/4 - 1):0],rx_data_r2[(RX_DATA_WIDTH-1):3*RX_DATA_WIDTH/4]};
            end
            else rx_data_r3  <=  `DLY    rx_data_r2;
        end
    end

    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)
        begin
            rx_data_r4      <=  `DLY   'h0;
            rx_data_r5      <=  `DLY   'h0;
            rx_data_r6      <=  `DLY   'h0;
            rx_data_r_track <=  `DLY   'h0;
        end
        else
        begin
            rx_data_r4      <=  `DLY    rx_data_r3;
            rx_data_r5      <=  `DLY    rx_data_r4;
            rx_data_r6      <=  `DLY    rx_data_r5;
            rx_data_r_track <=  `DLY    rx_data_r6;
        end
    end

    always @(posedge USER_CLK)
    begin
        if(system_reset_r2)
        begin
            rxctrl_r2      <=  `DLY   'h0;
            rxctrl_r3      <=  `DLY   'h0;
        end
        else
        begin
            rxctrl_r2      <=  `DLY   rxctrl_r;
            rxctrl_r3      <=  `DLY   rxctrl_r2;
        end
    end
    assign rx_data_aligned = rx_data_r3;

    //___________________________ Code for Channel bonding ____________________
    // code to prevent checking of clock correction sequences for the start of packet char
    always @(posedge USER_CLK)
    begin
        rx_chanbond_seq_r  <=  `DLY    RX_CHANBOND_SEQ_IN;
        rx_chanbond_seq_r2 <=  `DLY    rx_chanbond_seq_r;
        rx_chanbond_seq_r3 <=  `DLY    rx_chanbond_seq_r2;
    end

    assign input_to_chanbond_reg_i  = rx_chanbond_seq_r2; //一直为0
    assign input_to_chanbond_data_i = tied_to_ground_i;


   //______________ Code for Bit Slipping Logic______________

    assign rxdata_or = |(rx_data_r|rx_data_r2|rx_data_r3); // 通道有收到数据

    // State registers
    always @(posedge USER_CLK)
        if( (system_reset_r2 == 1'b1) | (wait_before_init_r[6] == 1'b0) | (rxdata_or == 1'b0) )
            {idle_slip_r,slip_assert_r,wait_state_r}  <=  `DLY    3'b100;
        else
        begin
            idle_slip_r            <=  `DLY    next_idle_slip_c;
            slip_assert_r          <=  `DLY    next_slip_assert_c;
            wait_state_r           <=  `DLY    wait_state_c;
        end

    // Next state logic
    assign  next_idle_slip_c            =   (idle_slip_r & bit_align_r) | (wait_state_r & count_slip_complete_c); // slip操作空闲信号,当复为后且bit已对齐时,或者已完成执行滑窗后的等待

    assign  next_slip_assert_c          =   (idle_slip_r & !bit_align_r);   // 继续执行slip,上一slip操作已完成,但bit仍未对齐

    assign  wait_state_c                =   (slip_assert_r) | (wait_state_r & !count_slip_complete_c); // slip请求已产生,但是等待操作还未完成,则持续等待

    //_______ Counter for waiting clock cycles after RXSLIDE________
    always @(posedge USER_CLK)
    begin
        if (!wait_state_r)
           wait_before_slip_r  <= `DLY  7'b000000;
        else
           wait_before_slip_r  <= `DLY  wait_before_slip_r + 1'b1; // slip操作等待计时器
    end

    //_______ Counter for waiting clock cycles before starting RXSLIDE operation________
    //_______ Wait for 64 clock cycles to see if the RXDATA is already byte aligned. If not, start RXSLIDE operation
    always @(posedge USER_CLK)
    begin 
        if( (system_reset_r2 == 1'b1) | (rxdata_or == 1'b0) )
         wait_before_init_r <= `DLY    7'b0000000;
        else if (wait_before_init_r[6] == 1'b0) // 在启动接收前等待64clk
             wait_before_init_r <= `DLY    wait_before_init_r + 1'b1;
    end

    assign count_slip_complete_c = wait_before_slip_r[6];

    always @(posedge USER_CLK)
    begin
        if( (system_reset_r2 == 1'b1) | (rxdata_or == 1'b0) )   begin
          bit_align_r <= 1'b0;
        end else begin
            if( ({rx_data_r[23:0],rx_data_r2[31:24]} == START_OF_PACKET_CHAR) || ({rx_data_r[15:0],rx_data_r2[31:16]} == START_OF_PACKET_CHAR)
                || ({rx_data_r[7:0],rx_data_r2[31:8]} == START_OF_PACKET_CHAR) || (rx_data_r[31:0]== START_OF_PACKET_CHAR) )
            begin
                bit_align_r <= 1'b1; // 比较COMMA所有可能存在的4种情况以确定bit对齐
            end
        end
    end

    // Comma realignment logic might be needed. 4 levels of registering for RXDATA to meet timing
    // In 4 Byte scenario, when align_comma_word=1, Comma can appear on any of the four bytes.
    // { BYTE3 | BYTE2 | BYTE1 | BYTE0 } - Comma can appear on BYTE0/1/2/3
    // If Comma appears on BYTE1/2/3, RX_DATA is realigned so that Comma appears on BYTE0 in rx_data_r_track
    always @(posedge USER_CLK)
    begin
        if(reset_on_error_in_r2 || system_reset_r2)    sel <= 2'b00;
        else if (begin_r && !rx_chanbond_seq_r)
        begin
            // if Comma appears on BYTE3 ..
            if((rx_data_r[(RX_DATA_WIDTH - 1) : 3*RX_DATA_WIDTH/4] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[3]) // rxctrl_r 指示COMMA出现的位置,并比较收的包头是否匹配
                sel <= 2'b11; 
            // if Comma appears on BYTE2 ..
            else if((rx_data_r[(3*RX_DATA_WIDTH/4 - 1):2*RX_DATA_WIDTH/4] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[2])
            begin
                sel <= 2'b10;
            end
            // if Comma appears on BYTE1 ..
            else if((rx_data_r[(2*RX_DATA_WIDTH/4 - 1):RX_DATA_WIDTH/4] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[1])
            begin
                sel <= 2'b01;
            end
            // if Comma appears on BYTE0 ..
            else if((rx_data_r[(RX_DATA_WIDTH/4 - 1):0] == START_OF_PACKET_CHAR[7:0]) && rxctrl_r[0])
            begin
                sel <= 2'b00;
            end
        end
    end

    //___________________________ Code for Channel bonding ____________________
    // code to prevent checking of clock correction sequences for the start of packet char
    genvar i;
    generate
    for (i=0;i<CHANBOND_SEQ_LEN ;i=i+1)
    begin:register_chan_seq
    if(i==0)
        FD rx_chanbond_reg_0  ( .Q (rx_chanbond_reg[i]), .D (input_to_chanbond_reg_i), .C(USER_CLK));
    else
        FD rx_chanbond_reg_i  ( .Q (rx_chanbond_reg[i]), .D (rx_chanbond_reg[i-1]), .C(USER_CLK));
    end
    endgenerate

    assign chanbondseq_in_data = |rx_chanbond_reg || input_to_chanbond_data_i; // 未绑定始终为0


    assign rx_data_has_start_char_c = (rx_data_aligned[7:0] == START_OF_PACKET_CHAR[7:0]) && !chanbondseq_in_data && (|rxctrl_r3); // 只要对齐后的数据有一byte匹配


    //_____________________________ Assign output ports _______________________
    //assign TRACK_DATA_OUT = track_data_r;

    assign RX_SLIDE = slip_assert_r; // 输出slip信号

    // Drive the enpcommaalign port of the gt for alignment
    // Active-High signal that enables the byte boundary alignment process when the plus comma pattern is detected.
    always @(posedge USER_CLK)
        if(system_reset_r2)  RXENPCOMMADET_OUT   <=  `DLY    1'b0;
        else              RXENPCOMMADET_OUT   <=  `DLY    1'b1;

    // Drive the enmcommaalign port of the gt for alignment
    // Active-High signal that enables the byte boundary alignment process when the minus comma pattern is detected.
    always @(posedge USER_CLK)
        if(system_reset_r2)  RXENMCOMMADET_OUT   <=  `DLY    1'b0;
        else              RXENMCOMMADET_OUT   <=  `DLY    1'b1;

    assign INC_OUT =  start_of_packet_detected_c;

    assign PATTERN_MATCHB_OUT =  data_error_detected_r;

    // Drive the enchansync port of the mgt for channel bonding
    always @(posedge USER_CLK)
        if(system_reset_r2)  RX_ENCHAN_SYNC_OUT   <=  `DLY    1'b0;
        else              RX_ENCHAN_SYNC_OUT   <=  `DLY    1'b1;

    //___________________________ Check incoming data for errors ______________

    //An error is detected when data read for the BRAM does not match the incoming data
    assign  error_detected_c    =  track_data_r3 && (rx_data_r_track != bram_data_r); // 数据与ROM中不匹配

    //We register the error_detected signal for use with the error counter logic
    always @(posedge USER_CLK)
        if(!track_data_r)
            error_detected_r    <=  `DLY    1'b0;
        else
            error_detected_r    <=  `DLY    error_detected_c;

    //We count the total number of errors we detect. By keeping a count we make it less likely that we will miss
    //errors we did not directly observe.
    always @(posedge USER_CLK)
        if(system_reset_r2)
            error_count_r       <=  `DLY    9'd0;
        else if(error_detected_r)
            error_count_r       <=  `DLY    error_count_r + 1;

    //Here we connect the lower 8 bits of the count (the MSbit is used only to check when the counter reaches
    //max value) to the module output
    assign  ERROR_COUNT_OUT =   error_count_r[7:0];

  localparam ST_LINK_DOWN = 1'b0;
  localparam ST_LINK_UP   = 1'b1;
  reg        sm_link      = ST_LINK_DOWN;
  reg [6:0]  link_ctr     = 7'd0;

  always @(posedge USER_CLK) begin
        if(!track_data_r)
              sm_link  <= ST_LINK_DOWN;
        else
    case (sm_link)
      // The link is considered to be down when the link counter initially has a value less than 67. When the link is
      // down, the counter is incremented on each cycle where all PRBS bits match, but reset whenever any PRBS mismatch
      // occurs. When the link counter reaches 67, transition to the link up state.
      ST_LINK_DOWN: begin
        if (error_detected_r !== 1'b0) begin
          link_ctr <= 7'd0;
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
          else
            sm_link <= ST_LINK_UP;
        end
      end

      // When the link is up, the link counter is decreased by 34 whenever any PRBS mismatch occurs, but is increased by
      // only 1 on each cycle where all PRBS bits match, up to its saturation point of 67. If the link counter reaches
      // 0 (including rollover protection), transition to the link down state.
      ST_LINK_UP: begin
        if (error_detected_r !== 1'b0) begin
          if (link_ctr > 7'd33) begin
            link_ctr <= link_ctr - 7'd34;
            if (link_ctr == 7'd34)
              sm_link  <= ST_LINK_DOWN;
          end
          else begin
            link_ctr <= 7'd0;
            sm_link  <= ST_LINK_DOWN;
          end
        end
        else begin
          if (link_ctr < 7'd67)
            link_ctr <= link_ctr + 7'd1;
        end
      end
    endcase
  end

assign TRACK_DATA_OUT = sm_link;
    //____________________________ Counter to read from BRAM __________________________
    always @(posedge USER_CLK)
        if(system_reset_r2 ||  (read_counter_i == (WORDS_IN_BRAM-1)))
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else if (start_of_packet_detected_r && !track_data_r)
        begin
            read_counter_i   <=  `DLY    10'd0;
        end
        else
        begin
            read_counter_i  <=  `DLY    read_counter_i + 10'd1;
        end

    //________________________________ BRAM Inference Logic _____________________________

//Array slice from dat file to compare against receive data
generate
if(RX_DATA_WIDTH==80)
begin : datapath_80
    assign bram_data_r      = rx_data_ram_r[(RX_DATA_WIDTH-1):0];
end
else
begin : datapath_16_20_32_40_64
    assign bram_data_r = rx_data_ram_r[(16+RX_DATA_WIDTH-1):16];
end
endgenerate

`ifdef SIM
    initial
    begin
           $readmemh("gt_rom_init_rx.dat",rom,0,511);
    end

    always @(posedge USER_CLK)
           rx_data_ram_r <= `DLY  rom[read_counter_i];
`else
    always @(posedge USER_CLK)
           rx_data_ram_r <= 'haa5555aa;//`DLY  rom[read_counter_i];
`endif

endmodule    
posted @ 2022-05-21 00:21  快乐气氛组阿宇  阅读(535)  评论(0编辑  收藏  举报