Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20641 Discussions

Stratix 10 PAC HSSI example

yashael
New Contributor I
2,474 Views

I'm trying to understand how to use the hssi interface in stratix 10 PAC. I had some problem on rx_data_valid (PCS Direct on serial loopback)

But unable to reproduce the issue, so i'm creating a new issue to ask how to use it properly.

I tried modifying the hssi_prbs example code, to be more precise i'm trying to change the pattern_gen.v and pattern_ver_pipelined.v into just a simple counter.

However, after changing both of them, the rx_ready is always fluctuating, and never stable at 0xff.

yashael_0-1634491621111.png

 

So, i'm at loss on how to actually use this hssi interface. I tried looking into the transceiver user guide but still don't understand how to use it. Can someone please advise me how to use the interface correctly?

 

here are the modifications to pattern_gen.v and pattern_ver_pipelined.v

// pattern_gen.v

`timescale 1ps/1ps

module pattern_gen #(
        parameter MAX           = 'hffff,       //width
        parameter width         = 16,       //width
        parameter low_freq_len  = 8,        // (width/(low_freq_len*2)) must be a whole number
        parameter pattern       = "prbs7",   // prbs7, prbs9, prbs15, prbs23, prbs31
        parameter prbs_initial_value = 97
    ) (
        input  wire             clk,
        input  wire             reset,
        input  wire             enable,
        output wire [width-1:0] data_out,
        output wire             valid
    );

    reg [width-1:0] counter;
    always @(posedge clk) begin
        if (reset)
            counter <= 'd0;
        else if (enable)
            counter <= (counter == MAX) ? counter : counter + 'd1;
        else
            counter <= counter;
    end
    assign valid    = enable & ~(counter == MAX);
    assign data_out = valid ? counter : 'h0;

endmodule
// pattern_ver_pipelined.v

`timescale 1ps/1ps
module pattern_ver_pipelined #(
        parameter MAX           = 'hffff,       //width
        parameter width         = 16,     // width
        parameter pattern       = "prbs7", // prbs7, prbs9, prbs15, prbs23, prbs31
        parameter prbs_initial_value = 97
    ) (
        input                       clk,
        input                       reset,
        input                       enable,
        input [width-1:0]           data_in,
        output                      data_locked,
        output reg                  error
    );

    reg [width-1:0] ref_value;
    always @(posedge clk) begin
        if (reset)
            ref_value     <= 'd0;
        else if (enable)
            ref_value     <= (ref_value == MAX) ? ref_value : ref_value + 'd1;
        else
            ref_value     <= ref_value;
    end

    reg [width-1:0] err_count;
    always @(posedge clk) begin
        if (reset)
            err_count     <= 'd0;
        else if (enable && (ref_value == data_in))
            err_count     <= err_count + 'd1;
        else
            err_count     <= err_count;
    end

    always @(posedge clk) begin
        if (reset)
            error   <= 'd0;
        else if (data_locked)
            error   <= err_count > 'd0;
        else
            error   <= error;
    end
    assign data_locked = ref_value == MAX;

endmodule
0 Kudos
16 Replies
JohnT_Intel
Employee
2,424 Views

Hi,


May I know which version of Software stack are you using? Are you able to update to DCP 2.0.1?


0 Kudos
yashael
New Contributor I
2,416 Views

I'm not sure what is DCP 2.0.1, but the Pr Interface Id is 9346116d-a52d-5ca8-b06a-a9a389ef7c8d, which correspond to acceleration stack version 2.0.1

0 Kudos
JohnT_Intel
Employee
2,378 Views

Hi,


From your pattern_gen.v, I observed that there is additional port for valid. May I know how do you connect the valid signal? Are you able to share with me the full design?


0 Kudos
yashael
New Contributor I
2,362 Views

Yes i have that additional port, however i didn't use it yet to keep it the same with the original pattern_gen.v

the prbs_top look like this.

 

// `include "pr_hssi_if.vh"

