- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
May I know which version of Software stack are you using? Are you able to update to DCP 2.0.1?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
May I know how do you compare the data? Have you make sure that your data is align when you are comparing?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page