initial commit, add dds_par module

This commit is contained in:
2024-01-15 09:36:08 +08:00
commit 315a673005
1374 changed files with 465956 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
####################################################################################
## Copyright (c) 2018 - 2023 Analog Devices, Inc.
### SPDX short identifier: BSD-1-Clause
## Auto-generated, do not modify!
####################################################################################
LIBRARY_NAME := jesd204_rx
GENERIC_DEPS += ../../common/ad_pack.v
GENERIC_DEPS += ../../common/ad_upack.v
GENERIC_DEPS += align_mux.v
GENERIC_DEPS += elastic_buffer.v
GENERIC_DEPS += jesd204_ilas_monitor.v
GENERIC_DEPS += jesd204_lane_latency_monitor.v
GENERIC_DEPS += jesd204_rx.v
GENERIC_DEPS += jesd204_rx_cgs.v
GENERIC_DEPS += jesd204_rx_ctrl.v
GENERIC_DEPS += jesd204_rx_frame_align.v
GENERIC_DEPS += jesd204_rx_lane.v
XILINX_DEPS += bd/bd.tcl
XILINX_DEPS += error_monitor.v
XILINX_DEPS += jesd204_rx_constr.ttcl
XILINX_DEPS += jesd204_rx_ctrl_64b.v
XILINX_DEPS += jesd204_rx_header.v
XILINX_DEPS += jesd204_rx_ip.tcl
XILINX_DEPS += jesd204_rx_lane_64b.v
XILINX_DEPS += jesd204_rx_ooc.ttcl
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_cfg.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_cfg_rtl.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_event.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_event_rtl.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_ilas_config.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_ilas_config_rtl.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_status.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_status_rtl.xml
XILINX_LIB_DEPS += jesd204/jesd204_common
XILINX_LIB_DEPS += util_cdc
XILINX_INTERFACE_DEPS += jesd204/interfaces
INTEL_DEPS += ../../util_cdc/sync_bits.v
INTEL_DEPS += ../../util_cdc/sync_data.v
INTEL_DEPS += ../../util_cdc/sync_event.v
INTEL_DEPS += ../jesd204_common/jesd204_eof_generator.v
INTEL_DEPS += ../jesd204_common/jesd204_frame_align_replace.v
INTEL_DEPS += ../jesd204_common/jesd204_frame_mark.v
INTEL_DEPS += ../jesd204_common/jesd204_lmfc.v
INTEL_DEPS += ../jesd204_common/jesd204_scrambler.v
INTEL_DEPS += ../jesd204_common/pipeline_stage.v
INTEL_DEPS += jesd204_rx_constr.sdc
INTEL_DEPS += jesd204_rx_hw.tcl
include ../../scripts/library.mk
+42
View File
@@ -0,0 +1,42 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2021, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module align_mux #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input [2:0] align,
input [DATA_PATH_WIDTH*8-1:0] in_data,
input [DATA_PATH_WIDTH-1:0] in_charisk,
output [DATA_PATH_WIDTH*8-1:0] out_data,
output [DATA_PATH_WIDTH-1:0] out_charisk
);
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
wire [DPW_LOG2-1:0] align_int;
reg [DATA_PATH_WIDTH*8-1:0] in_data_d1;
reg [DATA_PATH_WIDTH-1:0] in_charisk_d1;
wire [(DATA_PATH_WIDTH*8*2)-1:0] data;
wire [(DATA_PATH_WIDTH*2)-1:0] charisk;
always @(posedge clk) begin
in_data_d1 <= in_data;
in_charisk_d1 <= in_charisk;
end
assign data = {in_data, in_data_d1};
assign charisk = {in_charisk, in_charisk_d1};
assign align_int = align[DPW_LOG2-1:0];
assign out_data = data[align_int*8 +: (DATA_PATH_WIDTH*8)];
assign out_charisk = charisk[align_int +: DATA_PATH_WIDTH];
endmodule
+49
View File
@@ -0,0 +1,49 @@
###############################################################################
## Copyright (C) 2021 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
proc init {cellpath otherInfo} {
set ip [get_bd_cells $cellpath]
bd::mark_propagate_override $ip \
"ASYNC_CLK"
}
proc detect_async_clk { cellpath ip param_name clk_a clk_b } {
set param_src [get_property "CONFIG.$param_name.VALUE_SRC" $ip]
if {[string equal $param_src "USER"]} {
return;
}
set clk_domain_a [get_property CONFIG.CLK_DOMAIN $clk_a]
set clk_domain_b [get_property CONFIG.CLK_DOMAIN $clk_b]
set clk_freq_a [get_property CONFIG.FREQ_HZ $clk_a]
set clk_freq_b [get_property CONFIG.FREQ_HZ $clk_b]
set clk_phase_a [get_property CONFIG.PHASE $clk_a]
set clk_phase_b [get_property CONFIG.PHASE $clk_b]
# Only mark it as sync if we can make sure that it is sync, if the
# relationship of the clocks is unknown mark it as async
if {$clk_domain_a != {} && $clk_domain_b != {} && \
$clk_domain_a == $clk_domain_b && $clk_freq_a == $clk_freq_b && \
$clk_phase_a == $clk_phase_b} {
set clk_async 0
} else {
set clk_async 1
}
set_property "CONFIG.$param_name" $clk_async $ip
}
proc propagate {cellpath otherinfo} {
set ip [get_bd_cells $cellpath]
set link_clk [get_bd_pins "$ip/clk"]
set device_clk [get_bd_pins "$ip/device_clk"]
detect_async_clk $cellpath $ip "ASYNC_CLK" $link_clk $device_clk
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,142 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2021, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module elastic_buffer #(
parameter IWIDTH = 32,
parameter OWIDTH = 48,
parameter SIZE = 256,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input device_clk,
input device_reset,
input [IWIDTH-1:0] wr_data,
output [OWIDTH-1:0] rd_data,
input ready_n,
input do_release_n
);
localparam ADDR_WIDTH = SIZE > 128 ? 7 :
SIZE > 64 ? 6 :
SIZE > 32 ? 5 :
SIZE > 16 ? 4 :
SIZE > 8 ? 3 :
SIZE > 4 ? 2 :
SIZE > 2 ? 1 : 0;
localparam WIDTH = OWIDTH >= IWIDTH ? OWIDTH : IWIDTH;
reg [ADDR_WIDTH:0] wr_addr = 'h00;
reg [ADDR_WIDTH:0] rd_addr = 'h00;
(* ram_style = "distributed" *) reg [WIDTH-1:0] mem[0:SIZE - 1];
reg mem_rd_valid = 'b0;
reg [WIDTH-1:0] mem_rd_data;
wire mem_wr;
wire [WIDTH-1:0] mem_wr_data;
wire unpacker_ready;
generate if ((OWIDTH < IWIDTH) && ASYNC_CLK) begin
assign mem_wr = 1'b1;
always @(posedge clk) begin
if (ready_n) begin
wr_addr <= 'h00;
end else if (mem_wr) begin
wr_addr <= wr_addr + 1;
end
end
always @(posedge clk) begin
if (mem_wr) begin
mem[wr_addr] <= wr_data;
end
end
assign mem_rd_en = ~do_release_n & unpacker_ready;
always @(posedge device_clk) begin
if (mem_rd_en) begin
mem_rd_data <= mem[rd_addr];
end
mem_rd_valid <= mem_rd_en;
end
always @(posedge device_clk) begin
if (do_release_n) begin
rd_addr <= 'b0;
end else if (mem_rd_en) begin
rd_addr <= rd_addr + 1;
end
end
ad_upack #(
.I_W(IWIDTH/8),
.O_W(OWIDTH/8),
.UNIT_W(8),
.O_REG(0)
) i_ad_upack (
.clk(device_clk),
.reset(do_release_n),
.idata(mem_rd_data),
.ivalid(mem_rd_valid),
.iready(unpacker_ready),
.odata(rd_data),
.ovalid());
end else begin
if ((OWIDTH > IWIDTH) && ASYNC_CLK) begin
ad_pack #(
.I_W(IWIDTH/8),
.O_W(OWIDTH/8),
.UNIT_W(8)
) i_ad_pack (
.clk(clk),
.reset(ready_n),
.idata(wr_data),
.ivalid(1'b1),
.odata(mem_wr_data),
.ovalid(mem_wr));
end else begin
assign mem_wr = 1'b1;
assign mem_wr_data = wr_data;
end
always @(posedge clk) begin
if (ready_n == 1'b1) begin
wr_addr <= 'h00;
end else if (mem_wr) begin
mem[wr_addr] <= mem_wr_data;
wr_addr <= wr_addr + 1'b1;
end
end
always @(posedge device_clk) begin
if (do_release_n == 1'b1) begin
rd_addr <= 'h00;
end else begin
rd_addr <= rd_addr + 1'b1;
mem_rd_data <= mem[rd_addr];
end
end
assign rd_data = mem_rd_data;
end
endgenerate
endmodule
@@ -0,0 +1,53 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2020, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module error_monitor #(
parameter EVENT_WIDTH = 16,
parameter CNT_WIDTH = 32
) (
input clk,
input reset,
input active,
input [EVENT_WIDTH-1:0] error_event,
input [EVENT_WIDTH-1:0] error_event_mask,
output reg [CNT_WIDTH-1:0] status_err_cnt = 'h0
);
localparam EVENT_WIDTH_LOG = $clog2(EVENT_WIDTH);
reg [EVENT_WIDTH-1:0] err;
function [EVENT_WIDTH_LOG-1:0] num_set_bits;
input [EVENT_WIDTH-1:0] x;
integer j;
begin
num_set_bits = 0;
for (j = 0; j < EVENT_WIDTH; j = j + 1) begin
num_set_bits = num_set_bits + x[j];
end
end
endfunction
always @(posedge clk) begin
if (active == 1'b1) begin
err <= (~error_event_mask) & error_event;
end else begin
err <= {EVENT_WIDTH{1'b0}};
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
status_err_cnt <= 'h0;
end else if (~&status_err_cnt[CNT_WIDTH-1:EVENT_WIDTH_LOG]) begin
status_err_cnt <= status_err_cnt + num_set_bits(err);
end
end
endmodule
@@ -0,0 +1,3 @@
# This file is automatically written. Do not modify.
proc gen_USERPARAMETER_DATA_PATH_WIDTH_ENABLEMENT {LINK_MODE } {expr $LINK_MODE==1}
proc gen_USERPARAMETER_DATA_PATH_WIDTH_VALUE {LINK_MODE } {expr $LINK_MODE*4}
+123
View File
@@ -0,0 +1,123 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_ilas_monitor #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [9:0] cfg_octets_per_multiframe,
input [DATA_PATH_WIDTH*8-1:0] data,
input [DATA_PATH_WIDTH-1:0] charisk28,
output reg ilas_config_valid,
output reg [1:0] ilas_config_addr,
output reg [DATA_PATH_WIDTH*8-1:0] ilas_config_data,
output data_ready_n
);
localparam STATE_ILAS = 1'b1;
localparam STATE_DATA = 1'b0;
localparam ILAS_DATA_LENGTH = (DATA_PATH_WIDTH == 4) ? 4 : 2;
wire octets_per_mf_4_mod_8 = (DATA_PATH_WIDTH == 8) && ~cfg_octets_per_multiframe[2];
reg state = STATE_ILAS;
reg next_state;
reg prev_was_last = 1'b0;
wire ilas_config_start;
reg ilas_config_valid_i;
reg [1:0] ilas_config_addr_i;
reg [DATA_PATH_WIDTH*8-1:0] ilas_config_data_i;
assign data_ready_n = next_state;
always @(*) begin
next_state = state;
if (reset == 1'b0 && prev_was_last == 1'b1) begin
if (charisk28[0] != 1'b1 || data[7:5] != 3'h0) begin
next_state = STATE_DATA;
end
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
state <= STATE_ILAS;
end else begin
state <= next_state;
end
end
always @(posedge clk) begin
if (reset == 1'b1 || (charisk28[DATA_PATH_WIDTH-1] == 1'b1 && data[(DATA_PATH_WIDTH*8)-1:(DATA_PATH_WIDTH*8)-3] == 3'h3)) begin
prev_was_last <= 1'b1;
end else begin
prev_was_last <= 1'b0;
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
ilas_config_valid_i <= 1'b0;
end else if (state == STATE_ILAS) begin
if (ilas_config_start) begin
ilas_config_valid_i <= 1'b1;
end else if (ilas_config_addr_i == (ILAS_DATA_LENGTH-1)) begin
ilas_config_valid_i <= 1'b0;
end
end
end
always @(posedge clk) begin
if (ilas_config_valid_i == 1'b0) begin
ilas_config_addr_i <= 1'b0;
end else if (ilas_config_valid_i == 1'b1) begin
ilas_config_addr_i <= ilas_config_addr_i + 1'b1;
end
end
always @(posedge clk) begin
ilas_config_data_i <= data;
end
generate
if(DATA_PATH_WIDTH == 4) begin : gen_dp_4
assign ilas_config_start = charisk28[1] && (data[15:13] == 3'h4);
always @(*) begin
ilas_config_valid = ilas_config_valid_i;
ilas_config_addr = ilas_config_addr_i;
ilas_config_data = ilas_config_data_i;
end
end else begin : gen_dp_8
assign ilas_config_start = octets_per_mf_4_mod_8 ?
(charisk28[5] && (data[47:45] == 3'h4)) :
(charisk28[1] && (data[15:13] == 3'h4));
always @(posedge clk) begin
if (reset == 1'b1) begin
ilas_config_valid <= 1'b0;
end else begin
ilas_config_valid <= ilas_config_valid_i;
end
end
always @(posedge clk) begin
ilas_config_addr <= ilas_config_addr_i;
ilas_config_data <= octets_per_mf_4_mod_8 ? {data[31:0], ilas_config_data_i[63:32]} : ilas_config_data_i;
end
end
endgenerate
endmodule
@@ -0,0 +1,59 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2021, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_lane_latency_monitor #(
parameter NUM_LANES = 1,
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [NUM_LANES-1:0] lane_ready,
input [NUM_LANES*3-1:0] lane_frame_align,
output [14*NUM_LANES-1:0] lane_latency,
output [NUM_LANES-1:0] lane_latency_ready
);
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam BEAT_CNT_WIDTH = 14-DPW_LOG2;
reg [BEAT_CNT_WIDTH-1:0] beat_counter;
reg [BEAT_CNT_WIDTH-1:0] lane_latency_mem[0:NUM_LANES-1];
reg [NUM_LANES-1:0] lane_captured = 'h00;
always @(posedge clk) begin
if (reset == 1'b1) begin
beat_counter <= 'h0;
end else if (beat_counter != {BEAT_CNT_WIDTH{1'b1}}) begin
beat_counter <= beat_counter + 1'b1;
end
end
generate
genvar i;
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
always @(posedge clk) begin
if (reset == 1'b1) begin
lane_latency_mem[i] <= 'h00;
lane_captured[i] <= 1'b0;
end else if (lane_ready[i] == 1'b1 && lane_captured[i] == 1'b0) begin
lane_latency_mem[i] <= beat_counter;
lane_captured[i] <= 1'b1;
end
end
assign lane_latency[i*14+13:i*14] = {lane_latency_mem[i],lane_frame_align[(i*3)+DPW_LOG2-1:i*3]};
assign lane_latency_ready[i] = lane_captured[i];
end
endgenerate
endmodule
+574
View File
@@ -0,0 +1,574 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx #(
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter NUM_INPUT_PIPELINE = 1,
parameter NUM_OUTPUT_PIPELINE = 1,
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
/* Only 4 is supported at the moment for 8b/10b and 8 for 64b */
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4,
parameter ENABLE_FRAME_ALIGN_CHECK = 1,
parameter ENABLE_FRAME_ALIGN_ERR_RESET = 0,
parameter ENABLE_CHAR_REPLACE = 0,
parameter ASYNC_CLK = 1,
parameter TPL_DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input clk, // Link clock, lane rate / 40 or lane rate / 20 or lane rate / 66
input reset,
input device_clk, // Integer multiple of frame clock
input device_reset,
input [DATA_PATH_WIDTH*8*NUM_LANES-1:0] phy_data,
input [2*NUM_LANES-1:0] phy_header,
input [DATA_PATH_WIDTH*NUM_LANES-1:0] phy_charisk,
input [DATA_PATH_WIDTH*NUM_LANES-1:0] phy_notintable,
input [DATA_PATH_WIDTH*NUM_LANES-1:0] phy_disperr,
input [NUM_LANES-1:0] phy_block_sync,
input sysref,
output lmfc_edge,
output lmfc_clk,
output device_event_sysref_alignment_error,
output device_event_sysref_edge,
output event_frame_alignment_error,
output event_unexpected_lane_state_error,
output [NUM_LINKS-1:0] sync,
output phy_en_char_align,
output [TPL_DATA_PATH_WIDTH*8*NUM_LANES-1:0] rx_data,
output rx_valid,
output [TPL_DATA_PATH_WIDTH-1:0] rx_eof,
output [TPL_DATA_PATH_WIDTH-1:0] rx_sof,
output [TPL_DATA_PATH_WIDTH-1:0] rx_eomf,
output [TPL_DATA_PATH_WIDTH-1:0] rx_somf,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input cfg_disable_scrambler,
input cfg_disable_char_replacement,
input [7:0] cfg_frame_align_err_threshold,
input [9:0] device_cfg_octets_per_multiframe,
input [7:0] device_cfg_octets_per_frame,
input [7:0] device_cfg_beats_per_multiframe,
input [7:0] device_cfg_lmfc_offset,
input device_cfg_sysref_oneshot,
input device_cfg_sysref_disable,
input device_cfg_buffer_early_release,
input [7:0] device_cfg_buffer_delay,
input ctrl_err_statistics_reset,
input [6:0] ctrl_err_statistics_mask,
output [32*NUM_LANES-1:0] status_err_statistics_cnt,
output [NUM_LANES-1:0] ilas_config_valid,
output [NUM_LANES*2-1:0] ilas_config_addr,
output [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data,
output [1:0] status_ctrl_state,
output [2*NUM_LANES-1:0] status_lane_cgs_state,
output [NUM_LANES-1:0] status_lane_ifs_ready,
output [14*NUM_LANES-1:0] status_lane_latency,
output [3*NUM_LANES-1:0] status_lane_emb_state,
output [8*NUM_LANES-1:0] status_lane_frame_align_err_cnt,
output [31:0] status_synth_params0,
output [31:0] status_synth_params1,
output [31:0] status_synth_params2
);
/*
* Can be used to enable additional pipeline stages to ease timing. Usually not
* necessary.
*/
localparam CHAR_INFO_REGISTERED = 0;
localparam ALIGN_MUX_REGISTERED = 1;
localparam SCRAMBLER_REGISTERED = 0;
/*
* Maximum number of octets per multiframe for ADI JESD204 DACs is 256 (Adjust
* as necessary). Divide by data path width.
*/
localparam MAX_OCTETS_PER_FRAME = 32;
localparam MAX_OCTETS_PER_MULTIFRAME =
(MAX_OCTETS_PER_FRAME * 32) > 1024 ? 1024 : (MAX_OCTETS_PER_FRAME * 32);
localparam MAX_BEATS_PER_MULTIFRAME = MAX_OCTETS_PER_MULTIFRAME / DATA_PATH_WIDTH;
localparam ELASTIC_BUFFER_SIZE = MAX_BEATS_PER_MULTIFRAME;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam LMFC_COUNTER_WIDTH = MAX_BEATS_PER_MULTIFRAME > 256 ? 9 :
MAX_BEATS_PER_MULTIFRAME > 128 ? 8 :
MAX_BEATS_PER_MULTIFRAME > 64 ? 7 :
MAX_BEATS_PER_MULTIFRAME > 32 ? 6 :
MAX_BEATS_PER_MULTIFRAME > 16 ? 5 :
MAX_BEATS_PER_MULTIFRAME > 8 ? 4 :
MAX_BEATS_PER_MULTIFRAME > 4 ? 3 :
MAX_BEATS_PER_MULTIFRAME > 2 ? 2 : 1;
/* Helper for common expressions */
localparam DW = 8*DATA_PATH_WIDTH*NUM_LANES;
localparam ODW = 8*TPL_DATA_PATH_WIDTH*NUM_LANES;
localparam CW = DATA_PATH_WIDTH*NUM_LANES;
localparam HW = 2*NUM_LANES;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe >> DPW_LOG2;
wire [7:0] device_cfg_beats_per_multiframe_s;
wire [NUM_LANES-1:0] cgs_reset;
wire [NUM_LANES-1:0] cgs_ready;
wire [NUM_LANES-1:0] ifs_reset;
reg buffer_release_n = 1'b1;
reg buffer_release_d1 = 1'b0;
wire [NUM_LANES-1:0] buffer_ready_n;
wire all_buffer_ready_n;
wire dev_all_buffer_ready_n;
reg eof_reset = 1'b1;
wire [DW-1:0] phy_data_r;
wire [HW-1:0] phy_header_r;
wire [CW-1:0] phy_charisk_r;
wire [CW-1:0] phy_notintable_r;
wire [CW-1:0] phy_disperr_r;
wire [NUM_LANES-1:0] phy_block_sync_r;
wire [ODW-1:0] rx_data_s;
wire rx_valid_s = buffer_release_d1;
wire [7:0] lmfc_counter;
wire latency_monitor_reset;
wire [3*NUM_LANES-1:0] frame_align;
wire [NUM_LANES-1:0] ifs_ready;
wire event_data_phase;
wire err_statistics_reset;
wire lmfc_edge_synced;
reg [NUM_LANES-1:0] frame_align_err_thresh_met = {NUM_LANES{1'b0}};
reg [NUM_LANES-1:0] event_frame_alignment_error_per_lane = {NUM_LANES{1'b0}};
reg buffer_release_opportunity = 1'b0;
always @(posedge device_clk) begin
if (lmfc_counter == device_cfg_buffer_delay ||
device_cfg_buffer_early_release == 1'b1) begin
buffer_release_opportunity <= 1'b1;
end else begin
buffer_release_opportunity <= 1'b0;
end
end
assign all_buffer_ready_n = |(buffer_ready_n & ~cfg_lanes_disable);
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_all_buffer_ready_cdc (
.in_bits(all_buffer_ready_n),
.out_clk(device_clk),
.out_resetn(1'b1),
.out_bits(dev_all_buffer_ready_n));
always @(posedge device_clk) begin
if (device_reset == 1'b1) begin
buffer_release_n <= 1'b1;
end else begin
if (buffer_release_opportunity == 1'b1) begin
buffer_release_n <= dev_all_buffer_ready_n;
end
end
buffer_release_d1 <= ~buffer_release_n;
eof_reset <= buffer_release_n;
end
pipeline_stage #(
.WIDTH(NUM_LANES + (3 * CW) + HW + DW),
.REGISTERED(NUM_INPUT_PIPELINE)
) i_input_pipeline_stage (
.clk(clk),
.in({
phy_data,
phy_header,
phy_charisk,
phy_notintable,
phy_disperr,
phy_block_sync
}),
.out({
phy_data_r,
phy_header_r,
phy_charisk_r,
phy_notintable_r,
phy_disperr_r,
phy_block_sync_r
}));
pipeline_stage #(
.WIDTH(ODW+2),
.REGISTERED(NUM_OUTPUT_PIPELINE)
) i_output_pipeline_stage (
.clk(device_clk),
.in({
eof_reset,
rx_data_s,
rx_valid_s
}),
.out({
eof_reset_d,
rx_data,
rx_valid
}));
// If input and output widths are symmetric keep the calculation for backwards
// compatibility of the software.
assign device_cfg_beats_per_multiframe_s = (TPL_DATA_PATH_WIDTH == DATA_PATH_WIDTH) ?
device_cfg_octets_per_multiframe >> DPW_LOG2 :
device_cfg_beats_per_multiframe;
jesd204_lmfc #(
.LINK_MODE (LINK_MODE),
.DATA_PATH_WIDTH (TPL_DATA_PATH_WIDTH)
) i_lmfc (
.clk (device_clk),
.reset (device_reset),
.cfg_octets_per_multiframe (device_cfg_octets_per_multiframe),
.cfg_beats_per_multiframe (device_cfg_beats_per_multiframe_s),
.cfg_lmfc_offset (device_cfg_lmfc_offset),
.cfg_sysref_oneshot (device_cfg_sysref_oneshot),
.cfg_sysref_disable (device_cfg_sysref_disable),
.sysref (sysref),
.lmfc_edge (lmfc_edge),
.lmfc_clk (lmfc_clk),
.lmfc_counter (lmfc_counter),
.lmc_edge (),
.lmc_quarter_edge (),
.eoemb (),
.sysref_edge (device_event_sysref_edge),
.sysref_alignment_error (device_event_sysref_alignment_error));
jesd204_frame_mark #(
.DATA_PATH_WIDTH (TPL_DATA_PATH_WIDTH)
) i_frame_mark (
.clk (device_clk),
.reset (eof_reset_d),
.cfg_beats_per_multiframe (device_cfg_beats_per_multiframe_s),
.cfg_octets_per_multiframe (device_cfg_octets_per_multiframe),
.cfg_octets_per_frame (device_cfg_octets_per_frame),
.sof (rx_sof),
.eof (rx_eof),
.somf (rx_somf),
.eomf (rx_eomf));
generate
genvar i;
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_sync_lmfc (
.in_clk(device_clk),
.in_event(lmfc_edge),
.out_clk(clk),
.out_event(lmfc_edge_synced));
if (LINK_MODE[0] == 1) begin : mode_8b10b
wire unexpected_lane_state_error;
reg unexpected_lane_state_error_d = 1'b0;
jesd204_rx_ctrl #(
.NUM_LANES (NUM_LANES),
.NUM_LINKS (NUM_LINKS),
.ENABLE_FRAME_ALIGN_ERR_RESET (ENABLE_FRAME_ALIGN_ERR_RESET)
) i_rx_ctrl (
.clk (clk),
.reset (reset),
.cfg_lanes_disable (cfg_lanes_disable),
.cfg_links_disable (cfg_links_disable),
.phy_ready (1'b1),
.phy_en_char_align (phy_en_char_align),
.lmfc_edge (lmfc_edge_synced),
.frame_align_err_thresh_met (frame_align_err_thresh_met),
.sync (sync),
.latency_monitor_reset (latency_monitor_reset),
.cgs_reset (cgs_reset),
.cgs_ready (cgs_ready),
.ifs_reset (ifs_reset),
.status_state (status_ctrl_state),
.event_data_phase (event_data_phase));
assign err_statistics_reset = ctrl_err_statistics_reset ||
event_data_phase;
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
localparam D_STOP = D_START + DATA_PATH_WIDTH*8-1;
localparam OD_START = i * TPL_DATA_PATH_WIDTH*8;
localparam OD_STOP = OD_START + TPL_DATA_PATH_WIDTH*8-1;
localparam C_START = i * DATA_PATH_WIDTH;
localparam C_STOP = C_START + DATA_PATH_WIDTH-1;
jesd204_rx_lane #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.TPL_DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH),
.CHAR_INFO_REGISTERED(CHAR_INFO_REGISTERED),
.ALIGN_MUX_REGISTERED(ALIGN_MUX_REGISTERED),
.SCRAMBLER_REGISTERED(SCRAMBLER_REGISTERED),
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE),
.ENABLE_FRAME_ALIGN_CHECK(ENABLE_FRAME_ALIGN_CHECK),
.ENABLE_CHAR_REPLACE(ENABLE_CHAR_REPLACE),
.ASYNC_CLK(ASYNC_CLK)
) i_lane (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_charisk(phy_charisk_r[C_STOP:C_START]),
.phy_notintable(phy_notintable_r[C_STOP:C_START]),
.phy_disperr(phy_disperr_r[C_STOP:C_START]),
.cgs_reset(cgs_reset[i]),
.cgs_ready(cgs_ready[i]),
.ifs_reset(ifs_reset[i]),
.rx_data(rx_data_s[OD_STOP:OD_START]),
.buffer_release_n(buffer_release_n),
.buffer_ready_n(buffer_ready_n[i]),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.cfg_octets_per_frame(cfg_octets_per_frame),
.cfg_disable_char_replacement(cfg_disable_char_replacement),
.cfg_disable_scrambler(cfg_disable_scrambler),
.err_statistics_reset(err_statistics_reset),
.ctrl_err_statistics_mask(ctrl_err_statistics_mask[2:0]),
.status_err_statistics_cnt(status_err_statistics_cnt[32*i+31:32*i]),
.ilas_config_valid(ilas_config_valid[i]),
.ilas_config_addr(ilas_config_addr[2*i+1:2*i]),
.ilas_config_data(ilas_config_data[D_STOP:D_START]),
.status_cgs_state(status_lane_cgs_state[2*i+1:2*i]),
.status_ifs_ready(ifs_ready[i]),
.status_frame_align(frame_align[3*i+2:3*i]),
.status_frame_align_err_cnt(status_lane_frame_align_err_cnt[8*i+7:8*i]));
if(ENABLE_FRAME_ALIGN_CHECK) begin : gen_frame_align_err_thresh
always @(posedge clk) begin
if (reset) begin
frame_align_err_thresh_met[i] <= 1'b0;
event_frame_alignment_error_per_lane[i] <= 1'b0;
end else begin
if (status_lane_frame_align_err_cnt[8*i+7:8*i] >= cfg_frame_align_err_threshold) begin
frame_align_err_thresh_met[i] <= cgs_ready[i];
event_frame_alignment_error_per_lane[i] <= ~frame_align_err_thresh_met[i];
end else begin
frame_align_err_thresh_met[i] <= 1'b0;
event_frame_alignment_error_per_lane[i] <= 1'b0;
end
end
end
end else begin : gen_no_frame_align_err_thresh
always @(*) begin
frame_align_err_thresh_met[i] <= 1'b0;
event_frame_alignment_error_per_lane[i] <= 1'b0;
end
end
end
assign event_frame_alignment_error = |event_frame_alignment_error_per_lane;
/* If one of the enabled lanes falls out of DATA phase while the link is in DATA phase
* report an error event */
assign unexpected_lane_state_error = |(~(cgs_ready|cfg_lanes_disable)) & &status_ctrl_state;
always @(posedge clk) begin
unexpected_lane_state_error_d <= unexpected_lane_state_error;
end
assign event_unexpected_lane_state_error = unexpected_lane_state_error & ~unexpected_lane_state_error_d;
/* Delay matching based on the number of pipeline stages */
reg [NUM_LANES-1:0] ifs_ready_d1 = 1'b0;
reg [NUM_LANES-1:0] ifs_ready_d2 = 1'b0;
reg [NUM_LANES-1:0] ifs_ready_mux;
always @(posedge clk) begin
ifs_ready_d1 <= ifs_ready;
ifs_ready_d2 <= ifs_ready_d1;
end
always @(*) begin
case (SCRAMBLER_REGISTERED + ALIGN_MUX_REGISTERED)
1: ifs_ready_mux = ifs_ready_d1;
2: ifs_ready_mux = ifs_ready_d2;
default: ifs_ready_mux = ifs_ready;
endcase
end
jesd204_lane_latency_monitor #(
.NUM_LANES(NUM_LANES),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_lane_latency_monitor (
.clk(clk),
.reset(latency_monitor_reset),
.lane_ready(ifs_ready_mux),
.lane_frame_align(frame_align),
.lane_latency_ready(status_lane_ifs_ready),
.lane_latency(status_lane_latency));
assign status_lane_emb_state = 'b0;
end
if (LINK_MODE[1] == 1) begin : mode_64b66b
wire [NUM_LANES-1:0] emb_lock;
wire link_buffer_release_n;
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_buffer_release_cdc (
.in_bits(buffer_release_n),
.out_clk(clk),
.out_resetn(1'b1),
.out_bits(link_buffer_release_n));
jesd204_rx_ctrl_64b #(
.NUM_LANES(NUM_LANES)
) i_jesd204_rx_ctrl_64b (
.clk(clk),
.reset(reset),
.cfg_lanes_disable(cfg_lanes_disable),
.phy_block_sync(phy_block_sync_r),
.emb_lock(emb_lock),
.all_emb_lock(all_emb_lock),
.buffer_release_n(link_buffer_release_n),
.status_state(status_ctrl_state),
.event_unexpected_lane_state_error(event_unexpected_lane_state_error));
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
localparam D_STOP = D_START + DATA_PATH_WIDTH*8-1;
localparam TPL_D_START = i * TPL_DATA_PATH_WIDTH*8;
localparam TPL_D_STOP = TPL_D_START + TPL_DATA_PATH_WIDTH*8-1;
localparam H_START = i * 2;
localparam H_STOP = H_START + 2-1;
wire [7:0] status_lane_skew;
jesd204_rx_lane_64b #(
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE),
.TPL_DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH),
.ASYNC_CLK(ASYNC_CLK)
) i_lane (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_header(phy_header_r[H_STOP:H_START]),
.phy_block_sync(phy_block_sync_r[i]),
.cfg_disable_scrambler(cfg_disable_scrambler),
.cfg_header_mode(2'b0),
.cfg_rx_thresh_emb_err(5'd8),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.rx_data(rx_data_s[TPL_D_STOP:TPL_D_START]),
.buffer_release_n(buffer_release_n),
.buffer_ready_n(buffer_ready_n[i]),
.all_buffer_ready_n(all_buffer_ready_n),
.lmfc_edge(lmfc_edge_synced),
.emb_lock(emb_lock[i]),
.ctrl_err_statistics_reset(ctrl_err_statistics_reset),
.ctrl_err_statistics_mask(ctrl_err_statistics_mask[6:3]),
.status_err_statistics_cnt(status_err_statistics_cnt[32*i+31:32*i]),
.status_lane_emb_state(status_lane_emb_state[3*i+2:3*i]),
.status_lane_skew(status_lane_skew));
assign status_lane_latency[14*(i+1)-1:14*i] = {3'b0,status_lane_skew,3'b0};
end
// Assign unused outputs
assign sync = 'b0;
assign phy_en_char_align = 1'b0;
assign ilas_config_valid ='b0;
assign ilas_config_addr = 'b0;
assign ilas_config_data = 'b0;
assign status_lane_cgs_state = 'b0;
assign status_lane_ifs_ready = {NUM_LANES{1'b1}};
assign event_frame_alignment_error = 1'b0;
end
endgenerate
// Core static parameters
assign status_synth_params0 = {NUM_LANES};
assign status_synth_params1 = {
/*31:16 */ 16'b0,
/*15: 8 */ 1'b0,TPL_DATA_PATH_WIDTH[6:0],
/* 7: 0 */ 4'b0,DPW_LOG2[3:0]};
assign status_synth_params2 = {
/*31:19 */ 13'b0,
/* 18 */ ENABLE_CHAR_REPLACE[0],
/* 17 */ ENABLE_FRAME_ALIGN_ERR_RESET[0],
/* 16 */ ENABLE_FRAME_ALIGN_CHECK[0],
/*15:13 */ 3'b0,
/* 12 */ ASYNC_CLK[0],
/*11:10 */ 2'b0,
/* 9: 8 */ LINK_MODE[1:0],
/* 7: 0 */ NUM_LINKS[7:0]};
endmodule
@@ -0,0 +1,507 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Product Version: Vivado v2023.2.1 (64-bit) -->
<!-- -->
<!-- Copyright 1986-2022 Xilinx, Inc. All Rights Reserved. -->
<!-- Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved. -->
<Project Product="Vivado" Version="7" Minor="65" Path="/home/josh/tmp/hdl/library/jesd204/jesd204_rx/jesd204_rx.xpr">
<DefaultLaunch Dir="$PRUNDIR"/>
<Configuration>
<Option Name="Id" Val="cfc9f32b8125432197831f319320dfe5"/>
<Option Name="Part" Val="xc7vx485tffg1157-1"/>
<Option Name="CompiledLibDir" Val="$PCACHEDIR/compile_simlib"/>
<Option Name="CompiledLibDirXSim" Val=""/>
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
<Option Name="SimulatorInstallDirModelSim" Val=""/>
<Option Name="SimulatorInstallDirQuesta" Val=""/>
<Option Name="SimulatorInstallDirXcelium" Val=""/>
<Option Name="SimulatorInstallDirVCS" Val=""/>
<Option Name="SimulatorInstallDirRiviera" Val=""/>
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorGccInstallDirModelSim" Val=""/>
<Option Name="SimulatorGccInstallDirQuesta" Val=""/>
<Option Name="SimulatorGccInstallDirXcelium" Val=""/>
<Option Name="SimulatorGccInstallDirVCS" Val=""/>
<Option Name="SimulatorGccInstallDirRiviera" Val=""/>
<Option Name="SimulatorGccInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorVersionXsim" Val="2023.2"/>
<Option Name="SimulatorVersionModelSim" Val="2023.2"/>
<Option Name="SimulatorVersionQuesta" Val="2023.2"/>
<Option Name="SimulatorVersionXcelium" Val="23.03.002"/>
<Option Name="SimulatorVersionVCS" Val="U-2023.03-1"/>
<Option Name="SimulatorVersionRiviera" Val="2022.10"/>
<Option Name="SimulatorVersionActiveHdl" Val="14.1"/>
<Option Name="SimulatorGccVersionXsim" Val="9.3.0"/>
<Option Name="SimulatorGccVersionModelSim" Val="7.4.0"/>
<Option Name="SimulatorGccVersionQuesta" Val="7.4.0"/>
<Option Name="SimulatorGccVersionXcelium" Val="9.3.0"/>
<Option Name="SimulatorGccVersionVCS" Val="9.2.0"/>
<Option Name="SimulatorGccVersionRiviera" Val="9.3.0"/>
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
<Option Name="BoardPart" Val=""/>
<Option Name="SourceMgmtMode" Val="DisplayOnly"/>
<Option Name="ActiveSimSet" Val="sim_1"/>
<Option Name="DefaultLib" Val="xil_defaultlib"/>
<Option Name="ProjectType" Val="Default"/>
<Option Name="IPRepoPath" Val="$PPRDIR/../../../library"/>
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
<Option Name="IPDefaultOutputPath" Val="$PGENDIR/sources_1"/>
<Option Name="IPCachePermission" Val="read"/>
<Option Name="IPCachePermission" Val="write"/>
<Option Name="EnableCoreContainer" Val="FALSE"/>
<Option Name="EnableResourceEstimation" Val="FALSE"/>
<Option Name="SimCompileState" Val="TRUE"/>
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="FeatureSet" Val="FeatureSet_Classic"/>
<Option Name="WTXSimLaunchSim" Val="0"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
<Option Name="WTVcsLaunchSim" Val="0"/>
<Option Name="WTRivieraLaunchSim" Val="0"/>
<Option Name="WTActivehdlLaunchSim" Val="0"/>
<Option Name="WTXSimExportSim" Val="0"/>
<Option Name="WTModelSimExportSim" Val="0"/>
<Option Name="WTQuestaExportSim" Val="0"/>
<Option Name="WTIesExportSim" Val="0"/>
<Option Name="WTVcsExportSim" Val="0"/>
<Option Name="WTRivieraExportSim" Val="0"/>
<Option Name="WTActivehdlExportSim" Val="0"/>
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
<Option Name="XSimRadix" Val="hex"/>
<Option Name="XSimTimeUnit" Val="ns"/>
<Option Name="XSimArrayDisplayLimit" Val="1024"/>
<Option Name="XSimTraceLimit" Val="65536"/>
<Option Name="SimTypes" Val="rtl"/>
<Option Name="SimTypes" Val="bfm"/>
<Option Name="SimTypes" Val="tlm"/>
<Option Name="SimTypes" Val="tlm_dpi"/>
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
<Option Name="DcpsUptoDate" Val="TRUE"/>
<Option Name="ClassicSocBoot" Val="FALSE"/>
<Option Name="LocalIPRepoLeafDirName" Val="ip_repo"/>
</Configuration>
<FileSets Version="1" Minor="32">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/jesd204_rx_lane.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_lane_64b.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_header.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_cgs.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_ctrl.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_ctrl_64b.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/elastic_buffer.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/error_monitor.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_ilas_monitor.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/align_mux.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_lane_latency_monitor.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_frame_align.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/jesd204_rx_constr.ttcl"/>
<File Path="$PPRDIR/jesd204_rx_ooc.ttcl"/>
<File Path="$PPRDIR/jesd204_rx.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../../common/ad_pack.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../../common/ad_upack.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/bd/bd.tcl">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/component.xml">
<FileInfo SFType="IPXACT"/>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="jesd204_rx"/>
</Config>
</FileSet>
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1" RelGenDir="$PGENDIR/constrs_1">
<Filter Type="Constrs"/>
<Config>
<Option Name="ConstrsType" Val="XDC"/>
</Config>
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopAutoSet" Val="TRUE"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
<Option Name="PamDesignTestbench" Val=""/>
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
<Option Name="SrcSet" Val="sources_1"/>
</Config>
</FileSet>
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1" RelGenDir="$PGENDIR/utils_1">
<Filter Type="Utils"/>
<Config>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
</FileSets>
<Simulators>
<Simulator Name="XSim">
<Option Name="Description" Val="Vivado Simulator"/>
<Option Name="CompiledLib" Val="0"/>
</Simulator>
<Simulator Name="ModelSim">
<Option Name="Description" Val="ModelSim Simulator"/>
</Simulator>
<Simulator Name="Questa">
<Option Name="Description" Val="Questa Advanced Simulator"/>
</Simulator>
<Simulator Name="Xcelium">
<Option Name="Description" Val="Xcelium Parallel Simulator"/>
</Simulator>
<Simulator Name="VCS">
<Option Name="Description" Val="Verilog Compiler Simulator (VCS)"/>
</Simulator>
<Simulator Name="Riviera">
<Option Name="Description" Val="Riviera-PRO Simulator"/>
</Simulator>
</Simulators>
<Runs Version="1" Minor="21">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7vx485tffg1157-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="true" WriteIncrSynthDcp="false" State="current" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2023">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/>
</Strategy>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7vx485tffg1157-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2023">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
</Runs>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val="Vivado 12-1790"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="1"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
<MsgAttr Name="StringsToMatch" Val="Evaluation"/>
<MsgAttr Name="StringsToMatch" Val="features"/>
<MsgAttr Name="StringsToMatch" Val="should"/>
<MsgAttr Name="StringsToMatch" Val="NOT"/>
<MsgAttr Name="StringsToMatch" Val="be"/>
<MsgAttr Name="StringsToMatch" Val="used"/>
<MsgAttr Name="StringsToMatch" Val="in"/>
<MsgAttr Name="StringsToMatch" Val="production"/>
<MsgAttr Name="StringsToMatch" Val="systems."/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="INFO"/>
<MsgAttr Name="Id" Val="Designutils 20-3303"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="10"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
<MsgAttr Name="StringsToMatch" Val="HDPYFinalizeIO"/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val="Place 30-73"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="11"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
<MsgAttr Name="StringsToMatch" Val="axi_spi"/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val=""/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="12"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
<MsgAttr Name="StringsToMatch" Val="PCW_UIPARAM_DDR_DQS_TO_CLK_DELAY"/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val="BD 41-1343"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="2"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val="BD 41-1306"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="3"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="ERROR"/>
<MsgAttr Name="Id" Val="BD 41-1276"/>
<MsgAttr Name="Severity" Val="CRITICAL WARNING"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="4"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="INFO"/>
<MsgAttr Name="Id" Val="IP_Flow 19-3656"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="5"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="INFO"/>
<MsgAttr Name="Id" Val="IP_Flow 19-4623"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="6"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="INFO"/>
<MsgAttr Name="Id" Val="IP_Flow 19-459"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="7"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="INFO"/>
<MsgAttr Name="Id" Val="Synth 8-3331"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="8"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<MsgRule>
<MsgAttr Name="RuleType" Val="1"/>
<MsgAttr Name="Limit" Val="-1"/>
<MsgAttr Name="NewSeverity" Val="WARNING"/>
<MsgAttr Name="Id" Val="Synth 8-2490"/>
<MsgAttr Name="Severity" Val="ANY"/>
<MsgAttr Name="ShowRule" Val="1"/>
<MsgAttr Name="RuleSource" Val="2"/>
<MsgAttr Name="StringIsRegExp" Val="0"/>
<MsgAttr Name="RuleId" Val="9"/>
<MsgAttr Name="Note" Val=""/>
<MsgAttr Name="Author" Val=""/>
<MsgAttr Name="CreatedTimestamp" Val=""/>
</MsgRule>
<Board/>
<DashboardSummary Version="1" Minor="0">
<Dashboards>
<Dashboard Name="default_dashboard">
<Gadgets>
<Gadget Name="drc_1" Type="drc" Version="1" Row="2" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_drc_0 "/>
</Gadget>
<Gadget Name="methodology_1" Type="methodology" Version="1" Row="2" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_methodology_0 "/>
</Gadget>
<Gadget Name="power_1" Type="power" Version="1" Row="1" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_power_0 "/>
</Gadget>
<Gadget Name="timing_1" Type="timing" Version="1" Row="0" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_timing_summary_0 "/>
</Gadget>
<Gadget Name="utilization_1" Type="utilization" Version="1" Row="0" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="synth_1#synth_1_synth_report_utilization_0 "/>
<GadgetParam Name="RUN.STEP" Type="string" Value="synth_design"/>
<GadgetParam Name="RUN.TYPE" Type="string" Value="synthesis"/>
</Gadget>
<Gadget Name="utilization_2" Type="utilization" Version="1" Row="1" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_place_report_utilization_0 "/>
</Gadget>
</Gadgets>
</Dashboard>
<CurrentDashboard>default_dashboard</CurrentDashboard>
</Dashboards>
</DashboardSummary>
</Project>
@@ -0,0 +1,88 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_cgs #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [DATA_PATH_WIDTH-1:0] char_is_cgs,
input [DATA_PATH_WIDTH-1:0] char_is_error,
output ready,
output [1:0] status_state
);
localparam CGS_STATE_INIT = 2'b00;
localparam CGS_STATE_CHECK = 2'b01;
localparam CGS_STATE_DATA = 2'b10;
reg [1:0] state = CGS_STATE_INIT;
reg rdy = 1'b0;
reg [1:0] beat_error_count = 'h00;
wire beat_is_cgs = &char_is_cgs;
wire beat_has_error = |char_is_error;
wire beat_is_all_error = &char_is_error;
assign ready = rdy;
assign status_state = state;
always @(posedge clk) begin
if (state == CGS_STATE_INIT) begin
beat_error_count <= 'h00;
end else begin
if (beat_has_error == 1'b1) begin
beat_error_count <= beat_error_count + 1'b1;
end else begin
beat_error_count <= 'h00;
end
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
state <= CGS_STATE_INIT;
end else begin
case (state)
CGS_STATE_INIT: begin
if (beat_is_cgs == 1'b1) begin
state <= CGS_STATE_CHECK;
end
end
CGS_STATE_CHECK: begin
if (beat_has_error == 1'b1) begin
if (beat_error_count == 'h3 ||
beat_is_all_error == 1'b1) begin
state <= CGS_STATE_INIT;
end
end else begin
state <= CGS_STATE_DATA;
end
end
CGS_STATE_DATA: begin
if (beat_has_error == 1'b1) begin
state <= CGS_STATE_CHECK;
end
end
endcase
end
end
always @(posedge clk) begin
case (state)
CGS_STATE_INIT: rdy <= 1'b0;
CGS_STATE_DATA: rdy <= 1'b1;
default: rdy <= rdy;
endcase
end
endmodule
@@ -0,0 +1,15 @@
###############################################################################
## Copyright (C) 2017, 2020, 2021 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
set script_dir [file dirname [info script]]
source "$script_dir/util_cdc_constr.tcl"
# SYNC~ is a asynchronous interface
set_false_path \
-from [get_registers *|jesd204_rx_ctrl:i_rx_ctrl|sync_n[0]]
util_cdc_sync_bits_constr {*|sync_bits:i_all_buffer_ready_cdc}
util_cdc_sync_event_constr {*|sync_event:i_sync_lmfc}
@@ -0,0 +1,93 @@
###############################################################################
## Copyright (C) 2017, 2018, 2021 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
<: set ComponentName [getComponentNameString] :>
<: setOutputDirectory "./" :>
<: setFileName [ttcl_add $ComponentName "_constr"] :>
<: setFileExtension ".xdc" :>
<: setFileProcessingOrder late :>
<: set sysref_iob [get_property PARAM_VALUE.SYSREF_IOB] :>
<: set async_clk [getBooleanValue "ASYNC_CLK"] :>
<: set link_mode [getBooleanValue "LINK_MODE"] :>
set_property ASYNC_REG TRUE \
[get_cells {i_lmfc/sysref_d1_reg}] \
[get_cells {i_lmfc/sysref_d2_reg}]
# Make sure that the device clock to sysref skew is at least somewhat
# predictable
set_property IOB <=: $sysref_iob :> \
[get_cells {i_lmfc/sysref_r_reg}]
<: if {$async_clk} { :>
set link_clk [get_clocks -of_objects [get_ports -quiet {clk}]]
set device_clk [get_clocks -of_objects [get_ports -quiet {device_clk}]]
# sync bits
set_false_path \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_all_buffer_ready_cdc* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_all_buffer_ready_cdc* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage2_reg* \
-filter {NAME =~ *i_all_buffer_ready_cdc* && IS_SEQUENTIAL}]
# sync event i_sync_lmfc
set_false_path -quiet \
-from $device_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_out* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_out* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage2_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_out* && IS_SEQUENTIAL}]
set_false_path -quiet \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_in* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_in* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage2_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_in* && IS_SEQUENTIAL}]
# elastic buffer distributed RAM
set_false_path -quiet \
-from $link_clk \
-to [get_cells -quiet -hier *rd_data_reg* \
-filter {NAME =~ *i_elastic_buffer* && IS_SEQUENTIAL}]
<: if {$link_mode == 2} { :>
# sync bits i_buffer_release_cdc 64b66b
set_false_path \
-from $device_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_buffer_release_cdc* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_buffer_release_cdc* && IS_SEQUENTIAL}]
set_property ASYNC_REG TRUE \
[get_cells -quiet -hier *cdc_sync_stage2_reg* \
-filter {NAME =~ *i_buffer_release_cdc* && IS_SEQUENTIAL}]
<: } :>
<: } :>
+149
View File
@@ -0,0 +1,149 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_ctrl #(
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter ENABLE_FRAME_ALIGN_ERR_RESET = 0
) (
input clk,
input reset,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input phy_ready,
output phy_en_char_align,
output [NUM_LANES-1:0] cgs_reset,
input [NUM_LANES-1:0] cgs_ready,
output [NUM_LANES-1:0] ifs_reset,
input lmfc_edge,
input [NUM_LANES-1:0] frame_align_err_thresh_met,
output [NUM_LINKS-1:0] sync,
output reg latency_monitor_reset,
output [1:0] status_state,
output event_data_phase
);
localparam STATE_RESET = 0;
localparam STATE_WAIT_FOR_PHY = 1;
localparam STATE_CGS = 2;
localparam STATE_SYNCHRONIZED = 3;
reg [2:0] state = STATE_RESET;
reg [2:0] next_state = STATE_RESET;
reg [NUM_LANES-1:0] cgs_rst = {NUM_LANES{1'b1}};
reg [NUM_LANES-1:0] ifs_rst = {NUM_LANES{1'b1}};
reg [NUM_LINKS-1:0] sync_n = {NUM_LINKS{1'b1}};
reg en_align = 1'b0;
reg state_good = 1'b0;
reg [7:0] good_counter = 'h00;
wire [7:0] good_cnt_limit_s;
wire good_cnt_limit_reached_s;
wire goto_next_state_s;
assign cgs_reset = cgs_rst;
assign ifs_reset = ifs_rst;
assign sync = sync_n;
assign phy_en_char_align = en_align;
assign status_state = state;
always @(posedge clk) begin
case (state)
STATE_RESET: begin
cgs_rst <= {NUM_LANES{1'b1}};
ifs_rst <= {NUM_LANES{1'b1}};
sync_n <= {NUM_LINKS{1'b1}};
latency_monitor_reset <= 1'b1;
end
STATE_CGS: begin
sync_n <= cfg_links_disable;
cgs_rst <= cfg_lanes_disable;
end
STATE_SYNCHRONIZED: begin
if (lmfc_edge == 1'b1) begin
sync_n <= {NUM_LINKS{1'b1}};
ifs_rst <= cfg_lanes_disable;
latency_monitor_reset <= 1'b0;
end
end
endcase
end
always @(*) begin
case (state)
STATE_RESET: state_good = 1'b1;
STATE_WAIT_FOR_PHY: state_good = phy_ready;
STATE_CGS: state_good = &(cgs_ready | cfg_lanes_disable);
STATE_SYNCHRONIZED: state_good = ENABLE_FRAME_ALIGN_ERR_RESET ?
&(~frame_align_err_thresh_met | cfg_lanes_disable) :
1'b1;
default: state_good = 1'b0;
endcase
end
assign good_cnt_limit_s = (state == STATE_CGS) ? 'hff : 'h7;
assign good_cnt_limit_reached_s = good_counter == good_cnt_limit_s;
assign goto_next_state_s = good_cnt_limit_reached_s || (state == STATE_SYNCHRONIZED);
always @(posedge clk) begin
if (reset) begin
good_counter <= 'h00;
end else if (state_good == 1'b1) begin
if (good_cnt_limit_reached_s) begin
good_counter <= 'h00;
end else begin
good_counter <= good_counter + 1'b1;
end
end else begin
good_counter <= 'h00;
end
end
always @(posedge clk) begin
case (state)
STATE_CGS: en_align <= 1'b1;
default: en_align <= 1'b0;
endcase
end
always @(*) begin
case (state)
STATE_RESET: next_state = STATE_WAIT_FOR_PHY;
STATE_WAIT_FOR_PHY: next_state = STATE_CGS;
STATE_CGS: next_state = STATE_SYNCHRONIZED;
default: next_state = state_good ? state : STATE_RESET;
endcase
end
always @(posedge clk) begin
if (reset == 1'b1) begin
state <= STATE_RESET;
end else begin
if (goto_next_state_s) begin
state <= next_state;
end
end
end
assign event_data_phase = state == STATE_CGS &&
next_state == STATE_SYNCHRONIZED &&
good_cnt_limit_reached_s;
endmodule
@@ -0,0 +1,119 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_ctrl_64b #(
parameter NUM_LANES = 1
) (
input clk,
input reset,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LANES-1:0] phy_block_sync,
input [NUM_LANES-1:0] emb_lock,
output all_emb_lock,
input buffer_release_n,
output [1:0] status_state,
output reg event_unexpected_lane_state_error
);
localparam STATE_RESET = 2'b00;
localparam STATE_WAIT_BS = 2'b01;
localparam STATE_BLOCK_SYNC = 2'b10;
localparam STATE_DATA = 2'b11;
reg [1:0] state = STATE_RESET;
reg [1:0] next_state;
reg [5:0] good_cnt;
reg rst_good_cnt;
reg event_unexpected_lane_state_error_nx;
wire [NUM_LANES-1:0] phy_block_sync_masked;
wire [NUM_LANES-1:0] emb_lock_masked;
wire all_block_sync;
reg [NUM_LANES-1:0] emb_lock_d = {NUM_LANES{1'b0}};
reg buffer_release_d_n = 1'b1;
always @(posedge clk) begin
emb_lock_d <= emb_lock;
buffer_release_d_n <= buffer_release_n;
end
assign phy_block_sync_masked = phy_block_sync | cfg_lanes_disable;
assign emb_lock_masked = emb_lock_d | cfg_lanes_disable;
assign all_block_sync = &phy_block_sync_masked;
assign all_emb_lock = &emb_lock_masked;
always @(*) begin
next_state = state;
rst_good_cnt = 1'b1;
event_unexpected_lane_state_error_nx = 1'b0;
case (state)
STATE_RESET:
next_state = STATE_WAIT_BS;
STATE_WAIT_BS:
if (all_block_sync) begin
rst_good_cnt = 1'b0;
if (&good_cnt) begin
next_state = STATE_BLOCK_SYNC;
end
end
STATE_BLOCK_SYNC:
if (~all_block_sync) begin
next_state = STATE_WAIT_BS;
end else if (all_emb_lock & ~buffer_release_d_n) begin
rst_good_cnt = 1'b0;
if (&good_cnt) begin
next_state = STATE_DATA;
end
end
STATE_DATA:
if (~all_block_sync) begin
next_state = STATE_WAIT_BS;
event_unexpected_lane_state_error_nx = 1'b1;
end else if (~all_emb_lock | buffer_release_d_n) begin
next_state = STATE_BLOCK_SYNC;
event_unexpected_lane_state_error_nx = 1'b1;
end
endcase
end
// Wait n consecutive valid cycles before jumping into next state
always @(posedge clk) begin
if (reset || rst_good_cnt) begin
good_cnt <= 'h0;
end else begin
good_cnt <= good_cnt + 1;
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
state <= STATE_RESET;
end else begin
state <= next_state;
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
event_unexpected_lane_state_error <= 1'b0;
end else begin
event_unexpected_lane_state_error <= event_unexpected_lane_state_error_nx;
end
end
assign status_state = state;
endmodule
+162
View File
@@ -0,0 +1,162 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_frame_align #(
parameter DATA_PATH_WIDTH = 4,
parameter ENABLE_CHAR_REPLACE = 0
) (
input clk,
input reset,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
input [DATA_PATH_WIDTH-1:0] charisk28,
input [DATA_PATH_WIDTH*8-1:0] data,
output [DATA_PATH_WIDTH*8-1:0] data_replaced,
output reg [7:0] align_err_cnt
);
// Reset alignment error count on good multiframe alignment,
// or on good frame or multiframe alignment
// If disabled, misalignments could me masked if
// due to cfg_octets_per_multiframe mismatch or due to
// a slip of a multiple of cfg_octets_per_frame octets
localparam RESET_COUNT_ON_MF_ONLY = 1'b1;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 :
DATA_PATH_WIDTH == 4 ? 2 : 1;
function automatic [DPW_LOG2*2:0] count_ones(input [DATA_PATH_WIDTH*2-1:0] val);
reg [DPW_LOG2*2-1:0] ii;
begin
count_ones = 0;
for(ii = 0; ii != (DATA_PATH_WIDTH*2-1); ii=ii+1) begin
count_ones = count_ones + val[ii];
end
end
endfunction
reg [DATA_PATH_WIDTH-1:0] char_is_a;
reg [DATA_PATH_WIDTH-1:0] char_is_f;
wire [DATA_PATH_WIDTH-1:0] eof;
wire [DATA_PATH_WIDTH-1:0] eomf;
reg [DATA_PATH_WIDTH-1:0] eof_err;
reg [DATA_PATH_WIDTH-1:0] eof_good;
reg [DATA_PATH_WIDTH-1:0] eomf_err;
reg [DATA_PATH_WIDTH-1:0] eomf_good;
reg align_good;
reg align_err;
reg [DPW_LOG2*2:0] cur_align_err_cnt;
wire [8:0] align_err_cnt_next;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe>>DPW_LOG2;
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) i_frame_mark (
.clk (clk),
.reset (reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_beats_per_multiframe (cfg_beats_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (),
.eof (eof),
.somf (),
.eomf (eomf));
genvar ii;
generate
for (ii = 0; ii < DATA_PATH_WIDTH; ii = ii + 1) begin: gen_k_char
always @(*) begin
char_is_a[ii] = 1'b0;
char_is_f[ii] = 1'b0;
if(charisk28[ii]) begin
if(data[ii*8+7:ii*8+5] == 3'd3) begin
char_is_a[ii] = 1'b1;
end
if(data[ii*8+7:ii*8+5] == 3'd7) begin
char_is_f[ii] = 1'b1;
end
end
end
always @(posedge clk) begin
if(reset) begin
eomf_err[ii] <= 1'b0;
eomf_good[ii] <= 1'b0;
eof_err[ii] <= 1'b0;
eof_good[ii] <= 1'b0;
end else begin
eomf_err[ii] <= char_is_a[ii] && !eomf[ii];
eomf_good[ii] <= char_is_a[ii] && eomf[ii];
eof_err[ii] <= char_is_f[ii] && !eof[ii];
eof_good[ii] <= char_is_f[ii] && eof[ii];
end
end
end
endgenerate
always @(posedge clk) begin
if(reset) begin
align_good <= 1'b0;
align_err <= 1'b0;
end else begin
if(RESET_COUNT_ON_MF_ONLY) begin
align_good <= |eomf_good;
end else begin
align_good <= |({eomf_good, eof_good});
end
align_err <= |({eomf_err, eof_err});
end
end
assign align_err_cnt_next = {1'b0, align_err_cnt} + cur_align_err_cnt;
// Alignment error counter
// Resets upon good alignment
always @(posedge clk) begin
if(reset) begin
align_err_cnt <= 8'd0;
cur_align_err_cnt <= 'd0;
end else begin
cur_align_err_cnt <= count_ones({eomf_err, eof_err});
if(align_good && !align_err) begin
align_err_cnt <= 8'd0;
end else if(align_err_cnt_next[8]) begin
align_err_cnt <= 8'hFF;
end else begin
align_err_cnt <= align_err_cnt_next[7:0];
end
end
end
jesd204_frame_align_replace #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.IS_RX (1'b1),
.ENABLED (ENABLE_CHAR_REPLACE)
) i_align_replace (
.clk (clk),
.reset (reset),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.data (data),
.eof (eof),
.rx_char_is_a (char_is_a),
.rx_char_is_f (char_is_f),
.tx_eomf ({DATA_PATH_WIDTH{1'b0}}),
.data_out (data_replaced),
.charisk_out ());
endmodule
@@ -0,0 +1,166 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2020, 2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_header (
input clk,
input reset,
input sh_lock,
input [1:0] header,
input [1:0] cfg_header_mode, // 0 - CRC12 ; 1 - CRC3; 2 - FEC; 3 - CMD
input [4:0] cfg_rx_thresh_emb_err,
input [7:0] cfg_beats_per_multiframe,
output emb_lock,
output valid_eomb,
output valid_eoemb,
// Received header data qualified by valid_eomb
output [11:0] crc12,
output [2:0] crc3,
output [25:0] fec,
output [18:0] cmd,
output reg [7:0] sh_count = 'h0,
output [2:0] status_lane_emb_state,
output reg event_invalid_header,
output reg event_unexpected_eomb,
output reg event_unexpected_eoemb
);
localparam STATE_EMB_INIT = 3'b001;
localparam STATE_EMB_HUNT = 3'b010;
localparam STATE_EMB_LOCK = 3'b100;
localparam BIT_EMB_INIT = 0;
localparam BIT_EMB_HUNT = 1;
localparam BIT_EMB_LOCK = 2;
reg [2:0] state = STATE_EMB_INIT;
reg [2:0] next_state;
reg [31:0] sync_word = 'h0;
wire header_bit;
wire invalid_sequence;
wire invalid_eoemb;
wire invalid_eomb;
wire [6:0] cmd0;
wire [6:0] cmd1;
wire [18:0] cmd3;
wire eoemb;
wire eomb;
assign header_bit = header == 2'b01;
always @(posedge clk) begin
sync_word <= {sync_word[30:0],header_bit};
end
assign crc12 = {sync_word[31:29],sync_word[27:25],
sync_word[23:21],sync_word[19:17]};
assign crc3 = {sync_word[31:29]};
assign cmd0 = {sync_word[15:13],sync_word[11],
sync_word[7:5]};
assign cmd1 = {sync_word[27:25],
sync_word[19:17],
sync_word[11]};
assign cmd3 = {sync_word[31:29],sync_word[27:25],
sync_word[23:21],sync_word[19:17],
sync_word[15:13],sync_word[11],
sync_word[7:5]};
assign cmd = cfg_header_mode == 0 ? {12'b0,cmd0} :
cfg_header_mode == 1 ? {12'b0,cmd1} :
cfg_header_mode == 3 ? cmd3 : 'b0;
assign fec = {sync_word[31:10],sync_word[8:5]};
assign eomb = sync_word[4:0] == 5'b00001;
assign eoemb = sync_word[9] & eomb;
always @(posedge clk) begin
if (next_state[BIT_EMB_INIT] || sh_count == cfg_beats_per_multiframe) begin
sh_count <= 'h0;
end else begin
sh_count <= sh_count + 8'b1;
end
end
reg [1:0] emb_vcount = 'b0;
always @(posedge clk) begin
if (state[BIT_EMB_INIT]) begin
emb_vcount <= 'b0;
end else if (state[BIT_EMB_HUNT] && (sh_count == 0 && eoemb)) begin
emb_vcount <= emb_vcount + 'b1;
end
end
reg [4:0] emb_icount = 'b0;
always @(posedge clk) begin
if (state[BIT_EMB_INIT]) begin
emb_icount <= 'b0;
end else if (state[BIT_EMB_LOCK]) begin
if (sh_count == 0 && eoemb) begin
emb_icount <= 'b0;
end else if (invalid_eoemb || invalid_eomb) begin
emb_icount <= emb_icount + 5'b1;
end
end
end
always @(*) begin
next_state = state;
case (state)
STATE_EMB_INIT:
if (eoemb) begin
next_state = STATE_EMB_HUNT;
end
STATE_EMB_HUNT:
if (invalid_sequence) begin
next_state = STATE_EMB_INIT;
end else if (eoemb && emb_vcount == 2'd3) begin
next_state = STATE_EMB_LOCK;
end
STATE_EMB_LOCK:
if (emb_icount == cfg_rx_thresh_emb_err) begin
next_state = STATE_EMB_INIT;
end
endcase
if (sh_lock == 1'b0) next_state = STATE_EMB_INIT;
end
assign invalid_eoemb = (sh_count == 0 && ~eoemb);
assign invalid_eomb = (sh_count[4:0] == 0 && ~eomb);
assign valid_eomb = next_state[BIT_EMB_LOCK] && eomb;
assign valid_eoemb = next_state[BIT_EMB_LOCK] && eoemb;
assign invalid_sequence = (invalid_eoemb || invalid_eomb);
always @(posedge clk) begin
if (reset == 1'b1) begin
state <= STATE_EMB_INIT;
end else begin
state <= next_state;
end
end
assign emb_lock = next_state[BIT_EMB_LOCK];
// Status & error events
assign status_lane_emb_state = state;
always @(posedge clk) begin
event_invalid_header <= (~state[BIT_EMB_INIT]) && (header[0] == header[1]);
event_unexpected_eomb <= (~state[BIT_EMB_INIT]) && (sh_count[4:0] != 0 && eomb);
event_unexpected_eoemb <= (~state[BIT_EMB_INIT]) && invalid_eoemb;
end
endmodule
+244
View File
@@ -0,0 +1,244 @@
###############################################################################
## Copyright (C) 2017-2022 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
package require qsys 14.0
source ../../../scripts/adi_env.tcl
source $ad_hdl_dir/library/scripts/adi_ip_intel.tcl
ad_ip_create jesd204_rx "ADI JESD204 Receive" jesd204_rx_elaboration_callback
set_module_property INTERNAL true
# files
ad_ip_files jesd204_rx [list \
jesd204_rx.v \
align_mux.v \
elastic_buffer.v \
jesd204_ilas_monitor.v \
jesd204_lane_latency_monitor.v \
jesd204_rx_cgs.v \
jesd204_rx_ctrl.v \
jesd204_rx_lane.v \
jesd204_rx_frame_align.v \
jesd204_rx_constr.sdc \
../jesd204_common/jesd204_eof_generator.v \
../jesd204_common/jesd204_frame_mark.v \
../jesd204_common/jesd204_frame_align_replace.v \
../jesd204_common/jesd204_lmfc.v \
../jesd204_common/jesd204_scrambler.v \
../jesd204_common/pipeline_stage.v \
$ad_hdl_dir/library/util_cdc/sync_bits.v \
$ad_hdl_dir/library/util_cdc/sync_data.v \
$ad_hdl_dir/library/util_cdc/sync_event.v \
$ad_hdl_dir/library/util_cdc/util_cdc_constr.tcl \
../../common/ad_pack.v \
../../common/ad_upack.v \
]
# parameters
add_parameter NUM_LANES INTEGER 1
set_parameter_property NUM_LANES DISPLAY_NAME "Number of Lanes"
set_parameter_property NUM_LANES ALLOWED_RANGES 1:32
set_parameter_property NUM_LANES HDL_PARAMETER true
add_parameter NUM_LINKS INTEGER 1
set_parameter_property NUM_LINKS DISPLAY_NAME "Number of Links"
set_parameter_property NUM_LINKS ALLOWED_RANGES 1:8
set_parameter_property NUM_LINKS HDL_PARAMETER true
add_parameter NUM_INPUT_PIPELINE INTEGER 1
set_parameter_property NUM_INPUT_PIPELINE DISPLAY_NAME "Number of input pipeline stages"
set_parameter_property NUM_INPUT_PIPELINE ALLOWED_RANGES 1:3
set_parameter_property NUM_INPUT_PIPELINE HDL_PARAMETER true
add_parameter ASYNC_CLK BOOLEAN false
set_parameter_property ASYNC_CLK DISPLAY_NAME "Link and device clock asynchronous"
set_parameter_property ASYNC_CLK HDL_PARAMETER true
ad_ip_parameter TPL_DATA_PATH_WIDTH INTEGER 4 true { \
DISPLAY_NAME "Transport layer datapath width" \
DISPLAY_UNITS "octets" \
ALLOWED_RANGES {4 6 8 12} \
}
#ad_ip_parameter PORT_ENABLE_RX_EOF BOOLEAN false false
#ad_ip_parameter PORT_ENABLE_LMFC_CLK BOOLEAN false false
#ad_ip_parameter PORT_ENABLE_LMFC_EDGE BOOLEAN false false
# link clock
add_interface clock clock end
add_interface_port clock clk clk Input 1
# link clock reset
add_interface reset reset end
set_interface_property reset associatedClock clock
set_interface_property reset synchronousEdges DEASSERT
add_interface_port reset reset reset Input 1
# device clock
add_interface device_clock clock end
add_interface_port device_clock device_clk clk Input 1
# device clock reset
add_interface device_reset reset end
set_interface_property device_reset associatedClock device_clock
set_interface_property device_reset synchronousEdges DEASSERT
add_interface_port device_reset device_reset reset Input 1
# SYSREF~ interface
add_interface sysref conduit end
set_interface_property sysref associatedClock device_clock
set_interface_property sysref associatedReset device_reset
add_interface_port sysref sysref export Input 1
# SYNC interface
add_interface sync conduit end
set_interface_property sync associatedClock clock
set_interface_property sync associatedReset reset
add_interface_port sync sync export Output NUM_LINKS
# link clock domain config interface
add_interface config conduit end
set_interface_property config associatedClock clock
set_interface_property config associatedReset reset
add_interface_port config cfg_lanes_disable lanes_disable Input NUM_LANES
add_interface_port config cfg_links_disable links_disable Input NUM_LINKS
add_interface_port config cfg_octets_per_multiframe octets_per_multiframe Input 10
add_interface_port config cfg_octets_per_frame octets_per_frame Input 8
add_interface_port config cfg_disable_scrambler disable_scrambler Input 1
add_interface_port config cfg_disable_char_replacement disable_char_replacement Input 1
add_interface_port config cfg_frame_align_err_threshold frame_align_err_threshold Input 8
add_interface_port config ctrl_err_statistics_reset err_statistics_reset Input 1
add_interface_port config ctrl_err_statistics_mask err_statistics_mask Input 3
# device clock domain config interface
add_interface device_config conduit end
set_interface_property device_config associatedClock device_clock
set_interface_property device_config associatedReset device_reset
add_interface_port device_config device_cfg_octets_per_multiframe octets_per_multiframe Input 10
add_interface_port device_config device_cfg_octets_per_frame octets_per_frame Input 8
add_interface_port device_config device_cfg_beats_per_multiframe beats_per_multiframe Input 8
add_interface_port device_config device_cfg_lmfc_offset lmfc_offset Input 8
add_interface_port device_config device_cfg_sysref_disable sysref_disable Input 1
add_interface_port device_config device_cfg_sysref_oneshot sysref_oneshot Input 1
add_interface_port device_config device_cfg_buffer_delay buffer_delay Input 8
add_interface_port device_config device_cfg_buffer_early_release buffer_early_release Input 1
# status interface
add_interface status conduit end
set_interface_property status associatedClock clock
set_interface_property status associatedReset reset
add_interface_port status status_ctrl_state ctrl_state Output 2
add_interface_port status status_lane_cgs_state lane_cgs_state Output 2*NUM_LANES
add_interface_port status status_lane_ifs_ready lane_ifs_ready Output NUM_LANES
add_interface_port status status_lane_latency lane_latency Output 14*NUM_LANES
add_interface_port status status_err_statistics_cnt err_statistics_cnt Output 32*NUM_LANES
add_interface_port status status_lane_frame_align_err_cnt lane_frame_align_err_cnt Output 8*NUM_LANES
add_interface_port status status_synth_params0 synth_params0 Output 32
add_interface_port status status_synth_params1 synth_params1 Output 32
add_interface_port status status_synth_params2 synth_params2 Output 32
# event interface
add_interface device_event conduit end
set_interface_property device_event associatedClock device_clock
set_interface_property device_event associatedReset device_reset
add_interface_port device_event device_event_sysref_alignment_error sysref_alignment_error Output 1
add_interface_port device_event device_event_sysref_edge sysref_edge Output 1
# ilas_config interface
add_interface ilas_config conduit end
set_interface_property ilas_config associatedClock clock
set_interface_property ilas_config associatedReset reset
add_interface_port ilas_config ilas_config_addr addr Output NUM_LANES*2
add_interface_port ilas_config ilas_config_data data Output NUM_LANES*32
add_interface_port ilas_config ilas_config_valid valid Output NUM_LANES
# rx_eof interface
add_interface rx_eof conduit end
#set_interface_property rx_eof associatedClock clock
#set_interface_property rx_eof associatedReset reset
add_interface_port rx_eof rx_eof export Output 4
set_port_property rx_eof TERMINATION TRUE
# rx_sof interface
add_interface rx_sof conduit end
#set_interface_property rx_sof associatedClock clock
#set_interface_property rx_sof associatedReset reset
add_interface_port rx_sof rx_sof export Output 4
# lmfc_clk interface
add_interface lmfc_clk conduit end
#set_interface_property lmfc_clk associatedClock clock
#set_interface_property lmfc_clk associatedReset reset
add_interface_port lmfc_clk lmfc_clk export Output 1
set_port_property lmfc_clk TERMINATION TRUE
# lmfc_edge interface
add_interface lmfc_edge conduit end
#set_interface_property lmfc_edge associatedClock clock
#set_interface_property lmfc_edge associatedReset reset
add_interface_port lmfc_edge lmfc_edge export Output 1
set_port_property lmfc_edge TERMINATION TRUE
proc jesd204_rx_elaboration_callback {} {
set num_lanes [get_parameter_value "NUM_LANES"]
set tpl_width [get_parameter_value "TPL_DATA_PATH_WIDTH"]
# rx_data interface
add_interface rx_data avalon_streaming source
set_interface_property rx_data associatedClock device_clock
add_interface_port rx_data rx_data data output [expr 8*$tpl_width*$num_lanes]
add_interface_port rx_data rx_valid valid output 1
set_interface_property rx_data dataBitsPerSymbol [expr 8*$tpl_width*$num_lanes]
# phy interfaces
for {set i 0 } {$i < $num_lanes} {incr i} {
add_interface rx_phy${i} conduit end
# set_interface_property rx_phy${i} associatedClock clock
# set_interface_property rx_phy${i} associatedReset reset
add_interface_port rx_phy${i} rx_phy${i}_data char Input 32
set_port_property rx_phy${i}_data fragment_list \
[format "phy_data(%d:%d)" [expr 32*$i+31] [expr 32*$i]]
add_interface_port rx_phy${i} rx_phy${i}_charisk charisk Input 4
set_port_property rx_phy${i}_charisk fragment_list \
[format "phy_charisk(%d:%d)" [expr 4*$i+3] [expr 4*$i]]
add_interface_port rx_phy${i} rx_phy${i}_disperr disperr Input 4
set_port_property rx_phy${i}_disperr fragment_list \
[format "phy_disperr(%d:%d)" [expr 4*$i+3] [expr 4*$i]]
add_interface_port rx_phy${i} rx_phy${i}_notintable notintable Input 4
set_port_property rx_phy${i}_notintable fragment_list \
[format "phy_notintable(%d:%d)" [expr 4*$i+3] [expr 4*$i]]
add_interface_port rx_phy${i} rx_phy${i}_patternalign_en patternalign_en Output 1
set_port_property rx_phy${i}_patternalign_en fragment_list "phy_en_char_align"
}
}
+195
View File
@@ -0,0 +1,195 @@
###############################################################################
## Copyright (C) 2017-2023 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
source ../../../scripts/adi_env.tcl
source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl
global VIVADO_IP_LIBRARY
adi_ip_create jesd204_rx
adi_ip_files jesd204_rx [list \
"jesd204_rx_lane.v" \
"jesd204_rx_lane_64b.v" \
"jesd204_rx_header.v" \
"jesd204_rx_cgs.v" \
"jesd204_rx_ctrl.v" \
"jesd204_rx_ctrl_64b.v" \
"elastic_buffer.v" \
"error_monitor.v" \
"jesd204_ilas_monitor.v" \
"align_mux.v" \
"jesd204_lane_latency_monitor.v" \
"jesd204_rx_frame_align.v" \
"jesd204_rx_constr.ttcl" \
"jesd204_rx_ooc.ttcl" \
"jesd204_rx.v" \
"../../common/ad_pack.v" \
"../../common/ad_upack.v" \
"bd/bd.tcl"
]
set_property source_mgmt_mode DisplayOnly [current_project]
adi_ip_properties_lite jesd204_rx
adi_ip_ttcl jesd204_rx "jesd204_rx_constr.ttcl"
adi_ip_ttcl jesd204_rx "jesd204_rx_ooc.ttcl"
adi_ip_bd jesd204_rx "bd/bd.tcl"
adi_ip_add_core_dependencies [list \
analog.com:$VIVADO_IP_LIBRARY:jesd204_common:1.0 \
analog.com:$VIVADO_IP_LIBRARY:util_cdc:1.0 \
]
set_property display_name "ADI JESD204 Receive" [ipx::current_core]
set_property description "ADI JESD204 Receive" [ipx::current_core]
#adi_add_bus "rx_data" "master" \
# "xilinx.com:interface:axis_rtl:1.0" \
# "xilinx.com:interface:axis:1.0" \
# { \
# { "rx_valid" "TVALID" } \
# { "rx_data" "TDATA" } \
# }
adi_add_multi_bus 32 "rx_phy" "slave" \
"xilinx.com:display_jesd204:jesd204_rx_bus_rtl:1.0" \
"xilinx.com:display_jesd204:jesd204_rx_bus:1.0" \
[list \
{ "phy_data" "rxdata" 32 "(spirit:decode(id('MODELPARAM_VALUE.DATA_PATH_WIDTH')) * 8)"} \
{ "phy_charisk" "rxcharisk" 4 "(spirit:decode(id('MODELPARAM_VALUE.DATA_PATH_WIDTH')))"} \
{ "phy_disperr" "rxdisperr" 4 "(spirit:decode(id('MODELPARAM_VALUE.DATA_PATH_WIDTH')))"} \
{ "phy_notintable" "rxnotintable" 4 "(spirit:decode(id('MODELPARAM_VALUE.DATA_PATH_WIDTH')))"} \
{ "phy_header" "rxheader" 2} \
{ "phy_block_sync" "rxblock_sync" 1} \
] \
"(spirit:decode(id('MODELPARAM_VALUE.NUM_LANES')) > {i})"
set_property driver_value 0 [ipx::get_ports phy_charisk -of_objects [ipx::current_core]]
set_property driver_value 0 [ipx::get_ports phy_disperr -of_objects [ipx::current_core]]
set_property driver_value 0 [ipx::get_ports phy_notintable -of_objects [ipx::current_core]]
adi_add_bus "rx_cfg" "slave" \
"analog.com:interface:jesd204_rx_cfg_rtl:1.0" \
"analog.com:interface:jesd204_rx_cfg:1.0" \
{ \
{ "cfg_lanes_disable" "lanes_disable" } \
{ "cfg_links_disable" "links_disable" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_disable_scrambler" "disable_scrambler" } \
{ "cfg_disable_char_replacement" "disable_char_replacement" } \
{ "cfg_frame_align_err_threshold" "frame_align_err_threshold" } \
{ "device_cfg_octets_per_multiframe" "device_octets_per_multiframe" } \
{ "device_cfg_octets_per_frame" "device_octets_per_frame" } \
{ "device_cfg_beats_per_multiframe" "device_beats_per_multiframe" } \
{ "device_cfg_lmfc_offset" "device_lmfc_offset" } \
{ "device_cfg_sysref_oneshot" "device_sysref_oneshot" } \
{ "device_cfg_sysref_disable" "device_sysref_disable" } \
{ "device_cfg_buffer_delay" "device_buffer_delay" } \
{ "device_cfg_buffer_early_release" "device_buffer_early_release" } \
{ "ctrl_err_statistics_reset" "err_statistics_reset" } \
{ "ctrl_err_statistics_mask" "err_statistics_mask" } \
}
adi_add_bus "rx_status" "master" \
"analog.com:interface:jesd204_rx_status_rtl:1.0" \
"analog.com:interface:jesd204_rx_status:1.0" \
{ \
{ "status_ctrl_state" "ctrl_state" } \
{ "status_lane_cgs_state" "lane_cgs_state" } \
{ "status_lane_emb_state" "lane_emb_state" } \
{ "status_err_statistics_cnt" "err_statistics_cnt" } \
{ "status_lane_ifs_ready" "lane_ifs_ready" } \
{ "status_lane_latency" "lane_latency" } \
{ "status_lane_frame_align_err_cnt" "lane_frame_align_err_cnt" } \
{ "status_synth_params0" "synth_params0" } \
{ "status_synth_params1" "synth_params1" } \
{ "status_synth_params2" "synth_params2" } \
}
adi_add_bus "rx_ilas_config" "master" \
"analog.com:interface:jesd204_rx_ilas_config_rtl:1.0" \
"analog.com:interface:jesd204_rx_ilas_config:1.0" \
{ \
{ "ilas_config_valid" "valid" } \
{ "ilas_config_addr" "addr" } \
{ "ilas_config_data" "data" } \
}
adi_add_bus "rx_event" "master" \
"analog.com:interface:jesd204_rx_event_rtl:1.0" \
"analog.com:interface:jesd204_rx_event:1.0" \
{ \
{ "device_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "device_event_sysref_edge" "sysref_edge" } \
{ "event_frame_alignment_error" "frame_alignment_error" } \
{ "event_unexpected_lane_state_error" "unexpected_lane_state_error" } \
}
adi_add_bus_clock "clk" "rx_cfg:rx_ilas_config:rx_event:rx_status" "reset"
adi_add_bus_clock "device_clk" "rx_data" "device_reset"
adi_set_bus_dependency "rx_ilas_config" "rx_ilas_config" \
"(spirit:decode(id('MODELPARAM_VALUE.LINK_MODE')) = 1)"
adi_set_ports_dependency "sync" \
"(spirit:decode(id('MODELPARAM_VALUE.LINK_MODE')) = 1)"
adi_set_ports_dependency "phy_en_char_align" \
"(spirit:decode(id('MODELPARAM_VALUE.LINK_MODE')) = 1)"
set cc [ipx::current_core]
set_property -dict [list \
driver_value 0 \
] [ipx::get_ports phy_header -of_objects $cc]
# Arrange GUI page layout
set page0 [ipgui::get_pagespec -name "Page 0" -component $cc]
# Link layer mode
set p [ipgui::get_guiparamspec -name "LINK_MODE" -component $cc]
ipgui::move_param -component $cc -order 0 $p -parent $page0
set_property -dict [list \
"display_name" "Link Layer mode" \
"tooltip" "Link Layer mode" \
"widget" "comboBox" \
] $p
set_property -dict [list \
value_validation_type pairs \
value_validation_pairs {64B66B 2 8B10B 1} \
] [ipx::get_user_parameters $p -of_objects $cc]
# Data width selection
set param [ipx::get_user_parameters DATA_PATH_WIDTH -of_objects $cc]
set_property -dict [list \
enablement_tcl_expr {$LINK_MODE==1} \
value_tcl_expr {expr $LINK_MODE*4} \
] $param
set param [ipx::add_user_parameter SYSREF_IOB $cc]
set_property -dict {value_resolve_type user value_format bool value true} $param
set param [ipgui::add_param -name {SYSREF_IOB} -component $cc -parent $page0]
set_property -dict [list \
display_name {Place SYSREF in IOB} \
widget {checkBox} \
show_label true \
] $param
set clk_group [ipgui::add_group -name {Clock Domain Configuration} -component $cc \
-parent $page0 -display_name {Clock Domain Configuration}]
set p [ipgui::get_guiparamspec -name "ASYNC_CLK" -component $cc]
ipgui::move_param -component $cc -order 0 $p -parent $clk_group
set_property -dict [list \
"display_name" "Link and Device Clock Asynchronous" \
"widget" "checkBox" \
] $p
ipx::create_xgui_files [ipx::current_core]
ipx::save_core [ipx::current_core]
+314
View File
@@ -0,0 +1,314 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017, 2018, 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_lane #(
parameter DATA_PATH_WIDTH = 4,
parameter TPL_DATA_PATH_WIDTH = 4,
parameter CHAR_INFO_REGISTERED = 0,
parameter ALIGN_MUX_REGISTERED = 0,
parameter SCRAMBLER_REGISTERED = 0,
parameter ELASTIC_BUFFER_SIZE = 256,
parameter ENABLE_FRAME_ALIGN_CHECK = 0,
parameter ENABLE_CHAR_REPLACE = 0,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input device_clk,
input device_reset,
input [DATA_PATH_WIDTH*8-1:0] phy_data,
input [DATA_PATH_WIDTH-1:0] phy_charisk,
input [DATA_PATH_WIDTH-1:0] phy_notintable,
input [DATA_PATH_WIDTH-1:0] phy_disperr,
input cgs_reset,
output cgs_ready,
input ifs_reset,
output [TPL_DATA_PATH_WIDTH*8-1:0] rx_data,
output buffer_ready_n,
input buffer_release_n,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
output ilas_config_valid,
output [1:0] ilas_config_addr,
output [DATA_PATH_WIDTH*8-1:0] ilas_config_data,
input err_statistics_reset,
input [2:0] ctrl_err_statistics_mask,
output reg [31:0] status_err_statistics_cnt,
output [1:0] status_cgs_state,
output status_ifs_ready,
output [2:0] status_frame_align,
output [7:0] status_frame_align_err_cnt
);
localparam MAX_DATA_PATH_WIDTH = 8;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
wire [7:0] char[0:DATA_PATH_WIDTH-1];
wire [DATA_PATH_WIDTH-1:0] char_is_valid;
reg [DATA_PATH_WIDTH-1:0] char_is_cgs = 1'b0; // K28.5 /K/
reg [DATA_PATH_WIDTH-1:0] char_is_error = 1'b0;
reg [DATA_PATH_WIDTH-1:0] charisk28 = 4'b0000;
wire cgs_beat_is_cgs = &char_is_cgs;
wire cgs_beat_has_error = |char_is_error;
reg ifs_ready = 1'b0;
reg [2:0] frame_align = 'h00;
reg [2:0] frame_align_int;
wire [DATA_PATH_WIDTH*8-1:0] phy_data_s;
wire [DATA_PATH_WIDTH-1:0] charisk28_aligned_s;
wire [DATA_PATH_WIDTH*8-1:0] data_aligned_s;
wire [DATA_PATH_WIDTH-1:0] charisk28_aligned;
wire [DATA_PATH_WIDTH*8-1:0] data_aligned;
wire [DATA_PATH_WIDTH*8-1:0] data_replaced;
wire [DATA_PATH_WIDTH*8-1:0] data_scrambled_s;
wire [DATA_PATH_WIDTH*8-1:0] data_scrambled;
reg [DATA_PATH_WIDTH-1:0] unexpected_char;
reg [DATA_PATH_WIDTH-1:0] phy_char_err;
wire ilas_monitor_reset_s;
wire ilas_monitor_reset;
wire buffer_ready_n_s;
reg [DPW_LOG2:0] jj;
reg align_found;
assign status_ifs_ready = ifs_ready;
assign status_frame_align = frame_align;
genvar i;
generate
for (i = 0; i < DATA_PATH_WIDTH; i = i + 1) begin: gen_char
assign char[i] = phy_data[i*8+7:i*8];
assign char_is_valid[i] = ~(phy_notintable[i] | phy_disperr[i]);
always @(*) begin
char_is_error[i] = ~char_is_valid[i];
char_is_cgs[i] = 1'b0;
charisk28[i] = 1'b0;
unexpected_char[i] = 1'b0;
if (phy_charisk[i] == 1'b1 && char_is_valid[i] == 1'b1) begin
if (char[i][4:0] == 'd28) begin
charisk28[i] = 1'b1;
if (char[i][7:5] == 'd5) begin
char_is_cgs[i] = 1'b1;
end
end else begin
unexpected_char[i] = 1'b1;
end
end
end
end
endgenerate
always @(posedge clk) begin
if (cgs_ready == 1'b1) begin
/*
* Set the bit in phy_char_err if at least one of the monitored error
* conditions has occured.
*/
phy_char_err <= (~{DATA_PATH_WIDTH{ctrl_err_statistics_mask[0]}} & phy_disperr) |
(~{DATA_PATH_WIDTH{ctrl_err_statistics_mask[1]}} & phy_notintable) |
(~{DATA_PATH_WIDTH{ctrl_err_statistics_mask[2]}} & unexpected_char);
end else begin
phy_char_err <= {DATA_PATH_WIDTH{1'b0}};
end
end
function [7:0] num_set_bits;
input [DATA_PATH_WIDTH-1:0] x;
integer j;
begin
num_set_bits = 0;
for (j = 0; j < DATA_PATH_WIDTH; j = j + 1) begin
num_set_bits = num_set_bits + x[j];
end
end
endfunction
always @(posedge clk) begin
if (reset == 1'b1 || err_statistics_reset == 1'b1) begin
status_err_statistics_cnt <= 32'h0;
end else if (status_err_statistics_cnt[31:5] != 27'h7ffffff) begin
status_err_statistics_cnt <= status_err_statistics_cnt + num_set_bits(phy_char_err);
end
end
always @(posedge clk) begin
if (ifs_reset == 1'b1) begin
ifs_ready <= 1'b0;
end else if (cgs_beat_is_cgs == 1'b0 && cgs_beat_has_error == 1'b0) begin
ifs_ready <= 1'b1;
end
end
always @(*) begin
align_found = 1'b0;
frame_align_int = 0;
for(jj = 0; jj < DATA_PATH_WIDTH; jj=jj+1) begin
if (!align_found && (char_is_cgs[jj] == 1'b0)) begin
align_found = 1'b1;
frame_align_int = jj;
end
end
end
always @(posedge clk) begin
if (ifs_ready == 1'b0) begin
frame_align <= frame_align_int;
end
end
pipeline_stage #(
.WIDTH(DATA_PATH_WIDTH*8),
.REGISTERED(CHAR_INFO_REGISTERED)
) i_pipeline_stage0 (
.clk(clk),
.in(phy_data),
.out(phy_data_s));
align_mux #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_align_mux (
.clk(clk),
.align(frame_align),
.in_data(phy_data_s),
.out_data(data_aligned_s),
.in_charisk(charisk28),
.out_charisk(charisk28_aligned_s));
assign ilas_monitor_reset_s = ~ifs_ready;
pipeline_stage #(
.WIDTH(1 + DATA_PATH_WIDTH * (8 + 1)),
.REGISTERED(ALIGN_MUX_REGISTERED)
) i_pipeline_stage1 (
.clk(clk),
.in({
ilas_monitor_reset_s,
data_aligned_s,
charisk28_aligned_s
}),
.out({
ilas_monitor_reset,
data_aligned,
charisk28_aligned
}));
generate
if (ENABLE_FRAME_ALIGN_CHECK) begin : gen_frame_align
jesd204_rx_frame_align #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.ENABLE_CHAR_REPLACE (ENABLE_CHAR_REPLACE)
) i_frame_align (
.clk (clk),
.reset (buffer_ready_n_s),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.charisk28 (charisk28_aligned),
.data (data_aligned),
.data_replaced (data_replaced),
.align_err_cnt (status_frame_align_err_cnt));
end else begin : gen_no_frame_align_monitor
assign status_frame_align_err_cnt = 32'd0;
assign data_replaced = data_aligned;
end
endgenerate
jesd204_scrambler #(
.WIDTH(DATA_PATH_WIDTH*8),
.DESCRAMBLE(1)
) i_descrambler (
.clk(clk),
.reset(buffer_ready_n_s),
.enable(~cfg_disable_scrambler),
.data_in(data_replaced),
.data_out(data_scrambled_s));
pipeline_stage #(
.WIDTH(1 + DATA_PATH_WIDTH * 8),
.REGISTERED(SCRAMBLER_REGISTERED)
) i_pipeline_stage2 (
.clk(clk),
.in({
buffer_ready_n_s,
data_scrambled_s
}),
.out({
buffer_ready_n,
data_scrambled
}));
elastic_buffer #(
.IWIDTH(DATA_PATH_WIDTH*8),
.OWIDTH(TPL_DATA_PATH_WIDTH*8),
.SIZE(ELASTIC_BUFFER_SIZE),
.ASYNC_CLK(ASYNC_CLK)
) i_elastic_buffer (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.wr_data(data_scrambled),
.rd_data(rx_data),
.ready_n(buffer_ready_n),
.do_release_n(buffer_release_n));
jesd204_ilas_monitor #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_ilas_monitor (
.clk(clk),
.reset(ilas_monitor_reset),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.data(data_aligned),
.charisk28(charisk28_aligned),
.data_ready_n(buffer_ready_n_s),
.ilas_config_valid(ilas_config_valid),
.ilas_config_addr(ilas_config_addr),
.ilas_config_data(ilas_config_data));
jesd204_rx_cgs #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_cgs (
.clk(clk),
.reset(cgs_reset),
.char_is_cgs(char_is_cgs),
.char_is_error(char_is_error),
.ready(cgs_ready),
.status_state(status_cgs_state));
endmodule
@@ -0,0 +1,215 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2020-2022 Analog Devices, Inc. All rights reserved.
// SPDX short identifier: ADIJESD204
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module jesd204_rx_lane_64b #(
parameter ELASTIC_BUFFER_SIZE = 256,
parameter TPL_DATA_PATH_WIDTH = 8,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input device_clk,
input device_reset,
input [63:0] phy_data,
input [1:0] phy_header,
input phy_block_sync,
output [TPL_DATA_PATH_WIDTH*8-1:0] rx_data,
output reg buffer_ready_n = 'b1,
input all_buffer_ready_n,
input buffer_release_n,
input lmfc_edge,
output emb_lock,
input cfg_disable_scrambler,
input [1:0] cfg_header_mode, // 0 - CRC12 ; 1 - CRC3; 2 - FEC; 3 - CMD
input [4:0] cfg_rx_thresh_emb_err,
input [7:0] cfg_beats_per_multiframe,
input ctrl_err_statistics_reset,
input [3:0] ctrl_err_statistics_mask,
output [31:0] status_err_statistics_cnt,
output [2:0] status_lane_emb_state,
output reg [7:0] status_lane_skew
);
reg [11:0] crc12_calculated_prev;
wire [63:0] data_descrambled_s;
wire [63:0] data_descrambled;
wire [63:0] data_descrambled_reordered;
wire [11:0] crc12_received;
wire [11:0] crc12_calculated;
wire event_invalid_header;
wire event_unexpected_eomb;
wire event_unexpected_eoemb;
wire event_crc12_mismatch;
wire err_cnt_rst;
wire [63:0] rx_data_msb_s;
wire eomb;
wire eoemb;
wire [7:0] sh_count;
jesd204_rx_header i_rx_header (
.clk(clk),
.reset(reset),
.sh_lock(phy_block_sync),
.header(phy_header),
.cfg_header_mode(cfg_header_mode),
.cfg_rx_thresh_emb_err(cfg_rx_thresh_emb_err),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.emb_lock(emb_lock),
.valid_eomb(eomb),
.valid_eoemb(eoemb),
.crc12(crc12_received),
.crc3(),
.fec(),
.cmd(),
.sh_count(sh_count),
.status_lane_emb_state(status_lane_emb_state),
.event_invalid_header(event_invalid_header),
.event_unexpected_eomb(event_unexpected_eomb),
.event_unexpected_eoemb(event_unexpected_eoemb));
jesd204_crc12 i_crc12 (
.clk(clk),
.reset(1'b0),
.init(eomb),
.data_in(phy_data),
.crc12(crc12_calculated));
reg crc12_on = 'b0;
always @(posedge clk) begin
if (reset == 1'b1) begin
crc12_on <= 1'b0;
end else if (eomb) begin
crc12_on <= 1'b1;
end
end
reg crc12_rdy = 'b0;
always @(posedge clk) begin
if (reset == 1'b1) begin
crc12_rdy <= 1'b0;
end else if (crc12_on && eomb) begin
crc12_rdy <= 1'b1;
end
end
always @(posedge clk) begin
if (eomb) begin
crc12_calculated_prev <= crc12_calculated;
end
end
assign event_crc12_mismatch = crc12_rdy && eomb && (crc12_calculated_prev != crc12_received);
assign err_cnt_rst = reset || ctrl_err_statistics_reset;
error_monitor #(
.EVENT_WIDTH(4),
.CNT_WIDTH(32)
) i_error_monitor (
.clk(clk),
.reset(err_cnt_rst),
.active(1'b1),
.error_event({
event_invalid_header,
event_unexpected_eomb,
event_unexpected_eoemb,
event_crc12_mismatch
}),
.error_event_mask(ctrl_err_statistics_mask),
.status_err_cnt(status_err_statistics_cnt));
jesd204_scrambler_64b #(
.WIDTH(64),
.DESCRAMBLE(1)
) i_descrambler (
.clk(clk),
.reset(1'b0),
.enable(~cfg_disable_scrambler),
.data_in(phy_data),
.data_out(data_descrambled_s));
pipeline_stage #(
.WIDTH(64),
.REGISTERED(1)
) i_pipeline_stage2 (
.clk(clk),
.in({
data_descrambled_s
}),
.out({
data_descrambled
}));
// Control when data is written to the elastic buffer
// Start writing to the buffer when current lane is multiblock locked, but if
// other lanes are not writing in the next half multiblock period stop
// writing.
// This limits the supported lane skew to half of the multiframe
always @(posedge clk) begin
if (reset | ~emb_lock) begin
buffer_ready_n <= 1'b1;
end else if (sh_count == {1'b0,cfg_beats_per_multiframe[7:1]} && all_buffer_ready_n) begin
buffer_ready_n <= 1'b1;
end else if (eoemb) begin
buffer_ready_n <= 1'b0;
end
end
elastic_buffer #(
.IWIDTH(64),
.OWIDTH(TPL_DATA_PATH_WIDTH*8),
.SIZE(ELASTIC_BUFFER_SIZE),
.ASYNC_CLK(ASYNC_CLK)
) i_elastic_buffer (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.wr_data(data_descrambled_reordered),
.rd_data(rx_data),
.ready_n(buffer_ready_n),
.do_release_n(buffer_release_n));
// Measure the delay from the eoemb to the next LMFC edge.
always @(posedge clk) begin
if (lmfc_edge) begin
status_lane_skew <= sh_count;
end
end
/* Reorder octets LSB first */
genvar i;
generate
for (i = 0; i < 64; i = i + 8) begin: g_link_data
assign data_descrambled_reordered[i+:8] = data_descrambled[64-1-i-:8];
end
endgenerate
endmodule
@@ -0,0 +1,22 @@
###############################################################################
## Copyright (C) 2017-2019, 2021 Analog Devices, Inc. All rights reserved.
### SPDX short identifier: ADIJESD204
###############################################################################
<: setFileUsedIn { out_of_context synthesis implementation } :>
<: ;#Component and file information :>
<: set ComponentName [getComponentNameString] :>
<: setOutputDirectory "./" :>
<: setFileName $ComponentName :>
<: setFileExtension "_ooc.xdc" :>
# This XDC is used only for OOC mode of synthesis, implementation.
# These are default values for timing driven synthesis during OOC flow.
# These values will be overwritten during implementation with information
# from top level.
create_clock -name clk -period 2.5 [get_ports clk]
create_clock -name device_clk -period 2.5 [get_ports device_clk]
################################################################################
@@ -0,0 +1,202 @@
# Loading additional proc with user specified bodies to compute parameter values.
source [file join [file dirname [file dirname [info script]]] gui/jesd204_rx_v1_0.gtcl]
# Definitional proc to organize widgets for parameters.
proc init_gui { IPINST } {
ipgui::add_param $IPINST -name "Component_Name"
#Adding Page
set Page_0 [ipgui::add_page $IPINST -name "Page 0"]
ipgui::add_param $IPINST -name "LINK_MODE" -parent ${Page_0} -widget comboBox
ipgui::add_param $IPINST -name "DATA_PATH_WIDTH" -parent ${Page_0}
ipgui::add_param $IPINST -name "ENABLE_CHAR_REPLACE" -parent ${Page_0}
ipgui::add_param $IPINST -name "ENABLE_FRAME_ALIGN_CHECK" -parent ${Page_0}
ipgui::add_param $IPINST -name "ENABLE_FRAME_ALIGN_ERR_RESET" -parent ${Page_0}
ipgui::add_param $IPINST -name "NUM_INPUT_PIPELINE" -parent ${Page_0}
ipgui::add_param $IPINST -name "NUM_LANES" -parent ${Page_0}
ipgui::add_param $IPINST -name "NUM_LINKS" -parent ${Page_0}
ipgui::add_param $IPINST -name "NUM_OUTPUT_PIPELINE" -parent ${Page_0}
ipgui::add_param $IPINST -name "TPL_DATA_PATH_WIDTH" -parent ${Page_0}
ipgui::add_param $IPINST -name "SYSREF_IOB" -parent ${Page_0}
#Adding Group
set Clock_Domain_Configuration [ipgui::add_group $IPINST -name "Clock Domain Configuration" -parent ${Page_0}]
ipgui::add_param $IPINST -name "ASYNC_CLK" -parent ${Clock_Domain_Configuration} -widget checkBox
}
proc update_PARAM_VALUE.DATA_PATH_WIDTH { PARAM_VALUE.DATA_PATH_WIDTH PARAM_VALUE.LINK_MODE } {
# Procedure called to update DATA_PATH_WIDTH when any of the dependent parameters in the arguments change
set DATA_PATH_WIDTH ${PARAM_VALUE.DATA_PATH_WIDTH}
set LINK_MODE ${PARAM_VALUE.LINK_MODE}
set values(LINK_MODE) [get_property value $LINK_MODE]
if { [gen_USERPARAMETER_DATA_PATH_WIDTH_ENABLEMENT $values(LINK_MODE)] } {
set_property enabled true $DATA_PATH_WIDTH
} else {
set_property enabled false $DATA_PATH_WIDTH
set_property value [gen_USERPARAMETER_DATA_PATH_WIDTH_VALUE $values(LINK_MODE)] $DATA_PATH_WIDTH
}
}
proc validate_PARAM_VALUE.DATA_PATH_WIDTH { PARAM_VALUE.DATA_PATH_WIDTH } {
# Procedure called to validate DATA_PATH_WIDTH
return true
}
proc update_PARAM_VALUE.ASYNC_CLK { PARAM_VALUE.ASYNC_CLK } {
# Procedure called to update ASYNC_CLK when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.ASYNC_CLK { PARAM_VALUE.ASYNC_CLK } {
# Procedure called to validate ASYNC_CLK
return true
}
proc update_PARAM_VALUE.ENABLE_CHAR_REPLACE { PARAM_VALUE.ENABLE_CHAR_REPLACE } {
# Procedure called to update ENABLE_CHAR_REPLACE when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.ENABLE_CHAR_REPLACE { PARAM_VALUE.ENABLE_CHAR_REPLACE } {
# Procedure called to validate ENABLE_CHAR_REPLACE
return true
}
proc update_PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK { PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK } {
# Procedure called to update ENABLE_FRAME_ALIGN_CHECK when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK { PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK } {
# Procedure called to validate ENABLE_FRAME_ALIGN_CHECK
return true
}
proc update_PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET { PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET } {
# Procedure called to update ENABLE_FRAME_ALIGN_ERR_RESET when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET { PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET } {
# Procedure called to validate ENABLE_FRAME_ALIGN_ERR_RESET
return true
}
proc update_PARAM_VALUE.LINK_MODE { PARAM_VALUE.LINK_MODE } {
# Procedure called to update LINK_MODE when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.LINK_MODE { PARAM_VALUE.LINK_MODE } {
# Procedure called to validate LINK_MODE
return true
}
proc update_PARAM_VALUE.NUM_INPUT_PIPELINE { PARAM_VALUE.NUM_INPUT_PIPELINE } {
# Procedure called to update NUM_INPUT_PIPELINE when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.NUM_INPUT_PIPELINE { PARAM_VALUE.NUM_INPUT_PIPELINE } {
# Procedure called to validate NUM_INPUT_PIPELINE
return true
}
proc update_PARAM_VALUE.NUM_LANES { PARAM_VALUE.NUM_LANES } {
# Procedure called to update NUM_LANES when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.NUM_LANES { PARAM_VALUE.NUM_LANES } {
# Procedure called to validate NUM_LANES
return true
}
proc update_PARAM_VALUE.NUM_LINKS { PARAM_VALUE.NUM_LINKS } {
# Procedure called to update NUM_LINKS when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.NUM_LINKS { PARAM_VALUE.NUM_LINKS } {
# Procedure called to validate NUM_LINKS
return true
}
proc update_PARAM_VALUE.NUM_OUTPUT_PIPELINE { PARAM_VALUE.NUM_OUTPUT_PIPELINE } {
# Procedure called to update NUM_OUTPUT_PIPELINE when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.NUM_OUTPUT_PIPELINE { PARAM_VALUE.NUM_OUTPUT_PIPELINE } {
# Procedure called to validate NUM_OUTPUT_PIPELINE
return true
}
proc update_PARAM_VALUE.SYSREF_IOB { PARAM_VALUE.SYSREF_IOB } {
# Procedure called to update SYSREF_IOB when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.SYSREF_IOB { PARAM_VALUE.SYSREF_IOB } {
# Procedure called to validate SYSREF_IOB
return true
}
proc update_PARAM_VALUE.TPL_DATA_PATH_WIDTH { PARAM_VALUE.TPL_DATA_PATH_WIDTH } {
# Procedure called to update TPL_DATA_PATH_WIDTH when any of the dependent parameters in the arguments change
}
proc validate_PARAM_VALUE.TPL_DATA_PATH_WIDTH { PARAM_VALUE.TPL_DATA_PATH_WIDTH } {
# Procedure called to validate TPL_DATA_PATH_WIDTH
return true
}
proc update_MODELPARAM_VALUE.NUM_LANES { MODELPARAM_VALUE.NUM_LANES PARAM_VALUE.NUM_LANES } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.NUM_LANES}] ${MODELPARAM_VALUE.NUM_LANES}
}
proc update_MODELPARAM_VALUE.NUM_LINKS { MODELPARAM_VALUE.NUM_LINKS PARAM_VALUE.NUM_LINKS } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.NUM_LINKS}] ${MODELPARAM_VALUE.NUM_LINKS}
}
proc update_MODELPARAM_VALUE.NUM_INPUT_PIPELINE { MODELPARAM_VALUE.NUM_INPUT_PIPELINE PARAM_VALUE.NUM_INPUT_PIPELINE } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.NUM_INPUT_PIPELINE}] ${MODELPARAM_VALUE.NUM_INPUT_PIPELINE}
}
proc update_MODELPARAM_VALUE.NUM_OUTPUT_PIPELINE { MODELPARAM_VALUE.NUM_OUTPUT_PIPELINE PARAM_VALUE.NUM_OUTPUT_PIPELINE } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.NUM_OUTPUT_PIPELINE}] ${MODELPARAM_VALUE.NUM_OUTPUT_PIPELINE}
}
proc update_MODELPARAM_VALUE.LINK_MODE { MODELPARAM_VALUE.LINK_MODE PARAM_VALUE.LINK_MODE } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.LINK_MODE}] ${MODELPARAM_VALUE.LINK_MODE}
}
proc update_MODELPARAM_VALUE.DATA_PATH_WIDTH { MODELPARAM_VALUE.DATA_PATH_WIDTH PARAM_VALUE.DATA_PATH_WIDTH } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.DATA_PATH_WIDTH}] ${MODELPARAM_VALUE.DATA_PATH_WIDTH}
}
proc update_MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK { MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK}] ${MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_CHECK}
}
proc update_MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET { MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET}] ${MODELPARAM_VALUE.ENABLE_FRAME_ALIGN_ERR_RESET}
}
proc update_MODELPARAM_VALUE.ENABLE_CHAR_REPLACE { MODELPARAM_VALUE.ENABLE_CHAR_REPLACE PARAM_VALUE.ENABLE_CHAR_REPLACE } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.ENABLE_CHAR_REPLACE}] ${MODELPARAM_VALUE.ENABLE_CHAR_REPLACE}
}
proc update_MODELPARAM_VALUE.ASYNC_CLK { MODELPARAM_VALUE.ASYNC_CLK PARAM_VALUE.ASYNC_CLK } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.ASYNC_CLK}] ${MODELPARAM_VALUE.ASYNC_CLK}
}
proc update_MODELPARAM_VALUE.TPL_DATA_PATH_WIDTH { MODELPARAM_VALUE.TPL_DATA_PATH_WIDTH PARAM_VALUE.TPL_DATA_PATH_WIDTH } {
# Procedure called to set VHDL generic/Verilog parameter value(s) based on TCL parameter value
set_property value [get_property value ${PARAM_VALUE.TPL_DATA_PATH_WIDTH}] ${MODELPARAM_VALUE.TPL_DATA_PATH_WIDTH}
}