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
main
Matt Blanton 2020-01-29 09:41:43 -05:00 committed by Laszlo Nagy
parent ef5f29e66b
commit 1e04b2e2f2
20 changed files with 945 additions and 39 deletions

12
library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v Normal file → Executable file
View File

@ -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),

2
library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl Normal file → Executable file
View File

@ -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

2
library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl Normal file → Executable file
View File

@ -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" } \
}

26
library/jesd204/axi_jesd204_rx/jesd204_up_rx.v Normal file → Executable file
View File

@ -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),

7
library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v Normal file → Executable file
View File

@ -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

1
library/jesd204/interfaces/interfaces_ip.tcl Normal file → Executable file
View File

@ -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

74
library/jesd204/jesd204_rx/jesd204_rx.v Normal file → Executable file
View File

@ -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;

View File

@ -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
// <http://www.gnu.org/licenses/>.
//
// 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

View File

@ -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
// <http://www.gnu.org/licenses/>.
//
// 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

4
library/jesd204/jesd204_rx/jesd204_rx_hw.tcl Normal file → Executable file
View File

@ -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

5
library/jesd204/jesd204_rx/jesd204_rx_ip.tcl Normal file → Executable file
View File

@ -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

28
library/jesd204/jesd204_rx/jesd204_rx_lane.v Normal file → Executable file
View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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
// <http://www.gnu.org/licenses/>.
//
// 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

View File

@ -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"

6
library/jesd204/tb/loopback_tb.v Normal file → Executable file
View File

@ -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

34
library/jesd204/tb/run_tb.sh Normal file → Executable file
View File

@ -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

2
library/jesd204/tb/tb_base.v Normal file → Executable file
View File

@ -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;