From 1e04b2e2f234ab6fe8fa561ef3845cb9c1b34345 Mon Sep 17 00:00:00 2001 From: Matt Blanton Date: Wed, 29 Jan 2020 09:41:43 -0500 Subject: [PATCH] jesd204_rx: Add RX frame alignment character check Add support for RX frame alignment character checking when scrambling is enabled and for link reset on misalignment. Add support for xcelium simulator to jesd204/tb --- .../jesd204/axi_jesd204_rx/axi_jesd204_rx.v | 12 +- .../axi_jesd204_rx/axi_jesd204_rx_hw.tcl | 2 + .../axi_jesd204_rx/axi_jesd204_rx_ip.tcl | 2 + .../jesd204/axi_jesd204_rx/jesd204_up_rx.v | 26 +- .../axi_jesd204_rx/jesd204_up_rx_lane.v | 7 +- library/jesd204/interfaces/interfaces_ip.tcl | 1 + library/jesd204/jesd204_rx/jesd204_rx.v | 74 +++- .../jesd204_rx_frame_align_monitor.v | 181 +++++++++ .../jesd204_rx/jesd204_rx_frame_mark.v | 193 +++++++++ library/jesd204/jesd204_rx/jesd204_rx_hw.tcl | 4 + library/jesd204/jesd204_rx/jesd204_rx_ip.tcl | 5 + library/jesd204/jesd204_rx/jesd204_rx_lane.v | 28 +- .../jesd204_rx_static_config.v | 4 +- .../jesd204_rx_static_config_ip.tcl | 1 + library/jesd204/tb/frame_align_tb | 17 + library/jesd204/tb/frame_align_tb.v | 384 ++++++++++++++++++ library/jesd204/tb/loopback_tb | 1 + library/jesd204/tb/loopback_tb.v | 6 +- library/jesd204/tb/run_tb.sh | 34 +- library/jesd204/tb/tb_base.v | 2 +- 20 files changed, 945 insertions(+), 39 deletions(-) mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/jesd204_up_rx.v mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v mode change 100644 => 100755 library/jesd204/interfaces/interfaces_ip.tcl mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_rx.v create mode 100755 library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v create mode 100755 library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_rx_hw.tcl mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_rx_ip.tcl mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_rx_lane.v mode change 100644 => 100755 library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v mode change 100644 => 100755 library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl create mode 100755 library/jesd204/tb/frame_align_tb create mode 100755 library/jesd204/tb/frame_align_tb.v mode change 100644 => 100755 library/jesd204/tb/loopback_tb.v mode change 100644 => 100755 library/jesd204/tb/run_tb.sh mode change 100644 => 100755 library/jesd204/tb/tb_base.v diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v old mode 100644 new mode 100755 index 2e0ef36f8..313f559ef --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v @@ -90,6 +90,7 @@ module axi_jesd204_rx #( output core_cfg_sysref_disable, output core_cfg_buffer_early_release, output [7:0] core_cfg_buffer_delay, + output [7:0] core_cfg_frame_align_err_threshold, input [NUM_LANES-1:0] core_ilas_config_valid, input [2*NUM_LANES-1:0] core_ilas_config_addr, @@ -107,7 +108,8 @@ module axi_jesd204_rx #( input [2*NUM_LANES-1:0] core_status_lane_cgs_state, input [3*NUM_LANES-1:0] core_status_lane_emb_state, input [NUM_LANES-1:0] core_status_lane_ifs_ready, - input [14*NUM_LANES-1:0] core_status_lane_latency + input [14*NUM_LANES-1:0] core_status_lane_latency, + input [8*NUM_LANES-1:0] core_status_lane_frame_align_err_cnt ); localparam PCORE_VERSION = 32'h00010361; // 1.03.a @@ -137,6 +139,7 @@ wire up_cfg_sysref_disable; wire up_cfg_buffer_early_release; wire [7:0] up_cfg_buffer_delay; wire [7:0] up_cfg_lmfc_offset; +wire [7:0] up_cfg_frame_align_err_threshold; wire up_reset; wire up_reset_synchronizer; @@ -181,7 +184,7 @@ jesd204_up_common #( .NUM_LINKS(NUM_LINKS), .DATA_PATH_WIDTH(DATA_PATH_WIDTH), .NUM_IRQS(5), - .EXTRA_CFG_WIDTH(19), + .EXTRA_CFG_WIDTH(27), .LINK_MODE(LINK_MODE) ) i_up_common ( .up_clk(s_axi_aclk), @@ -213,6 +216,7 @@ jesd204_up_common #( .core_cfg_disable_char_replacement(core_cfg_disable_char_replacement), .up_extra_cfg({ + /* 19-26 */ up_cfg_frame_align_err_threshold, /* 18 */ up_cfg_sysref_disable, /* 17 */ up_cfg_sysref_oneshot, /* 16 */ up_cfg_buffer_early_release, @@ -220,6 +224,7 @@ jesd204_up_common #( /* 00-07 */ up_cfg_lmfc_offset }), .core_extra_cfg({ + /* 19-26 */ core_cfg_frame_align_err_threshold, /* 18 */ core_cfg_sysref_disable, /* 17 */ core_cfg_sysref_oneshot, /* 16 */ core_cfg_buffer_early_release, @@ -274,6 +279,8 @@ jesd204_up_rx #( .up_cfg_buffer_early_release(up_cfg_buffer_early_release), .up_cfg_buffer_delay(up_cfg_buffer_delay), + .up_cfg_frame_align_err_threshold(up_cfg_frame_align_err_threshold), + .core_ctrl_err_statistics_reset(core_ctrl_err_statistics_reset), .core_ctrl_err_statistics_mask(core_ctrl_err_statistics_mask), @@ -282,6 +289,7 @@ jesd204_up_rx #( .core_status_lane_emb_state(core_status_lane_emb_state), .core_status_lane_ifs_ready(core_status_lane_ifs_ready), .core_status_lane_latency(core_status_lane_latency), + .core_status_lane_frame_align_err_cnt(core_status_lane_frame_align_err_cnt), .core_status_err_statistics_cnt(core_status_err_statistics_cnt), diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl old mode 100644 new mode 100755 index 112010125..81a12ec7d --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl @@ -133,6 +133,7 @@ add_interface_port config core_cfg_lmfc_offset lmfc_offset Output 8 add_interface_port config core_cfg_octets_per_frame octets_per_frame Output 8 add_interface_port config core_cfg_sysref_disable sysref_disable Output 1 add_interface_port config core_cfg_sysref_oneshot sysref_oneshot Output 1 +add_interface_port config core_cfg_frame_align_err_threshold frame_align_err_threshold Output 8 add_interface_port config core_ctrl_err_statistics_reset err_statistics_reset Output 1 add_interface_port config core_ctrl_err_statistics_mask err_statistics_mask Output 3 @@ -146,6 +147,7 @@ add_interface_port status core_status_ctrl_state ctrl_state Input 2 add_interface_port status core_status_lane_cgs_state lane_cgs_state Input 2*NUM_LANES add_interface_port status core_status_lane_ifs_ready lane_ifs_ready Input NUM_LANES add_interface_port status core_status_lane_latency lane_latency Input 14*NUM_LANES +add_interface_port status core_status_lane_frame_align_err_cnt lane_frame_align_err_cnt Input 8*NUM_LANES add_interface_port status core_status_err_statistics_cnt err_statistics_cnt Input 32*NUM_LANES # event interface diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl old mode 100644 new mode 100755 index ca3c5cfdb..c7ead8b24 --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl @@ -88,6 +88,7 @@ adi_add_bus "rx_cfg" "master" \ { "core_cfg_buffer_delay" "buffer_delay" } \ { "core_cfg_disable_char_replacement" "disable_char_replacement" } \ { "core_cfg_disable_scrambler" "disable_scrambler" } \ + { "core_cfg_frame_align_err_threshold" "frame_align_err_threshold" } \ } adi_add_bus "rx_ilas_config" "slave" \ @@ -116,6 +117,7 @@ adi_add_bus "rx_status" "slave" \ { "core_status_lane_emb_state" "lane_emb_state" } \ { "core_status_lane_ifs_ready" "lane_ifs_ready" } \ { "core_status_lane_latency" "lane_latency" } \ + { "core_status_lane_frame_align_err_cnt" "lane_frame_align_err_cnt" } \ { "core_status_err_statistics_cnt" "err_statistics_cnt" } \ } diff --git a/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v b/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v old mode 100644 new mode 100755 index 49a08d1e8..c9f717db5 --- a/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v +++ b/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v @@ -71,6 +71,7 @@ module jesd204_up_rx # ( input [3*NUM_LANES-1:0] core_status_lane_emb_state, input [NUM_LANES-1:0] core_status_lane_ifs_ready, input [14*NUM_LANES-1:0] core_status_lane_latency, + input [8*NUM_LANES-1:0] core_status_lane_frame_align_err_cnt, input [32*NUM_LANES-1:0] core_status_err_statistics_cnt, output [6:0] core_ctrl_err_statistics_mask, @@ -78,13 +79,16 @@ module jesd204_up_rx # ( input up_cfg_is_writeable, output reg up_cfg_buffer_early_release, - output reg [7:0] up_cfg_buffer_delay + output reg [7:0] up_cfg_buffer_delay, + + output reg [7:0] up_cfg_frame_align_err_threshold ); localparam ELASTIC_BUFFER_SIZE = 256; wire [1:0] up_status_ctrl_state; wire [2*NUM_LANES-1:0] up_status_lane_cgs_state; +wire [8*NUM_LANES-1:0] up_status_lane_frame_align_err_cnt; wire [3*NUM_LANES-1:0] up_status_lane_emb_state; wire [31:0] up_lane_rdata[0:NUM_LANES-1]; wire [32*NUM_LANES-1:0] up_status_err_statistics_cnt; @@ -93,21 +97,23 @@ reg up_ctrl_err_statistics_reset = 0; reg [6:0] up_ctrl_err_statistics_mask = 7'h0; sync_data #( - .NUM_OF_BITS(2+NUM_LANES*(3+2+32)) + .NUM_OF_BITS(2+NUM_LANES*(3+2+32+8)) ) i_cdc_status ( .in_clk(core_clk), .in_data({ core_status_err_statistics_cnt, core_status_ctrl_state, core_status_lane_cgs_state, - core_status_lane_emb_state + core_status_lane_emb_state, + core_status_lane_frame_align_err_cnt }), .out_clk(up_clk), .out_data({ up_status_err_statistics_cnt, up_status_ctrl_state, up_status_lane_cgs_state, - up_status_lane_emb_state + up_status_lane_emb_state, + up_status_lane_frame_align_err_cnt }) ); @@ -147,7 +153,12 @@ always @(*) begin /* 01-07 */ 7'h0, /* 00 */ up_ctrl_err_statistics_reset }; - /* 0x92-0x9f reserved for future use */ + 12'h92: up_rdata <= { + /* 08-31 */ 24'h0, + /* 00-07 */ up_cfg_frame_align_err_threshold + }; + + /* 0x93-0x9f reserved for future use */ /* JESD RX status */ 12'ha0: up_rdata <= { @@ -172,6 +183,7 @@ always @(posedge up_clk) begin up_cfg_buffer_delay <= 'h00; up_ctrl_err_statistics_mask <= 7'h0; up_ctrl_err_statistics_reset <= 1'b0; + up_cfg_frame_align_err_threshold <= 8'd4; end else if (up_wreq == 1'b1 && up_cfg_is_writeable == 1'b1) begin case (up_waddr) /* JESD RX configuraton */ @@ -186,6 +198,9 @@ always @(posedge up_clk) begin up_ctrl_err_statistics_mask <= up_wdata[14:8]; up_ctrl_err_statistics_reset <= up_wdata[0]; end + 12'h92: begin + up_cfg_frame_align_err_threshold <= up_wdata[7:0]; + end endcase end end @@ -203,6 +218,7 @@ generate for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane .up_status_cgs_state(up_status_lane_cgs_state[2*i+1:2*i]), .up_status_err_statistics_cnt(up_status_err_statistics_cnt[32*i+31:32*i]), .up_status_emb_state(up_status_lane_emb_state[3*i+2:3*i]), + .up_status_lane_frame_align_err_cnt(up_status_lane_frame_align_err_cnt[8*i+7:8*i]), .core_clk(core_clk), .core_reset(core_reset), diff --git a/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v b/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v old mode 100644 new mode 100755 index fa1443d8f..4274e4fc4 --- a/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v +++ b/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v @@ -55,6 +55,7 @@ module jesd204_up_rx_lane ( input [1:0] up_status_cgs_state, input [31:0] up_status_err_statistics_cnt, input [2:0] up_status_emb_state, + input [7:0] up_status_lane_frame_align_err_cnt, input core_clk, input core_reset, @@ -108,7 +109,7 @@ always @(*) begin end else begin case (up_raddr[1:0]) 2'b00: up_rdata <= { - /* 06-31 */ 26'h00, /* Reserved for future use */ + /* 11-31 */ 21'h0, /* Reserved for future use */ /* 08-10 */ up_status_emb_state, /* 06-07 */ 2'h00, /* 05 */ up_ilas_ready, @@ -123,6 +124,10 @@ always @(*) begin 2'b10: up_rdata <= { /* 00-31 */ up_status_err_statistics_cnt }; + 2'b11: up_rdata <= { + /* 08-31 */ 24'h0, /* Reserved for future use */ + /* 00-07 */ up_status_lane_frame_align_err_cnt + }; default: up_rdata <= 'h00; endcase end diff --git a/library/jesd204/interfaces/interfaces_ip.tcl b/library/jesd204/interfaces/interfaces_ip.tcl old mode 100644 new mode 100755 index c5cef3f4c..377de054b --- a/library/jesd204/interfaces/interfaces_ip.tcl +++ b/library/jesd204/interfaces/interfaces_ip.tcl @@ -88,6 +88,7 @@ adi_if_ports output 1 buffer_early_release adi_if_ports output 1 buffer_delay adi_if_ports output 1 disable_char_replacement adi_if_ports output 1 disable_scrambler +adi_if_ports output 8 frame_align_err_threshold adi_if_ports output 1 err_statistics_reset adi_if_ports output 7 err_statistics_mask diff --git a/library/jesd204/jesd204_rx/jesd204_rx.v b/library/jesd204/jesd204_rx/jesd204_rx.v old mode 100644 new mode 100755 index f0707a52f..9a11d846c --- a/library/jesd204/jesd204_rx/jesd204_rx.v +++ b/library/jesd204/jesd204_rx/jesd204_rx.v @@ -50,7 +50,9 @@ module jesd204_rx #( parameter NUM_INPUT_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 DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4, + parameter ENABLE_FRAME_ALIGN_CHECK = 1, + parameter ENABLE_FRAME_ALIGN_ERR_RESET = 1 ) ( input clk, input reset, @@ -93,6 +95,8 @@ module jesd204_rx #( input ctrl_err_statistics_reset, input [6:0] ctrl_err_statistics_mask, + input [7:0] cfg_frame_align_err_threshold, + output [32*NUM_LANES-1:0] status_err_statistics_cnt, output [NUM_LANES-1:0] ilas_config_valid, @@ -103,7 +107,8 @@ module jesd204_rx #( 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 [3*NUM_LANES-1:0] status_lane_emb_state, + output [8*NUM_LANES-1:0] status_lane_frame_align_err_cnt ); /* @@ -147,6 +152,7 @@ reg buffer_release_d1 = 1'b0; wire [NUM_LANES-1:0] buffer_ready_n; wire all_buffer_ready_n; +reg core_reset; reg eof_reset = 1'b1; wire [DW-1:0] phy_data_r; @@ -166,6 +172,8 @@ wire latency_monitor_reset; wire [2*NUM_LANES-1:0] frame_align; wire [NUM_LANES-1:0] ifs_ready; +reg [NUM_LANES-1:0] frame_align_err_thresh_met = {NUM_LANES{1'b0}}; + reg buffer_release_opportunity = 1'b0; always @(posedge clk) begin @@ -231,7 +239,7 @@ pipeline_stage #( jesd204_lmfc i_lmfc ( .clk(clk), - .reset(reset), + .reset(core_reset), .cfg_beats_per_multiframe(cfg_beats_per_multiframe), .cfg_lmfc_offset(cfg_lmfc_offset), @@ -277,7 +285,7 @@ jesd204_rx_ctrl #( .NUM_LINKS(NUM_LINKS) ) i_rx_ctrl ( .clk(clk), - .reset(reset), + .reset(core_reset), .cfg_lanes_disable(cfg_lanes_disable), .cfg_links_disable(cfg_links_disable), @@ -298,6 +306,31 @@ jesd204_rx_ctrl #( .status_state(status_ctrl_state) ); +// Reset core when frame alignment errors occur +if(ENABLE_FRAME_ALIGN_CHECK && ENABLE_FRAME_ALIGN_ERR_RESET) begin : gen_frame_align_err_reset + + reg [7:0] reset_cnt; + + always @(posedge clk) begin + if(reset) begin + reset_cnt <= 8'h00; + end else begin + if(|frame_align_err_thresh_met) begin + reset_cnt <= 8'hFF; + end else if(reset_cnt != 0) begin + reset_cnt <= reset_cnt - 1'b1; + end + end + + core_reset <= reset | (reset_cnt != 0); + end + +end else begin : gen_no_frame_align_err_reset + always @(*) begin + core_reset = reset; + end +end + for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane localparam D_START = i * DATA_PATH_WIDTH*8; @@ -310,10 +343,11 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane .CHAR_INFO_REGISTERED(CHAR_INFO_REGISTERED), .ALIGN_MUX_REGISTERED(ALIGN_MUX_REGISTERED), .SCRAMBLER_REGISTERED(SCRAMBLER_REGISTERED), - .ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE) + .ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE), + .ENABLE_FRAME_ALIGN_CHECK(ENABLE_FRAME_ALIGN_CHECK) ) i_lane ( .clk(clk), - .reset(reset), + .reset(core_reset), .phy_data(phy_data_r[D_STOP:D_START]), .phy_charisk(phy_charisk_r[C_STOP:C_START]), @@ -325,13 +359,15 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane .ifs_reset(ifs_reset[i]), - .cfg_disable_scrambler(cfg_disable_scrambler), - .rx_data(rx_data_s[D_STOP:D_START]), .buffer_release_n(buffer_release_n), .buffer_ready_n(buffer_ready_n[i]), + .cfg_beats_per_multiframe(cfg_beats_per_multiframe), + .cfg_octets_per_frame(cfg_octets_per_frame), + .cfg_disable_scrambler(cfg_disable_scrambler), + .ctrl_err_statistics_reset(ctrl_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]), @@ -342,10 +378,20 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane .status_cgs_state(status_lane_cgs_state[2*i+1:2*i]), .status_ifs_ready(ifs_ready[i]), - .status_frame_align(frame_align[2*i+1:2*i]) + .status_frame_align(frame_align[2*i+1:2*i]), + + .status_frame_align_err_cnt(status_lane_frame_align_err_cnt[8*i+7:8*i]) ); + + if(ENABLE_FRAME_ALIGN_CHECK && ENABLE_FRAME_ALIGN_ERR_RESET) begin : gen_frame_align_err_thresh + always @(posedge clk) begin + frame_align_err_thresh_met[i] <= status_lane_frame_align_err_cnt[8*i+7:8*i] >= cfg_frame_align_err_threshold; + end + end end + + /* 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; @@ -382,11 +428,15 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b wire [NUM_LANES-1:0] emb_lock; +always @(*) begin + core_reset = reset; +end + jesd204_rx_ctrl_64b #( .NUM_LANES(NUM_LANES) ) i_jesd204_rx_ctrl_64b ( .clk(clk), - .reset(reset), + .reset(core_reset), .cfg_lanes_disable(cfg_lanes_disable), @@ -412,7 +462,7 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane .ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE) ) i_lane ( .clk(clk), - .reset(reset), + .reset(core_reset), .phy_data(phy_data_r[D_STOP:D_START]), .phy_header(phy_header_r[H_STOP:H_START]), @@ -444,7 +494,7 @@ assign status_lane_latency[14*(i+1)-1:14*i] = {3'b0,status_lane_skew,3'b0}; end -// Assign unused outputs +// Assign unused outputs assign sync = 'b0; assign phy_en_char_align = 1'b0; diff --git a/library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v b/library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v new file mode 100755 index 000000000..f216fb12f --- /dev/null +++ b/library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v @@ -0,0 +1,181 @@ +// +// The ADI JESD204 Core is released under the following license, which is +// different than all other HDL cores in this repository. +// +// Please read this, and understand the freedoms and responsibilities you have +// by using this source code/core. +// +// The JESD204 HDL, is copyright © 2016-2017 Analog Devices Inc. +// +// This core is free software, you can use run, copy, study, change, ask +// questions about and improve this core. Distribution of source, or resulting +// binaries (including those inside an FPGA or ASIC) require you to release the +// source of the entire project (excluding the system libraries provide by the +// tools/compiler/FPGA vendor). These are the terms of the GNU General Public +// License version 2 as published by the Free Software Foundation. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License version 2 +// along with this source code, and binary. If not, see +// . +// +// Commercial licenses (with commercial support) of this JESD204 core are also +// available under terms different than the General Public License. (e.g. they +// do not require you to accompany any image (FPGA or ASIC) using the JESD204 +// core with any corresponding source code.) For these alternate terms you must +// purchase a license from Analog Devices Technology Licensing Office. Users +// interested in such a license should contact jesd204-licensing@analog.com for +// more information. This commercial license is sub-licensable (if you purchase +// chips from Analog Devices, incorporate them into your PCB level product, and +// purchase a JESD204 license, end users of your product will also have a +// license to use this core in a commercial setting without releasing their +// source code). +// +// In addition, we kindly ask you to acknowledge ADI in any program, application +// or publication in which you use this JESD204 HDL core. (You are not required +// to do so; it is up to your common sense to decide whether you want to comply +// with this request or not.) For general publications, we suggest referencing : +// “The design and implementation of the JESD204 HDL Core used in this project +// is copyright © 2016-2017, Analog Devices, Inc.” +// + +`timescale 1ns/100ps + +module jesd204_rx_frame_align_monitor #( + parameter DATA_PATH_WIDTH = 4 +) ( + input clk, + input reset, + input [7:0] cfg_beats_per_multiframe, + input [7:0] cfg_octets_per_frame, + input cfg_disable_scrambler, + input [DATA_PATH_WIDTH-1:0] charisk28, + input [DATA_PATH_WIDTH*8-1:0] data, + + 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_beats_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-1: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-1:0] cur_align_err_cnt; +wire [8:0] align_err_cnt_next; + + +jesd204_rx_frame_mark #( + .DATA_PATH_WIDTH (DATA_PATH_WIDTH) +) frame_mark ( + .clk (clk), + .reset (reset), + .cfg_beats_per_multiframe (cfg_beats_per_multiframe), + .cfg_octets_per_frame (cfg_octets_per_frame), + .charisk28 (charisk28), + .data (data), + .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 + + // TODO: support cfg_disable_scrambler + + 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] <= !cfg_disable_scrambler && (char_is_a[ii] && !eomf[ii]); + eomf_good[ii] <= !cfg_disable_scrambler && (char_is_a[ii] && eomf[ii]); + eof_err[ii] <= !cfg_disable_scrambler && (char_is_f[ii] && !eof[ii]); + eof_good[ii] <= !cfg_disable_scrambler && (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 + +endmodule diff --git a/library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v b/library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v new file mode 100755 index 000000000..a8d946ea3 --- /dev/null +++ b/library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v @@ -0,0 +1,193 @@ +// +// The ADI JESD204 Core is released under the following license, which is +// different than all other HDL cores in this repository. +// +// Please read this, and understand the freedoms and responsibilities you have +// by using this source code/core. +// +// The JESD204 HDL, is copyright © 2016-2017 Analog Devices Inc. +// +// This core is free software, you can use run, copy, study, change, ask +// questions about and improve this core. Distribution of source, or resulting +// binaries (including those inside an FPGA or ASIC) require you to release the +// source of the entire project (excluding the system libraries provide by the +// tools/compiler/FPGA vendor). These are the terms of the GNU General Public +// License version 2 as published by the Free Software Foundation. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License version 2 +// along with this source code, and binary. If not, see +// . +// +// Commercial licenses (with commercial support) of this JESD204 core are also +// available under terms different than the General Public License. (e.g. they +// do not require you to accompany any image (FPGA or ASIC) using the JESD204 +// core with any corresponding source code.) For these alternate terms you must +// purchase a license from Analog Devices Technology Licensing Office. Users +// interested in such a license should contact jesd204-licensing@analog.com for +// more information. This commercial license is sub-licensable (if you purchase +// chips from Analog Devices, incorporate them into your PCB level product, and +// purchase a JESD204 license, end users of your product will also have a +// license to use this core in a commercial setting without releasing their +// source code). +// +// In addition, we kindly ask you to acknowledge ADI in any program, application +// or publication in which you use this JESD204 HDL core. (You are not required +// to do so; it is up to your common sense to decide whether you want to comply +// with this request or not.) For general publications, we suggest referencing : +// “The design and implementation of the JESD204 HDL Core used in this project +// is copyright © 2016-2017, Analog Devices, Inc.” +// + +// Limitations: +// DATA_PATH_WIDTH = 4 +// F*K=4, multiples of DATA_PATH_WIDTH +// F=1,2,3,4,6, and multiples of DATA_PATH_WIDTH + +`timescale 1ns/100ps + +module jesd204_rx_frame_mark #( + parameter DATA_PATH_WIDTH = 4 +) ( + input clk, + input reset, + input [7:0] cfg_beats_per_multiframe, + input [7:0] cfg_octets_per_frame, + input [DATA_PATH_WIDTH-1:0] charisk28, + input [DATA_PATH_WIDTH*8-1:0] data, + + output reg [DATA_PATH_WIDTH-1:0] sof, + output reg [DATA_PATH_WIDTH-1:0] eof, + output reg [DATA_PATH_WIDTH-1:0] somf, + output reg [DATA_PATH_WIDTH-1:0] eomf +); + +localparam MAX_OCTETS_PER_FRAME = 16; +localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1; +localparam CW = MAX_OCTETS_PER_FRAME > 128 ? 8 : + MAX_OCTETS_PER_FRAME > 64 ? 7 : + MAX_OCTETS_PER_FRAME > 32 ? 6 : + MAX_OCTETS_PER_FRAME > 16 ? 5 : + MAX_OCTETS_PER_FRAME > 8 ? 4 : + MAX_OCTETS_PER_FRAME > 4 ? 3 : + MAX_OCTETS_PER_FRAME > 2 ? 2 : 1; +localparam BEATS_PER_FRAME_WIDTH = CW-DPW_LOG2; + +reg [1:0] beat_cnt_mod_3; +reg [BEATS_PER_FRAME_WIDTH-1:0] beat_cnt_frame; +wire cur_sof; +wire cur_eof; +reg [7:0] beat_cnt_mf; +wire cur_somf; +wire cur_eomf; + +wire [BEATS_PER_FRAME_WIDTH-1:0] cfg_beats_per_frame = cfg_octets_per_frame[CW-1:DPW_LOG2]; +reg [DATA_PATH_WIDTH-1:0] sof_f_3[2:0]; +reg [DATA_PATH_WIDTH-1:0] eof_f_3[2:0]; +reg [DATA_PATH_WIDTH-1:0] sof_f_6[2:0]; +reg [DATA_PATH_WIDTH-1:0] eof_f_6[2:0]; + +initial begin + sof_f_3[0] = {4'b1001}; + sof_f_3[1] = {4'b0100}; + sof_f_3[2] = {4'b0010}; + eof_f_3[0] = {4'b0100}; + eof_f_3[1] = {4'b0010}; + eof_f_3[2] = {4'b1001}; + sof_f_6[0] = {4'b0001}; + sof_f_6[1] = {4'b0100}; + sof_f_6[2] = {4'b0000}; + eof_f_6[0] = {4'b0000}; + eof_f_6[1] = {4'b0010}; + eof_f_6[2] = {4'b1000}; +end + +// Beat count % 3, to support F=3,6 +always @(posedge clk) begin + if(reset) begin + beat_cnt_mod_3 <= 2'd0; + end else begin + if(beat_cnt_mod_3 == 2'd2) begin + beat_cnt_mod_3 <= 2'd0; + end else begin + beat_cnt_mod_3 <= beat_cnt_mod_3 + 1'b1; + end + end +end + +// Beat count per frame +always @(posedge clk) begin + if(reset) begin + beat_cnt_frame <= {BEATS_PER_FRAME_WIDTH{1'b0}}; + end else begin + if(beat_cnt_frame == cfg_beats_per_frame) begin + beat_cnt_frame <= {BEATS_PER_FRAME_WIDTH{1'b0}}; + end else begin + beat_cnt_frame <= beat_cnt_frame + 1'b1; + end + end +end + +assign cur_sof = beat_cnt_frame == 0; +assign cur_eof = beat_cnt_frame == cfg_beats_per_frame; + +// cfg_octets_per_frame must be a multiple of DATA_PATH_WIDTH' +// except for the following supported special cases +always @(*) begin + case(cfg_octets_per_frame) + 8'd0: + begin + sof = {DATA_PATH_WIDTH{1'b1}}; + eof = {DATA_PATH_WIDTH{1'b1}}; + end + 8'd1: + begin + sof = {DATA_PATH_WIDTH/2{2'b01}}; + eof = {DATA_PATH_WIDTH/2{2'b10}}; + end + 8'd2: + begin + sof = sof_f_3[beat_cnt_mod_3]; + eof = eof_f_3[beat_cnt_mod_3]; + end + 8'd5: + begin + sof = sof_f_6[beat_cnt_mod_3]; + eof = eof_f_6[beat_cnt_mod_3]; + end + default: + begin + sof = {{DATA_PATH_WIDTH-1{1'b0}}, cur_sof}; + eof = {cur_eof, {DATA_PATH_WIDTH-1{1'b0}}}; + end + endcase +end + + +// Beat count per multiframe +always @(posedge clk) begin + if(reset) begin + beat_cnt_mf <= 8'b0; + end else begin + if(beat_cnt_mf == cfg_beats_per_multiframe) begin + beat_cnt_mf <= 8'b0; + end else begin + beat_cnt_mf <= beat_cnt_mf + 1'b1; + end + end +end + +assign cur_somf = beat_cnt_mf == 0; +assign cur_eomf = beat_cnt_mf == cfg_beats_per_multiframe; + +// Only support F*K equals a multipe of DATA_PATH_WIDTH, +always @(*) begin + somf = {{DATA_PATH_WIDTH-1{1'b0}}, cur_somf}; + eomf = {cur_eomf, {DATA_PATH_WIDTH-1{1'b0}}}; +end + +endmodule + diff --git a/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl b/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl old mode 100644 new mode 100755 index 0455113cd..57239c98f --- a/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl +++ b/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl @@ -62,6 +62,8 @@ ad_ip_files jesd204_rx [list \ jesd204_rx_cgs.v \ jesd204_rx_ctrl.v \ jesd204_rx_lane.v \ + jesd204_rx_frame_mark.v \ + jesd204_rx_frame_align_monitor.v \ jesd204_rx_constr.sdc \ ../jesd204_common/jesd204_eof_generator.v \ ../jesd204_common/jesd204_lmfc.v \ @@ -134,6 +136,7 @@ add_interface_port config cfg_lmfc_offset lmfc_offset Input 8 add_interface_port config cfg_octets_per_frame octets_per_frame Input 8 add_interface_port config cfg_sysref_disable sysref_disable Input 1 add_interface_port config cfg_sysref_oneshot sysref_oneshot 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 @@ -148,6 +151,7 @@ add_interface_port status status_lane_cgs_state lane_cgs_state Output 2*NUM_LANE 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 # event interface diff --git a/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl b/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl old mode 100644 new mode 100755 index 59eaa0250..f7d518d05 --- a/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl +++ b/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl @@ -58,6 +58,8 @@ adi_ip_files jesd204_rx [list \ "jesd204_ilas_monitor.v" \ "align_mux.v" \ "jesd204_lane_latency_monitor.v" \ + "jesd204_rx_frame_mark.v" \ + "jesd204_rx_frame_align_monitor.v" \ "jesd204_rx_constr.ttcl" \ "jesd204_rx.v" \ ] @@ -110,6 +112,7 @@ adi_add_bus "rx_cfg" "slave" \ { "ctrl_err_statistics_reset" "err_statistics_reset" } \ { "ctrl_err_statistics_mask" "err_statistics_mask" } \ { "cfg_disable_scrambler" "disable_scrambler" } \ + { "cfg_frame_align_err_threshold" "frame_align_err_threshold" } \ } adi_add_bus "rx_status" "master" \ @@ -122,6 +125,7 @@ adi_add_bus "rx_status" "master" \ { "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" } \ } adi_add_bus "rx_ilas_config" "master" \ @@ -182,6 +186,7 @@ set_property -dict [list \ 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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_lane.v b/library/jesd204/jesd204_rx/jesd204_rx_lane.v old mode 100644 new mode 100755 index 002458277..a4c35c6ff --- a/library/jesd204/jesd204_rx/jesd204_rx_lane.v +++ b/library/jesd204/jesd204_rx/jesd204_rx_lane.v @@ -49,7 +49,8 @@ module jesd204_rx_lane #( parameter CHAR_INFO_REGISTERED = 0, parameter ALIGN_MUX_REGISTERED = 0, parameter SCRAMBLER_REGISTERED = 0, - parameter ELASTIC_BUFFER_SIZE = 256 + parameter ELASTIC_BUFFER_SIZE = 256, + parameter ENABLE_FRAME_ALIGN_CHECK = 0 ) ( input clk, input reset, @@ -69,6 +70,8 @@ module jesd204_rx_lane #( output buffer_ready_n, input buffer_release_n, + input [7:0] cfg_beats_per_multiframe, + input [7:0] cfg_octets_per_frame, input cfg_disable_scrambler, output ilas_config_valid, @@ -81,7 +84,8 @@ module jesd204_rx_lane #( output [1:0] status_cgs_state, output status_ifs_ready, - output [1:0] status_frame_align + output [1:0] status_frame_align, + output [7:0] status_frame_align_err_cnt ); localparam MAX_DATA_PATH_WIDTH = 8; @@ -237,6 +241,26 @@ pipeline_stage #( }) ); +generate +if(ENABLE_FRAME_ALIGN_CHECK) begin : gen_frame_align_monitor +jesd204_rx_frame_align_monitor #( + .DATA_PATH_WIDTH (DATA_PATH_WIDTH) +) i_align_monitor ( + .clk (clk), + .reset (buffer_ready_n_s), + .cfg_beats_per_multiframe (cfg_beats_per_multiframe), + .cfg_octets_per_frame (cfg_octets_per_frame), + .cfg_disable_scrambler (cfg_disable_scrambler), + .charisk28 (charisk28_aligned), + .data (data_aligned), + .align_err_cnt (status_frame_align_err_cnt) +); + +end else begin : gen_no_frame_align_monitor + assign status_frame_align_err_cnt = 32'd0; +end +endgenerate + jesd204_scrambler #( .WIDTH(DATA_PATH_WIDTH*8), .DESCRAMBLE(1) diff --git a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v old mode 100644 new mode 100755 index c9dd2e3b6..249c5987a --- a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v +++ b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v @@ -66,7 +66,8 @@ module jesd204_rx_static_config #( output [7:0] cfg_buffer_delay, output cfg_buffer_early_release, output cfg_disable_scrambler, - output cfg_disable_char_replacement + output cfg_disable_char_replacement, + output [7:0] cfg_frame_align_err_threshold ); /* Only 4 is supported at the moment for 8b/10b and 8 for 64b */ @@ -83,5 +84,6 @@ assign cfg_lanes_disable = {NUM_LANES{1'b0}}; assign cfg_links_disable = {NUM_LINKS{1'b0}}; assign cfg_disable_scrambler = SCR ? 1'b0 : 1'b1; assign cfg_disable_char_replacement = cfg_disable_scrambler; +assign cfg_frame_align_err_threshold = 8'd4; endmodule diff --git a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl old mode 100644 new mode 100755 index a4322be84..67b595e9c --- a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl +++ b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl @@ -63,6 +63,7 @@ adi_add_bus "rx_cfg" "master" \ { "cfg_sysref_oneshot" "sysref_oneshot" } \ { "cfg_sysref_disable" "sysref_disable" } \ { "cfg_buffer_early_release" "buffer_early_release" } \ + { "cfg_frame_align_err_threshold" "frame_align_err_threshold" } \ } adi_add_bus_clock "clk" "rx_cfg" diff --git a/library/jesd204/tb/frame_align_tb b/library/jesd204/tb/frame_align_tb new file mode 100755 index 000000000..76fb9cead --- /dev/null +++ b/library/jesd204/tb/frame_align_tb @@ -0,0 +1,17 @@ +#!/bin/bash + +SOURCE="frame_align_tb.v" +SOURCE+=" ../jesd204_common/jesd204_lmfc.v ../jesd204_common/jesd204_scrambler.v ../jesd204_common/jesd204_eof_generator.v" +SOURCE+=" ../jesd204_common/pipeline_stage.v" +SOURCE+=" ../jesd204_rx/jesd204_rx.v ../jesd204_rx/jesd204_rx_lane.v" +SOURCE+=" ../jesd204_rx/jesd204_ilas_monitor.v ../jesd204_rx/align_mux.v ../jesd204_rx/jesd204_rx_cgs.v" +SOURCE+=" ../jesd204_rx/jesd204_rx_ctrl.v ../jesd204_rx/elastic_buffer.v ../jesd204_rx/jesd204_lane_latency_monitor.v" +SOURCE+=" ../jesd204_rx/jesd204_rx_frame_mark.v ../jesd204_rx/jesd204_rx_frame_align_monitor.v" +SOURCE+=" ../jesd204_rx_static_config/jesd204_rx_static_config.v" +SOURCE+=" ../jesd204_tx/jesd204_tx.v ../jesd204_tx/jesd204_tx_ctrl.v ../jesd204_tx/jesd204_tx_lane.v" +SOURCE+=" ../jesd204_tx_static_config/jesd204_tx_static_config.v" +SOURCE+=" ../jesd204_tx_static_config/jesd204_ilas_cfg_static.v" +SOURCE+=" ../../util_cdc/sync_bits.v" + +cd `dirname $0` +source run_tb.sh diff --git a/library/jesd204/tb/frame_align_tb.v b/library/jesd204/tb/frame_align_tb.v new file mode 100755 index 000000000..83c92225d --- /dev/null +++ b/library/jesd204/tb/frame_align_tb.v @@ -0,0 +1,384 @@ +// +// The ADI JESD204 Core is released under the following license, which is +// different than all other HDL cores in this repository. +// +// Please read this, and understand the freedoms and responsibilities you have +// by using this source code/core. +// +// The JESD204 HDL, is copyright © 2016-2017 Analog Devices Inc. +// +// This core is free software, you can use run, copy, study, change, ask +// questions about and improve this core. Distribution of source, or resulting +// binaries (including those inside an FPGA or ASIC) require you to release the +// source of the entire project (excluding the system libraries provide by the +// tools/compiler/FPGA vendor). These are the terms of the GNU General Public +// License version 2 as published by the Free Software Foundation. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License version 2 +// along with this source code, and binary. If not, see +// . +// +// Commercial licenses (with commercial support) of this JESD204 core are also +// available under terms different than the General Public License. (e.g. they +// do not require you to accompany any image (FPGA or ASIC) using the JESD204 +// core with any corresponding source code.) For these alternate terms you must +// purchase a license from Analog Devices Technology Licensing Office. Users +// interested in such a license should contact jesd204-licensing@analog.com for +// more information. This commercial license is sub-licensable (if you purchase +// chips from Analog Devices, incorporate them into your PCB level product, and +// purchase a JESD204 license, end users of your product will also have a +// license to use this core in a commercial setting without releasing their +// source code). +// +// In addition, we kindly ask you to acknowledge ADI in any program, application +// or publication in which you use this JESD204 HDL core. (You are not required +// to do so; it is up to your common sense to decide whether you want to comply +// with this request or not.) For general publications, we suggest referencing : +// “The design and implementation of the JESD204 HDL Core used in this project +// is copyright © 2016-2017, Analog Devices, Inc.” +// + +`timescale 1ns/100ps + +module frame_align_tb; + parameter VCD_FILE = "frame_align_tb.vcd"; + parameter NUM_LANES = 4; + parameter NUM_LINKS = 1; + parameter OCTETS_PER_FRAME = 4; + parameter FRAMES_PER_MULTIFRAME = 16; + parameter ENABLE_SCRAMBLER = 1; + parameter BUFFER_EARLY_RELEASE = 1; + parameter LANE_DELAY = 1; + parameter ALIGN_ERROR_PERCENT = 50; + + localparam BEATS_PER_MULTIFRAME = OCTETS_PER_FRAME * FRAMES_PER_MULTIFRAME / 4; + localparam TX_LATENCY = 3; + localparam RX_LATENCY = 3; + localparam BASE_LATENCY = TX_LATENCY + RX_LATENCY; + + `define TIMEOUT 1000000 + + `include "tb_base.v" + + reg [5:0] tx_counter = 'h00; + reg [5:0] rx_counter = 'h00; + reg [NUM_LANES*32-1:0] rx_mask = 'hffff0000; + wire tx_ready; + wire rx_valid; + wire [NUM_LANES*32-1:0] rx_data; + reg data_mismatch = 1'b1; + wire [NUM_LINKS-1:0] sync; + + always @(posedge clk) begin + if (sync == 1'b0) begin + tx_counter <= 'h00000000; + end else if (tx_ready == 1'b1) begin + tx_counter <= tx_counter + 1'b1; + end + end + + always @(posedge clk) begin + if (sync == 1'b0) begin + rx_counter <= 'h00000000; + if (ENABLE_SCRAMBLER == 1'b1) begin + rx_mask <= {NUM_LANES{32'hffff0000}}; // First two octets are invalid due to scrambling + end else begin + rx_mask <= {NUM_LANES{32'hffffffff}}; + end + end else if (rx_valid == 1'b1) begin + rx_counter <= rx_counter + 1'b1; + rx_mask <= {NUM_LANES{32'hffffffff}}; + end + end + + wire [31:0] tx_data = {tx_counter,2'h3,tx_counter,2'h2,tx_counter,2'h1,tx_counter,2'h0}; + wire [31:0] rx_ref_data = {rx_counter,2'h3,rx_counter,2'h2,rx_counter,2'h1,rx_counter,2'h0}; + + wire [NUM_LANES*32-1:0] phy_data_out; + wire [NUM_LANES*4-1:0] phy_charisk_out; + wire [NUM_LANES*32-1:0] phy_data_delayed; + wire [NUM_LANES*4-1:0] phy_charisk_delayed; + reg [NUM_LANES*32-1:0] phy_data_in; + reg [NUM_LANES*4-1:0] phy_charisk_in; + + reg align_err_mf; + reg align_err_f; + reg cur_err; + + reg [5:0] sysref_counter = 'h00; + reg sysref_rx = 1'b0; + reg sysref_tx = 1'b0; + + always @(posedge clk) begin + if (sysref_counter == 'h2f) + sysref_rx <= ~sysref_rx; + sysref_counter <= sysref_counter + 1'b1; + sysref_tx <= sysref_rx; + end + + localparam MAX_LANE_DELAY = LANE_DELAY + NUM_LANES; + + reg [10:0] phy_delay_fifo_wr; + reg [36*NUM_LANES-1:0] phy_delay_fifo[0:MAX_LANE_DELAY-1]; + + always @(posedge clk) begin + phy_delay_fifo[phy_delay_fifo_wr] <= {phy_charisk_out,phy_data_out}; + + if (reset == 1'b1 || phy_delay_fifo_wr == MAX_LANE_DELAY-1) begin + phy_delay_fifo_wr <= 'h00; + end else begin + phy_delay_fifo_wr <= phy_delay_fifo_wr + 1'b1; + end + end + + initial begin + align_err_mf = 1'b0; + align_err_f = 1'b0; + + #100000; + align_err_f = 1'b1; + #50000; + align_err_f = 1'b0; + #100000; + + align_err_mf = 1'b1; + #50000; + align_err_mf = 1'b0; + #100000; + + align_err_f = 1'b1; + align_err_mf = 1'b1; + #50000; + align_err_f = 1'b0; + align_err_mf = 1'b0; + #100000; + end + + always @(posedge clk) begin + if(ALIGN_ERROR_PERCENT != 0) begin + cur_err <= $urandom_range(99) < ALIGN_ERROR_PERCENT; + end else begin + cur_err <= 1'b0; + end + end + + genvar i; + generate for (i = 0; i < NUM_LANES; i = i + 1) begin + localparam OFF = MAX_LANE_DELAY - (i + LANE_DELAY); + assign phy_data_delayed[32*i+31:32*i] = + phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][32*i+31:32*i]; + assign phy_charisk_delayed[4*i+3:4*i] = + phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][4*i+3+NUM_LANES*32:4*i+32*NUM_LANES]; + end endgenerate + + always @(*) begin + phy_data_in = phy_data_delayed; + phy_charisk_in = phy_charisk_delayed; + + if(cur_err) begin + if(align_err_mf) begin + phy_data_in = {NUM_LANES*4{8'h7C}}; + phy_charisk_in = {NUM_LANES*4{1'b1}}; + end else if(align_err_f) begin + phy_data_in = {NUM_LANES*4{8'hFC}}; + phy_charisk_in = {NUM_LANES*4{1'b1}}; + end + end + end + + + wire [NUM_LANES-1:0] tx_cfg_lanes_disable; + wire [NUM_LINKS-1:0] tx_cfg_links_disable; + wire [7:0] tx_cfg_beats_per_multiframe; + wire [7:0] tx_cfg_octets_per_frame; + wire [7:0] tx_cfg_lmfc_offset; + wire tx_cfg_sysref_disable; + wire tx_cfg_sysref_oneshot; + wire tx_cfg_continuous_cgs; + wire tx_cfg_continuous_ilas; + wire tx_cfg_skip_ilas; + wire [7:0] tx_cfg_mframes_per_ilas; + wire tx_cfg_disable_char_replacement; + wire tx_cfg_disable_scrambler; + + wire tx_ilas_config_rd; + wire [1:0] tx_ilas_config_addr; + wire [32*NUM_LANES-1:0] tx_ilas_config_data; + + jesd204_tx_static_config #( + .NUM_LANES(NUM_LANES), + .NUM_LINKS(NUM_LINKS), + .OCTETS_PER_FRAME(OCTETS_PER_FRAME), + .FRAMES_PER_MULTIFRAME(FRAMES_PER_MULTIFRAME), + .SCR(ENABLE_SCRAMBLER) + ) i_tx_cfg ( + .clk(clk), + + .cfg_lanes_disable(tx_cfg_lanes_disable), + .cfg_links_disable(tx_cfg_links_disable), + .cfg_beats_per_multiframe(tx_cfg_beats_per_multiframe), + .cfg_octets_per_frame(tx_cfg_octets_per_frame), + .cfg_lmfc_offset(tx_cfg_lmfc_offset), + .cfg_sysref_disable(tx_cfg_sysref_disable), + .cfg_sysref_oneshot(tx_cfg_sysref_oneshot), + .cfg_continuous_cgs(tx_cfg_continuous_cgs), + .cfg_continuous_ilas(tx_cfg_continuous_ilas), + .cfg_skip_ilas(tx_cfg_skip_ilas), + .cfg_mframes_per_ilas(tx_cfg_mframes_per_ilas), + .cfg_disable_char_replacement(tx_cfg_disable_char_replacement), + .cfg_disable_scrambler(tx_cfg_disable_scrambler), + + .ilas_config_rd(tx_ilas_config_rd), + .ilas_config_addr(tx_ilas_config_addr), + .ilas_config_data(tx_ilas_config_data) + ); + + jesd204_tx #( + .NUM_LANES(NUM_LANES), + .NUM_LINKS(NUM_LINKS) + ) i_tx ( + .clk(clk), + .reset(reset), + + .cfg_lanes_disable(tx_cfg_lanes_disable), + .cfg_links_disable(tx_cfg_links_disable), + .cfg_beats_per_multiframe(tx_cfg_beats_per_multiframe), + .cfg_octets_per_frame(tx_cfg_octets_per_frame), + .cfg_lmfc_offset(tx_cfg_lmfc_offset), + .cfg_sysref_disable(tx_cfg_sysref_disable), + .cfg_sysref_oneshot(tx_cfg_sysref_oneshot), + .cfg_continuous_cgs(tx_cfg_continuous_cgs), + .cfg_continuous_ilas(tx_cfg_continuous_ilas), + .cfg_skip_ilas(tx_cfg_skip_ilas), + .cfg_mframes_per_ilas(tx_cfg_mframes_per_ilas), + .cfg_disable_char_replacement(tx_cfg_disable_char_replacement), + .cfg_disable_scrambler(tx_cfg_disable_scrambler), + + .ilas_config_rd(tx_ilas_config_rd), + .ilas_config_addr(tx_ilas_config_addr), + .ilas_config_data(tx_ilas_config_data), + + .ctrl_manual_sync_request(1'b0), + + .tx_ready(tx_ready), + .tx_data({NUM_LANES{tx_data}}), + + .sync(sync), + .sysref(sysref_tx), + + .phy_data(phy_data_out), + .phy_charisk(phy_charisk_out) + ); + + wire [NUM_LANES-1:0] rx_cfg_lanes_disable; + wire [NUM_LINKS-1:0] rx_cfg_links_disable; + wire [7:0] rx_cfg_beats_per_multiframe; + wire [7:0] rx_cfg_octets_per_frame; + wire [7:0] rx_cfg_lmfc_offset; + wire rx_sysref_disable; + wire rx_sysref_oneshot; + wire rx_cfg_disable_scrambler; + wire rx_cfg_disable_char_replacement; + wire rx_cfg_buffer_early_release; + wire [7:0] rx_cfg_buffer_delay; + wire [NUM_LANES-1:0] rx_status_lane_ifs_ready; + wire [NUM_LANES*14-1:0] rx_status_lane_latency; + wire [NUM_LANES*8-1:0] rx_status_lane_frame_align_err_cnt; + wire [7:0] rx_cfg_frame_align_err_threshold; + + jesd204_rx_static_config #( + .NUM_LANES(NUM_LANES), + .OCTETS_PER_FRAME(OCTETS_PER_FRAME), + .FRAMES_PER_MULTIFRAME(FRAMES_PER_MULTIFRAME), + .SCR(ENABLE_SCRAMBLER), + .BUFFER_EARLY_RELEASE(BUFFER_EARLY_RELEASE) + ) i_rx_cfg ( + .clk(clk), + + .cfg_lanes_disable(rx_cfg_lanes_disable), + .cfg_links_disable(rx_cfg_links_disable), + .cfg_beats_per_multiframe(rx_cfg_beats_per_multiframe), + .cfg_octets_per_frame(rx_cfg_octets_per_frame), + .cfg_lmfc_offset(rx_cfg_lmfc_offset), + .cfg_sysref_disable(rx_cfg_sysref_disable), + .cfg_sysref_oneshot(rx_cfg_sysref_oneshot), + .cfg_disable_scrambler(rx_cfg_disable_scrambler), + .cfg_disable_char_replacement(rx_cfg_disable_char_replacement), + .cfg_buffer_delay(rx_cfg_buffer_delay), + .cfg_buffer_early_release(rx_cfg_buffer_early_release), + .cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold) + ); + + jesd204_rx #( + .NUM_LANES(NUM_LANES) + ) i_rx ( + .clk(clk), + .reset(reset), + + .cfg_lanes_disable(rx_cfg_lanes_disable), + .cfg_links_disable(rx_cfg_links_disable), + .cfg_beats_per_multiframe(rx_cfg_beats_per_multiframe), + .cfg_octets_per_frame(rx_cfg_octets_per_frame), + .cfg_lmfc_offset(rx_cfg_lmfc_offset), + .cfg_sysref_disable(rx_cfg_sysref_disable), + .cfg_sysref_oneshot(rx_cfg_sysref_oneshot), + .cfg_disable_scrambler(rx_cfg_disable_scrambler), + .cfg_disable_char_replacement(rx_cfg_disable_char_replacement), + .cfg_buffer_delay(rx_cfg_buffer_delay), + .cfg_buffer_early_release(rx_cfg_buffer_early_release), + .cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold), + + .sync(sync), + .sysref(sysref_rx), + + .rx_data(rx_data), + .rx_valid(rx_valid), + + .phy_data(phy_data_in), + .phy_charisk(phy_charisk_in), + .phy_notintable({NUM_LANES{4'b0000}}), + .phy_disperr({NUM_LANES{4'b0000}}), + + .status_lane_ifs_ready(rx_status_lane_ifs_ready), + .status_lane_latency(rx_status_lane_latency), + .status_lane_frame_align_err_cnt(rx_status_lane_frame_align_err_cnt) + ); + + always @(posedge clk) begin + if (reset == 1'b1) begin + data_mismatch <= 1'b0; + end else if (rx_valid == 1'b1) begin + if ((rx_data & rx_mask) !== ({NUM_LANES{rx_ref_data}} & rx_mask)) begin + data_mismatch <= 1'b1; + end + end + end + + reg [NUM_LANES-1:0] lane_latency_match; + + generate for (i = 0; i < NUM_LANES; i = i + 1) begin + localparam LANE_OFFSET = BASE_LATENCY + LANE_DELAY + BEATS_PER_MULTIFRAME + i; + + always @(posedge clk) begin + if (rx_status_lane_ifs_ready[i] == 1'b1 && + rx_status_lane_latency[i*14+13:i*14+2] == LANE_OFFSET) begin + lane_latency_match[i] <= 1'b1; + end else begin + lane_latency_match[i] <= 1'b0; + end + end + end endgenerate + + always @(*) begin + if (rx_valid !== 1'b1 || tx_ready !== 1'b1 || data_mismatch == 1'b1 || + &lane_latency_match != 1'b1) begin + failed <= 1'b1; + end else begin + failed <= 1'b0; + end + end +endmodule diff --git a/library/jesd204/tb/loopback_tb b/library/jesd204/tb/loopback_tb index a17c5b512..a840ec83d 100755 --- a/library/jesd204/tb/loopback_tb +++ b/library/jesd204/tb/loopback_tb @@ -6,6 +6,7 @@ SOURCE+=" ../jesd204_common/pipeline_stage.v" SOURCE+=" ../jesd204_rx/jesd204_rx.v ../jesd204_rx/jesd204_rx_lane.v" SOURCE+=" ../jesd204_rx/jesd204_ilas_monitor.v ../jesd204_rx/align_mux.v ../jesd204_rx/jesd204_rx_cgs.v" SOURCE+=" ../jesd204_rx/jesd204_rx_ctrl.v ../jesd204_rx/elastic_buffer.v ../jesd204_rx/jesd204_lane_latency_monitor.v" +SOURCE+=" ../jesd204_rx/jesd204_rx_frame_mark.v ../jesd204_rx/jesd204_rx_frame_align_monitor.v" SOURCE+=" ../jesd204_rx_static_config/jesd204_rx_static_config.v" SOURCE+=" ../jesd204_tx/jesd204_tx.v ../jesd204_tx/jesd204_tx_ctrl.v ../jesd204_tx/jesd204_tx_lane.v" SOURCE+=" ../jesd204_tx_static_config/jesd204_tx_static_config.v" diff --git a/library/jesd204/tb/loopback_tb.v b/library/jesd204/tb/loopback_tb.v old mode 100644 new mode 100755 index f03b99a01..67eb0da06 --- a/library/jesd204/tb/loopback_tb.v +++ b/library/jesd204/tb/loopback_tb.v @@ -231,6 +231,8 @@ module loopback_tb; wire [7:0] rx_cfg_buffer_delay; wire [NUM_LANES-1:0] rx_status_lane_ifs_ready; wire [NUM_LANES*14-1:0] rx_status_lane_latency; + wire [NUM_LANES*32-1:0] rx_status_lane_frame_align_err_cnt; + wire [31:0] rx_cfg_frame_align_err_threshold = 32'd4; // TODO: static config jesd204_rx_static_config #( .NUM_LANES(NUM_LANES), @@ -271,6 +273,7 @@ module loopback_tb; .cfg_disable_char_replacement(rx_cfg_disable_char_replacement), .cfg_buffer_delay(rx_cfg_buffer_delay), .cfg_buffer_early_release(rx_cfg_buffer_early_release), + .cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold), .sync(sync), .sysref(sysref_rx), @@ -284,7 +287,8 @@ module loopback_tb; .phy_disperr({NUM_LANES{4'b0000}}), .status_lane_ifs_ready(rx_status_lane_ifs_ready), - .status_lane_latency(rx_status_lane_latency) + .status_lane_latency(rx_status_lane_latency), + .status_lane_frame_align_err_cnt(rx_status_lane_frame_align_err_cnt) ); always @(posedge clk) begin diff --git a/library/jesd204/tb/run_tb.sh b/library/jesd204/tb/run_tb.sh old mode 100644 new mode 100755 index 4769fa4d8..e6c857949 --- a/library/jesd204/tb/run_tb.sh +++ b/library/jesd204/tb/run_tb.sh @@ -1,24 +1,30 @@ NAME=`basename $0` case "$SIMULATOR" in - modelsim) - # ModelSim flow - vlib work - vlog ${SOURCE} || exit 1 - vsim ${NAME} -do "add log /* -r; run -a" -gui || exit 1 - ;; - xsim) - # xsim flow - xvlog -log ${NAME}_xvlog.log --sourcelibdir . ${SOURCE} - xelab -log ${NAME}_xelab.log -debug all ${NAME} - xsim work.${NAME} -R - ;; - *) + modelsim) + # ModelSim flow + vlib work + vlog ${SOURCE} || exit 1 + vsim ${NAME} -do "add log /* -r; run -a" -gui || exit 1 + ;; + xcelium) + # Xcelium flow + xmvlog -NOWARN NONPRT ${SOURCE} || exit 1 + xmelab -access +rc ${NAME} + xmsim ${NAME} -run -gui || exit 1 + ;; + xsim) + # xsim flow + xvlog -log ${NAME}_xvlog.log --sourcelibdir . ${SOURCE} + xelab -log ${NAME}_xelab.log -debug all ${NAME} + xsim work.${NAME} -R + ;; + *) mkdir -p run mkdir -p vcd iverilog ${SOURCE} -o run/run_${NAME} $1 || exit 1 cd vcd ../run/run_${NAME} - ;; + ;; esac diff --git a/library/jesd204/tb/tb_base.v b/library/jesd204/tb/tb_base.v old mode 100644 new mode 100755 index 459ae7573..629836e98 --- a/library/jesd204/tb/tb_base.v +++ b/library/jesd204/tb/tb_base.v @@ -67,7 +67,7 @@ $finish; end - always @(*) #10 clk <= ~clk; + initial forever #10 clk <= ~clk; always @(posedge clk) begin if (trigger_reset == 1'b1) begin reset_shift <= 3'b111;