module prbs_top #(
        parameter NUM_HSSI_RAW_PR_IFCS      = 2,
        parameter NUM_HSSI_LN               = 4,
        parameter PRBS_DATA_WIDTH           = 8,
        parameter PRBS_INITIAL_VALUE        = 97,
        parameter PRBS_TAP                  = 31,
        parameter PRBS_XAUI_PATTERN         = 97,
        parameter PRBS_NUM_CYCLES_FOR_LOCK  = 8'd31,
        parameter PRBS_PIPELINE             = 3
    ) (
        input  logic        clk,                 // Primary CCI-P interface clock.
        input logic         clk_125,
        input  logic        softReset,

        // Raw HSSI interface
        pr_hssi_if.to_fiu   hssi                [NUM_HSSI_RAW_PR_IFCS],

        // HSSI control signals
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        rx_seriallpbken,

        // PRBS control signals
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        prbs_insert_error,
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        prbs_pause_tx,
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        prbs_pause_rx,

        // PRBS status signals
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        prbs_lock,
        // HSSI feedback signals
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        tx_ready,
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        rx_ready,
        // PRBS counters
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0][31:0]  prbs_tx_count,
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0][31:0]  prbs_tx_err_count,
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0][31:0]  prbs_rx_count,
        output logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0][31:0]  prbs_rx_err_count,

        // Resets
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        cr2hssi_reset,
        input  logic [NUM_HSSI_RAW_PR_IFCS-1:0][NUM_HSSI_LN-1:0]        cr2ctr_reset,

        output logic [PRBS_DATA_WIDTH-1:0] rx_prbs_02,
        output logic [PRBS_DATA_WIDTH-1:0] tx_prbs_02
    );

    // logic to stage sync for output
    logic [31:0]    prbs_tx_count_d             [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_tx_count_en            [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [31:0]    prbs_rx_count_d             [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_rx_count_en            [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic [31:0]    prbs_tx_err_count_d         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_tx_err_count_en        [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [31:0]    prbs_rx_err_count_d         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_rx_err_count_en        [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    // logic operating on hssi if clocks
    logic [31:0]    prbs_tx_count_hssi          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [31:0]    prbs_rx_count_hssi          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic [31:0]    prbs_tx_err_count_hssi      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [31:0]    prbs_rx_err_count_hssi      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic           prbs_pause_hssi_tx          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_pause_hssi_rx          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic           prbs_gen_data_valid         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];


    logic           prbs_pause_gen              [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_pause_chk              [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_pause_chk_sync              [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic           prbs_insert_error_hssi      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_insert_error_hssi_q    [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_insert_error_hssi_e    [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic           prbs_lock_hssi_rx           [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           prbs_lock_hssi_rx_sync           [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           shift_lock_hssi_rx          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           shift_lock_hssi_tx          [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic           rx_seriallpbken_hssi        [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic           hssi_reset                  [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    // PRBS outputs
    logic [PRBS_DATA_WIDTH-1:0] prbs_dout       [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [PRBS_DATA_WIDTH-1:0] shift_dout      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [PRBS_DATA_WIDTH-1:0] prbs_din        [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic [PRBS_DATA_WIDTH-1:0] prbs_din_sync        [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic                       prbs_error_flag [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic                       prbs_error_flag_sync [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    //TX XCVR Clock Shared for 4 channels per QSFP
    logic   tx_clk                              [NUM_HSSI_RAW_PR_IFCS];
    logic   tx_arst_n                           [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   tx_arst_n_d                         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    //RX_CLKOUT 4 independent clocks per QSFP
    logic   rx_clk                              [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_arst_n                           [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_arst_n_d                         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic   plls_locked                         [NUM_HSSI_RAW_PR_IFCS];
    logic   rx_data_valid                       [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   cr2hssi_reset_sync                  [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   cr2ctr_tx_reset_n                   [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   cr2ctr_rx_reset_n                   [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];

    logic   tx_count_reset_n                    [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_count_reset_n                    [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];


    logic   hssi_ch_reset                       [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   pll_arst_n                          [NUM_HSSI_RAW_PR_IFCS];


    logic   tx_analogreset                      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   tx_digitalreset                     [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_analogreset                      [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_digitalreset                     [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_analogreset_stat                 [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_digitalreset_stat                [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   tx_analogreset_stat                 [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   tx_digitalreset_stat                [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_is_lockedtodata                  [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   tx_cal_busy                         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    logic   rx_cal_busy                         [NUM_HSSI_RAW_PR_IFCS][NUM_HSSI_LN];
    genvar  ch_idx, if_idx;

    generate
        for (if_idx = 0; if_idx < NUM_HSSI_RAW_PR_IFCS; if_idx = if_idx + 1) begin : HSSI_IF
            assign tx_clk[if_idx]       = hssi[if_idx].f2a_tx_parallel_clk_x2;
            assign plls_locked[if_idx]  = hssi[if_idx].f2a_atxpll_locked & hssi[if_idx].f2a_fpll_locked;

            resync #(
                .SYNC_CHAIN_LENGTH  (2),
                .WIDTH              (1),
                .INIT_VALUE         (0),
                .NO_CUT             (0)
            ) inst_async_reset (
                .clk                (clk_125),
                .reset              (~plls_locked[if_idx]),
                .d                  (1'b1),
                .q                  (pll_arst_n[if_idx])
            );

            for (ch_idx = 0; ch_idx < 4; ch_idx = ch_idx + 1) begin : HSSI_CH
                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_tx_ctr_reset_sync (
                    .clk                (tx_clk[if_idx]),
                    .reset              (cr2ctr_reset      [if_idx][ch_idx]),
                    .d                  (1'b1),
                    .q                  (cr2ctr_tx_reset_n [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_rx_ctr_reset_sync (
                    .clk                (rx_clk[if_idx][ch_idx]),
                    .reset              (cr2ctr_reset      [if_idx][ch_idx]),
                    .d                  (1'b1),
                    .q                  (cr2ctr_rx_reset_n [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_prbs_pause_tx_sync (
                    .clk                (tx_clk[if_idx]),
                    .reset              (1'b0),
                    .d                  (prbs_pause_tx      [if_idx][ch_idx]),
                    .q                  (prbs_pause_hssi_tx [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_prbs_pause_rx_sync (
                    .clk                (rx_clk[if_idx][ch_idx]),
                    .reset              (1'b0),
                    .d                  (prbs_pause_rx      [if_idx][ch_idx]),
                    .q                  (prbs_pause_hssi_rx [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_prbs_ins_err_sync (
                    .clk                (tx_clk[if_idx]),
                    .reset              (1'b0),
                    .d                  (prbs_insert_error      [if_idx][ch_idx]),
                    .q                  (prbs_insert_error_hssi [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_prbs_lock_sync (
                    .clk                (clk),
                    .reset              (1'b0),
                    .d                  (prbs_lock_hssi_rx [if_idx][ch_idx]),
                    .q                  (prbs_lock         [if_idx][ch_idx])
                );

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_shift_lock_sync (
                    .clk                (tx_clk[if_idx]),
                    .reset              (1'b0),
                    .d                  (shift_lock_hssi_rx [if_idx][ch_idx]),
                    .q                  (shift_lock_hssi_tx [if_idx][ch_idx])
                );

                // reset signal outputs
                assign hssi[if_idx].a2f_tx_analogreset       [ch_idx] = tx_analogreset       [if_idx][ch_idx];
                assign hssi[if_idx].a2f_tx_digitalreset      [ch_idx] = tx_digitalreset      [if_idx][ch_idx];
                assign hssi[if_idx].a2f_rx_analogreset       [ch_idx] = rx_analogreset       [if_idx][ch_idx];
                assign hssi[if_idx].a2f_rx_digitalreset      [ch_idx] = rx_digitalreset      [if_idx][ch_idx];

                // reset status inputs
                assign rx_analogreset_stat  [if_idx][ch_idx] = hssi[if_idx].f2a_rx_analogreset_stat  [ch_idx];
                assign rx_digitalreset_stat [if_idx][ch_idx] = hssi[if_idx].f2a_rx_digitalreset_stat [ch_idx];
                assign tx_analogreset_stat  [if_idx][ch_idx] = hssi[if_idx].f2a_tx_analogreset_stat  [ch_idx];
                assign tx_digitalreset_stat [if_idx][ch_idx] = hssi[if_idx].f2a_tx_digitalreset_stat [ch_idx];
                assign rx_is_lockedtodata   [if_idx][ch_idx] = hssi[if_idx].f2a_rx_is_lockedtodata   [ch_idx];
                assign tx_cal_busy          [if_idx][ch_idx] = hssi[if_idx].f2a_tx_cal_busy          [ch_idx];
                assign rx_cal_busy          [if_idx][ch_idx] = hssi[if_idx].f2a_rx_cal_busy          [ch_idx];

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_async100_reset (
                    .clk                (clk_125),
                    .reset              (1'b0),
                    .d                  (cr2hssi_reset[if_idx][ch_idx]),
                    .q                  (cr2hssi_reset_sync[if_idx][ch_idx])
                );

                assign hssi_ch_reset[if_idx][ch_idx] = !pll_arst_n[if_idx] | cr2hssi_reset_sync[if_idx][ch_idx];
                reset_controller inst_reset_controller (
                    .clock                  (clk_125),
                    .reset                  (hssi_ch_reset[if_idx][ch_idx]),
                    .tx_ready               (tx_ready[if_idx][ch_idx]), // out to FME and to PR boundary
                    .rx_ready               (rx_ready[if_idx][ch_idx]), // out to FME and to PR boundary
                    .pll_locked             (plls_locked[if_idx]), // both ATX and fPLL are locked
                    .pll_select             (1'b0),
                    .tx_analogreset         (tx_analogreset       [if_idx][ch_idx]),
                    .tx_digitalreset        (tx_digitalreset      [if_idx][ch_idx]),
                    .rx_analogreset         (rx_analogreset       [if_idx][ch_idx]),
                    .rx_digitalreset        (rx_digitalreset      [if_idx][ch_idx]),
                    .rx_analogreset_stat    (rx_analogreset_stat  [if_idx][ch_idx]),
                    .rx_digitalreset_stat   (rx_digitalreset_stat [if_idx][ch_idx]),
                    .tx_analogreset_stat    (tx_analogreset_stat  [if_idx][ch_idx]),
                    .tx_digitalreset_stat   (tx_digitalreset_stat [if_idx][ch_idx]),
                    .rx_is_lockedtodata     (rx_is_lockedtodata   [if_idx][ch_idx]),
                    .tx_cal_busy            (tx_cal_busy          [if_idx][ch_idx]),
                    .rx_cal_busy            (rx_cal_busy          [if_idx][ch_idx])
                );

                always_ff @(posedge tx_clk[if_idx] or negedge tx_arst_n[if_idx][ch_idx]) begin
                    if(~tx_arst_n[if_idx][ch_idx]) begin
                        prbs_insert_error_hssi_q[if_idx][ch_idx] <= '0;
                        prbs_insert_error_hssi_e[if_idx][ch_idx] <= '0;
                    end else begin
                        prbs_insert_error_hssi_q[if_idx][ch_idx] <= prbs_insert_error_hssi[if_idx][ch_idx];
                        prbs_insert_error_hssi_e[if_idx][ch_idx] <= prbs_insert_error_hssi[if_idx][ch_idx] & !prbs_insert_error_hssi_q[if_idx][ch_idx];
                    end
                end

                resync #(
                    .SYNC_CHAIN_LENGTH  (2),
                    .WIDTH              (1),
                    .INIT_VALUE         (0),
                    .NO_CUT             (0)
                ) inst_prbs_seriallpbken_sync (
                    .clk                (rx_clk[if_idx][ch_idx]),
                    .reset              (1'b0),
                    .d                  (rx_seriallpbken      [if_idx][ch_idx]),
                    .q                  (rx_seriallpbken_hssi [if_idx][ch_idx])
                );

                // assign the rxclk
                assign rx_clk[if_idx][ch_idx] = hssi[if_idx].f2a_rx_clkout[ch_idx];

                // Generate resets based off PLL locks
                assign hssi_reset[if_idx][ch_idx] = !plls_locked[if_idx] | cr2hssi_reset[if_idx][ch_idx];

                always_ff @(posedge tx_clk[if_idx] or posedge hssi_reset[if_idx][ch_idx]) begin
                    if(hssi_reset[if_idx][ch_idx]) begin
                        {tx_arst_n[if_idx][ch_idx],tx_arst_n_d[if_idx][ch_idx]} <= '0;
                    end else begin
                        {tx_arst_n[if_idx][ch_idx],tx_arst_n_d[if_idx][ch_idx]} <= {tx_arst_n_d[if_idx][ch_idx],1'b1};
                    end
                end

                always_ff @(posedge rx_clk[if_idx][ch_idx] or posedge hssi_reset[if_idx][ch_idx]) begin
                    if(hssi_reset[if_idx][ch_idx]) begin
                        {rx_arst_n[if_idx][ch_idx],rx_arst_n_d[if_idx][ch_idx]} <= '0;
                    end else begin
                        {rx_arst_n[if_idx][ch_idx],rx_arst_n_d[if_idx][ch_idx]} <= {rx_arst_n_d[if_idx][ch_idx],1'b1};
                    end
                end

// when tx are constant value, rx_value stays asserted

                // Bolt-up PRBS generator to TX side of PHY
                always_ff @(posedge tx_clk[if_idx] or negedge tx_arst_n[if_idx][ch_idx]) begin
                    if(!tx_arst_n[if_idx][ch_idx]) begin
                        hssi[if_idx].a2f_tx_parallel_data[(ch_idx*80)+79:(ch_idx*80)]    <= '0;
                    end else begin
                        hssi[if_idx].a2f_tx_parallel_data[(ch_idx*80)+31:(ch_idx*80)] <= prbs_dout[if_idx][ch_idx];//{prbs_dout[if_idx][ch_idx][31:1],
                                                // prbs_dout[if_idx][ch_idx][0] ^ prbs_insert_error_hssi_e[if_idx][ch_idx]};
                        hssi[if_idx].a2f_tx_parallel_data[(ch_idx*80)+36]              <= 1'b1; // tx_enh_data_valid
                        hssi[if_idx].a2f_tx_parallel_data[(ch_idx*80)+79]              <= 1'b1; // tx_fifo_wr_en
                    end
                end

                // Bolt-up RX side of PHY to PRBS checker and drive serial loopback low for now
                always_ff @(posedge rx_clk[if_idx][ch_idx] or negedge rx_arst_n[if_idx][ch_idx]) begin
                    if(!rx_arst_n[if_idx][ch_idx]) begin
                        hssi[if_idx].a2f_rx_seriallpbken[ch_idx]      <= '0;
                        prbs_din[if_idx][ch_idx]                      <= '0;
                        rx_data_valid[if_idx][ch_idx]                 <= '0;
                    end else begin
                        hssi[if_idx].a2f_rx_seriallpbken[ch_idx]      <= rx_seriallpbken_hssi[if_idx][ch_idx];
                        prbs_din[if_idx][ch_idx]                      <= hssi[if_idx].f2a_rx_parallel_data[(ch_idx*80)+31:(ch_idx*80)];
                        rx_data_valid[if_idx][ch_idx]                 <= hssi[if_idx].f2a_rx_parallel_data[(ch_idx*80)+79];
                    end
                end

                assign prbs_pause_gen[if_idx][ch_idx] = prbs_pause_hssi_tx[if_idx][ch_idx];
                assign prbs_pause_chk[if_idx][ch_idx] = prbs_pause_hssi_rx[if_idx][ch_idx] | !rx_data_valid[if_idx][ch_idx];

                assign tx_count_reset_n[if_idx][ch_idx] = cr2ctr_tx_reset_n[if_idx][ch_idx] & tx_arst_n[if_idx][ch_idx];
                assign rx_count_reset_n[if_idx][ch_idx] = cr2ctr_rx_reset_n[if_idx][ch_idx] & rx_arst_n[if_idx][ch_idx];

                pattern_gen #(
                    .MAX                    (32'hFFFF_FFFF),
                    .prbs_initial_value     (32'h5555_5555),
                    .width                  (PRBS_DATA_WIDTH),
                    .pattern                ("prbs31")
                ) inst_pattern_gen (
                    .clk                    (tx_clk                  [if_idx]),
                    .reset                  (~tx_arst_n              [if_idx][ch_idx]),
                    .data_out               (prbs_dout               [if_idx][ch_idx]),
                    .enable                 (~prbs_pause_gen         [if_idx][ch_idx]),
                    .valid                  (prbs_gen_data_valid     [if_idx][ch_idx])
                );

                pattern_ver_pipelined #(
                    .MAX                    (32'hFFFF_FFFF),
                    .prbs_initial_value     (PRBS_INITIAL_VALUE),
                    .width                  (PRBS_DATA_WIDTH),
                    .pattern                ("prbs31")
                ) inst_pattern_ver (
                    .clk                    (rx_clk             [if_idx][ch_idx]),
                    .reset                  (~rx_arst_n         [if_idx][ch_idx]),
                    .data_in                (prbs_din           [if_idx][ch_idx]),
                    .data_locked            (prbs_lock_hssi_rx  [if_idx][ch_idx]),
                    .error                  (prbs_error_flag    [if_idx][ch_idx]),
                    .enable                 (~prbs_pause_chk    [if_idx][ch_idx])
                );


                // rx/tx counters
                always_ff @(posedge tx_clk[if_idx] or negedge tx_count_reset_n[if_idx][ch_idx]) begin
                    if(!tx_count_reset_n[if_idx][ch_idx]) begin
                        prbs_tx_count_hssi[if_idx][ch_idx] <= '0;
                    end else if (!(prbs_pause_gen[if_idx][ch_idx])) begin
                        prbs_tx_count_hssi[if_idx][ch_idx] <= prbs_tx_count_hssi[if_idx][ch_idx] + 1;
                    end
                end

                always_ff @(posedge tx_clk[if_idx] or negedge tx_count_reset_n[if_idx][ch_idx]) begin
                    if(!tx_count_reset_n[if_idx][ch_idx]) begin
                        prbs_tx_err_count_hssi[if_idx][ch_idx] <= '0;
                    end else if (prbs_insert_error_hssi_e[if_idx][ch_idx]) begin
                        prbs_tx_err_count_hssi[if_idx][ch_idx] <= prbs_tx_err_count_hssi[if_idx][ch_idx] + 1;
                    end
                end

                always_ff @(posedge rx_clk[if_idx][ch_idx] or negedge rx_count_reset_n[if_idx][ch_idx]) begin
                    if(!rx_count_reset_n[if_idx][ch_idx]) begin
                        prbs_rx_count_hssi[if_idx][ch_idx] <= '0;
                    end else if (!(prbs_pause_chk[if_idx][ch_idx]  | prbs_error_flag[if_idx][ch_idx])) begin
                        prbs_rx_count_hssi[if_idx][ch_idx] <= prbs_rx_count_hssi[if_idx][ch_idx] + 1;
                    end
                end

                always_ff @(posedge rx_clk[if_idx][ch_idx] or negedge rx_count_reset_n[if_idx][ch_idx]) begin
                    if(!rx_count_reset_n[if_idx][ch_idx]) begin
                        prbs_rx_err_count_hssi[if_idx][ch_idx] <= '0;
                    end else if (prbs_error_flag[if_idx][ch_idx] & !prbs_pause_chk[if_idx][ch_idx]) begin
                        prbs_rx_err_count_hssi[if_idx][ch_idx] <= prbs_rx_err_count_hssi[if_idx][ch_idx] + 1;
                    end
                end

                avst_sync tx_count_bridge (
                    .in_clk(tx_clk[if_idx]),
                    .in_reset(!tx_count_reset_n[if_idx][ch_idx]),
                    .out_clk(clk),
                    .out_reset(softReset),
                    .in_ready(),
                    .in_valid('1),
                    .in_data(prbs_tx_count_hssi[if_idx][ch_idx]),
                    .out_ready('1),
                    .out_valid(prbs_tx_count_en[if_idx][ch_idx]),
                    .out_data(prbs_tx_count_d[if_idx][ch_idx])
                );

                avst_sync tx_err_count_bridge (
                    .in_clk(tx_clk[if_idx]),
                    .in_reset(!tx_count_reset_n[if_idx][ch_idx]),
                    .out_clk(clk),
                    .out_reset(softReset),
                    .in_ready(),
                    .in_valid('1),
                    .in_data(prbs_tx_err_count_hssi[if_idx][ch_idx]),
                    .out_ready('1),
                    .out_valid(prbs_tx_err_count_en[if_idx][ch_idx]),
                    .out_data(prbs_tx_err_count_d[if_idx][ch_idx])
                );

                avst_sync rx_count_bridge (
                    .in_clk(rx_clk[if_idx][ch_idx]),
                    .in_reset(!rx_count_reset_n[if_idx][ch_idx]),
                    .out_clk(clk),
                    .out_reset(softReset),
                    .in_ready(),
                    .in_valid('1),
                    .in_data(prbs_rx_count_hssi[if_idx][ch_idx]),
                    .out_ready('1),
                    .out_valid(prbs_rx_count_en[if_idx][ch_idx]),
                    .out_data(prbs_rx_count_d[if_idx][ch_idx])
                );

                avst_sync rx_err_count_bridge (
                    .in_clk(rx_clk[if_idx][ch_idx]),
                    .in_reset(!rx_count_reset_n[if_idx][ch_idx]),
                    .out_clk(clk),
                    .out_reset(softReset),
                    .in_ready(),
                    .in_valid('1),
                    .in_data(prbs_rx_err_count_hssi[if_idx][ch_idx]),
                    .out_ready('1),
                    .out_valid(prbs_rx_err_count_en[if_idx][ch_idx]),
                    .out_data(prbs_rx_err_count_d[if_idx][ch_idx])
                );

                always_ff @(posedge clk) begin
                    if(softReset) begin
                    prbs_tx_count[if_idx][ch_idx] <= '0;
                    end else if (prbs_tx_count_en[if_idx][ch_idx]) begin
                    prbs_tx_count[if_idx][ch_idx] <= prbs_tx_count_d[if_idx][ch_idx];
                    end
                end

                always_ff @(posedge clk) begin
                    if(softReset) begin
                    prbs_tx_err_count[if_idx][ch_idx] <= '0;
                    end else if (prbs_tx_err_count_en[if_idx][ch_idx]) begin
                    prbs_tx_err_count[if_idx][ch_idx] <= prbs_tx_err_count_d[if_idx][ch_idx];
                    end
                end

                always_ff @(posedge clk) begin
                    if(softReset) begin
                    prbs_rx_count[if_idx][ch_idx] <= '0;
                    end else if (prbs_rx_count_en[if_idx][ch_idx]) begin
                    prbs_rx_count[if_idx][ch_idx] <= prbs_rx_count_d[if_idx][ch_idx];
                    end
                end

                always_ff @(posedge clk) begin
                    if(softReset) begin
                    prbs_rx_err_count[if_idx][ch_idx] <= '0;
                    end else if (prbs_rx_err_count_en[if_idx][ch_idx]) begin
                    prbs_rx_err_count[if_idx][ch_idx] <= prbs_rx_err_count_d[if_idx][ch_idx];
                    end
                end
            end // block: HSSI_CH
        end // block: HSSI_IF
    endgenerate
endmodule // prbs_top

 

0 Kudos
yashael
New Contributor I
2,327 Views

After several seconds, the RX_READY seems to assert well. but I couldn't found the correct data in the rx_parallel_data. using the same code.

Also, in the code, bit no 79 is always set high. Is it not working if we have a valid signal for that particular signal?

0 Kudos
JohnT_Intel
Employee
2,309 Views

HI,


After further investigation, the TX_READY and RX_READY will not have anything to with the PRBS module. The TX_READY and RX_READY will be related to the interface readiness. Have you check if this issue is not happening on the original design?


0 Kudos
yashael
New Contributor I
2,243 Views

Yes I can confirm that those signal is asserted if given enough time. But why is the data on the receiving end differs from the transmitter? I observed a kind of shifted value on the receiving end. Do I have to implement an error correction module?

0 Kudos
JohnT_Intel
Employee
2,236 Views

Hi,


May I know how do you compare the data? Have you make sure that your data is align when you are comparing?


0 Kudos
yashael
New Contributor I
2,234 Views

I compared the data in tx_parallel_data[0..31] with rx_parallel_data[0..31]. To make it clear, I attached the screenshot of logic analyzer showing the difference in tx_parallel_data and rx_parallel_data.

0 Kudos
JohnT_Intel
Employee
2,230 Views

Hi,


May I know if you have make sure that your data is check before you locked the data?


From the rtl you provided, you are only locking the data once the counter hit MAX.


assign data_locked = ref_value == MAX;


0 Kudos
yashael
New Contributor I
2,208 Views

In the rtl I provided, I was not sure what the data_locked is used for, and its function is not clear in the example.

However, in the screenshot I sent you I used the example design (prbs pattern_generator) and not my own pattern generator (counter).

In the rx_pattern_ver waveform, we can see that the data is check before the data locked, (the pause_chk is low and the data_locked is still lo). But, even there the rx_data is not equal to tx_data.

0 Kudos
yashael
New Contributor I
2,162 Views

Hello,

I tried simulating (in ModelSim 10.6d) using the native PHY PCS direct with the same parameter as in ug-20211 and the same prbs_top, prbs_gen, prbs_ver_pipelined from the hssi_prbs example.

I tried simulating the same steps as in hssi_prbs.c (reset, serial loopback, and unpause tx & rx). But in the simulator itself, the data received is not the same. (comparing prbs_din with prbs_dout). Is there any special instructions or configurations or technique that I need to implement in order to use PCS direct? Can someone help me with this?

0 Kudos
JohnT_Intel
Employee
2,111 Views

Hi,


There is no simulation for the HSSI IP. I would recommend that you try to look at the resync block which help to syncronize the data between the TX and RX before you are able to expect the correct data.


0 Kudos
yashael
New Contributor I
2,065 Views

Hi,

I'm extracting simulation files from Stratix 10 Native PHY IP, then simulate it in modelsim.

In the simulation, i tried using resync block for the receiver data, and some data is missing.

0 Kudos
yashael
New Contributor I
2,056 Views

Hi, I tried implementing a word aligner by sending a pattern (0xF0000000). because of the bitslip, the RX then will receive a different value (e.g 0x003c0000).

But then it turns out that the bitslip is not constant throughout the transfer.

 

To prove that there's are bitslips happening, I took a screenshot of the receiving part. This time, the prbs_din is sync using resync.

The expected sequence of the 5 first word are: 0x55555555, 0x5fffffff, 0x2a000000, 0x17a00000, 0x0aaa0000.

But if you see the screenshot, you can see that the words are getting mixed, for example
0xfd555555 is parts of the first and second correct sequence. thus showing a bit slip.

Although the prbs check is shows no error, the data itself is not correct.

 

To reproduce this error, you can compile hssi_prbs example with the attached prbs_top.v and hssi.stp within src.zip.

Is there any pattern to this bitslip? How do I fix this bitslips? 
I really need this to work, my goal is just simply moving data from 1 fpga to another.

Please advise a way to correct the received data.

0 Kudos
JohnT_Intel
Employee
1,966 Views

Hi,


I would recommend you to get the design example from Algo Logic (https://www.intel.com/content/www/us/en/programmable/products/boards_and_kits/dev-kits/altera/intel-fpga-pac-d5005/algo-logic-ip.html) which will consist of the MAC block where it will help you on sending and receiving the data correctly.


0 Kudos
Reply