jesd204: Add support for 8-byte JESD204B, frame alignment character insertion/replacement

Add support to JESD204 RX and TX core for 8-byte 8b/10b link mode,
and frame alignment character replace/insert with or without scrambling.
Add support for xcelium simulator to jesd204/tb
Increased cores minor version.
main
Matt Blanton 2020-01-30 17:05:13 -05:00 committed by Laszlo Nagy
parent 7be66b63c1
commit 400c3927f7
48 changed files with 1538 additions and 507 deletions

18
library/jesd204/axi_jesd204_common/jesd204_up_common.v Normal file → Executable file
View File

@ -50,7 +50,7 @@ module jesd204_up_common # (
parameter ID = 0,
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter DATA_PATH_WIDTH = 2,
parameter DATA_PATH_WIDTH_LOG2 = 2,
parameter MAX_OCTETS_PER_FRAME = 256,
parameter NUM_IRQS = 1,
parameter EXTRA_CFG_WIDTH = 1,
@ -84,19 +84,17 @@ module jesd204_up_common # (
output reg [NUM_LANES-1:0] core_cfg_lanes_disable,
output reg [NUM_LINKS-1:0] core_cfg_links_disable,
output reg [7:0] core_cfg_beats_per_multiframe,
output reg [9:0] core_cfg_octets_per_multiframe,
output reg [7:0] core_cfg_octets_per_frame,
output reg core_cfg_disable_scrambler,
output reg core_cfg_disable_char_replacement,
output reg [EXTRA_CFG_WIDTH-1:0] core_extra_cfg
);
localparam MAX_BEATS_PER_MULTIFRAME = (MAX_OCTETS_PER_FRAME * 32) / DATA_PATH_WIDTH;
reg [31:0] up_scratch = 32'h00000000;
reg [7:0] up_cfg_octets_per_frame = 'h00;
reg [9-DATA_PATH_WIDTH:0] up_cfg_beats_per_multiframe = 'h00;
reg [9:0] up_cfg_octets_per_multiframe = 'h00;
reg [NUM_LANES-1:0] up_cfg_lanes_disable = {NUM_LANES{1'b0}};
reg [NUM_LINKS-1:0] up_cfg_links_disable = {NUM_LINKS{1'b0}};
reg up_cfg_disable_char_replacement = 1'b0;
@ -169,7 +167,7 @@ end
always @(posedge core_clk) begin
if (core_cfg_transfer_en == 1'b1) begin
core_cfg_beats_per_multiframe <= up_cfg_beats_per_multiframe;
core_cfg_octets_per_multiframe <= up_cfg_octets_per_multiframe;
core_cfg_octets_per_frame <= up_cfg_octets_per_frame;
core_cfg_lanes_disable <= up_cfg_lanes_disable;
core_cfg_links_disable <= up_cfg_links_disable;
@ -264,7 +262,7 @@ always @(*) begin
/* Core configuration */
12'h004: up_rdata = NUM_LANES;
12'h005: up_rdata = DATA_PATH_WIDTH;
12'h005: up_rdata = DATA_PATH_WIDTH_LOG2;
12'h006: up_rdata = {22'b0,LINK_MODE[1:0], NUM_LINKS[7:0]};
/* 0x07-0x0f reserved for future use */
/* 0x10-0x1f reserved for core specific HDL configuration information */
@ -287,7 +285,7 @@ always @(*) begin
/* 24-31 */ 8'h00, /* Reserved for future extensions of octets_per_frame */
/* 16-23 */ up_cfg_octets_per_frame,
/* 10-15 */ 6'b000000, /* Reserved for future extensions of beats_per_multiframe */
/* 00-09 */ up_cfg_beats_per_multiframe,{DATA_PATH_WIDTH{1'b1}}
/* 00-09 */ up_cfg_octets_per_multiframe
};
12'h85: up_rdata = {
/* 02-31 */ 30'h00, /* Reserved for future additions */
@ -327,7 +325,7 @@ always @(posedge up_clk) begin
up_reset_core <= 1'b1;
up_cfg_octets_per_frame <= 'h00;
up_cfg_beats_per_multiframe <= 'h00;
up_cfg_octets_per_multiframe <= 'h00;
up_cfg_lanes_disable <= {NUM_LANES{1'b0}};
up_cfg_links_disable <= {NUM_LINKS{1'b0}};
@ -358,7 +356,7 @@ always @(posedge up_clk) begin
end
12'h084: begin
up_cfg_octets_per_frame <= up_wdata[23:16];
up_cfg_beats_per_multiframe <= up_wdata[9:DATA_PATH_WIDTH];
up_cfg_octets_per_multiframe <= up_wdata[9:0];
end
12'h085: begin
up_cfg_disable_char_replacement <= up_wdata[1];

4
library/jesd204/axi_jesd204_common/jesd204_up_sysref.v Normal file → Executable file
View File

@ -45,7 +45,7 @@
`timescale 1ns/100ps
module jesd204_up_sysref #(
parameter DATA_PATH_WIDTH = 2
parameter DATA_PATH_WIDTH_LOG2 = 2
) (
input up_clk,
input up_reset,
@ -128,7 +128,7 @@ always @(posedge up_clk) begin
end
12'h041: begin
/* Aligned to data path width */
up_cfg_lmfc_offset <= up_wdata[9:DATA_PATH_WIDTH];
up_cfg_lmfc_offset <= up_wdata[9:DATA_PATH_WIDTH_LOG2];
end
endcase
end

View File

@ -49,7 +49,8 @@ module axi_jesd204_rx #(
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter ENABLE_LINK_STATS = 0
parameter ENABLE_LINK_STATS = 0,
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input s_axi_aclk,
input s_axi_aresetn,
@ -82,7 +83,7 @@ module axi_jesd204_rx #(
output [NUM_LANES-1:0] core_cfg_lanes_disable,
output [NUM_LINKS-1:0] core_cfg_links_disable,
output [7:0] core_cfg_beats_per_multiframe,
output [9:0] core_cfg_octets_per_multiframe,
output [7:0] core_cfg_octets_per_frame,
output core_cfg_disable_scrambler,
output core_cfg_disable_char_replacement,
@ -95,7 +96,7 @@ module axi_jesd204_rx #(
input [NUM_LANES-1:0] core_ilas_config_valid,
input [2*NUM_LANES-1:0] core_ilas_config_addr,
input [32*NUM_LANES-1:0] core_ilas_config_data,
input [NUM_LANES*DATA_PATH_WIDTH*8-1:0] core_ilas_config_data,
input core_event_sysref_alignment_error,
input core_event_sysref_edge,
@ -115,10 +116,10 @@ module axi_jesd204_rx #(
input [8*NUM_LANES-1:0] core_status_lane_frame_align_err_cnt
);
localparam PCORE_VERSION = 32'h00010461; // 1.04.a
localparam PCORE_VERSION = 32'h00010561; // 1.05.a
localparam PCORE_MAGIC = 32'h32303452; // 204R
localparam DATA_PATH_WIDTH = LINK_MODE == 2 ? 3 : 2;
localparam DATA_PATH_WIDTH_LOG2 = (DATA_PATH_WIDTH == 8) ? 3 : 2;
/* Register interface signals */
reg [31:0] up_rdata = 'h0;
@ -203,7 +204,7 @@ jesd204_up_common #(
.ID(ID),
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2),
.NUM_IRQS(5),
.EXTRA_CFG_WIDTH(27),
.LINK_MODE(LINK_MODE),
@ -230,7 +231,7 @@ jesd204_up_common #(
.up_irq_trigger(up_irq_trigger),
.irq(irq),
.core_cfg_beats_per_multiframe(core_cfg_beats_per_multiframe),
.core_cfg_octets_per_multiframe(core_cfg_octets_per_multiframe),
.core_cfg_octets_per_frame(core_cfg_octets_per_frame),
.core_cfg_lanes_disable(core_cfg_lanes_disable),
.core_cfg_links_disable(core_cfg_links_disable),
@ -256,7 +257,7 @@ jesd204_up_common #(
);
jesd204_up_sysref #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2)
) i_up_sysref (
.up_clk(s_axi_aclk),
.up_reset(up_reset),
@ -280,7 +281,8 @@ jesd204_up_sysref #(
jesd204_up_rx #(
.NUM_LANES(NUM_LANES),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2)
) i_up_rx (
.up_clk(s_axi_aclk),
.up_reset(up_reset),

View File

@ -122,8 +122,8 @@ set_false_path \
# Use -quiet here since the ILAS mem is missing in non 8b10b configuration
set_max_delay -quiet -datapath_only \
-from [get_pins {i_up_rx/gen_lane[*].i_up_rx_lane/i_ilas_mem/mem_reg_*/*/CLK}] \
-to [get_pins {i_up_rx/gen_lane[*].i_up_rx_lane/i_ilas_mem/up_rdata_reg[*]/D}] \
-from [get_pins {i_up_rx/gen_lane[*].i_up_rx_lane/i_ilas_mem/mem_reg*/*/CLK}] \
-to [get_pins {i_up_rx/gen_lane[*].i_up_rx_lane/i_ilas_mem/dp_*_gen.up_rdata_reg*/D}] \
[get_property -min PERIOD $axi_clk]
set_false_path \

View File

@ -122,7 +122,7 @@ add_interface config conduit end
set_interface_property config associatedClock core_clock
set_interface_property config associatedReset core_reset
add_interface_port config core_cfg_beats_per_multiframe beats_per_multiframe Output 8
add_interface_port config core_cfg_octets_per_multiframe octets_per_multiframe Output 10
add_interface_port config core_cfg_buffer_delay buffer_delay Output 8
add_interface_port config core_cfg_buffer_early_release buffer_early_release Output 1
add_interface_port config core_cfg_disable_char_replacement disable_char_replacement Output 1

View File

@ -77,7 +77,7 @@ adi_add_bus "rx_cfg" "master" \
{ \
{ "core_cfg_lanes_disable" "lanes_disable" } \
{ "core_cfg_links_disable" "links_disable" } \
{ "core_cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "core_cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "core_cfg_octets_per_frame" "octets_per_frame" } \
{ "core_cfg_lmfc_offset" "lmfc_offset" } \
{ "core_cfg_sysref_oneshot" "sysref_oneshot" } \

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

@ -44,7 +44,9 @@
`timescale 1ns/100ps
module jesd204_up_ilas_mem (
module jesd204_up_ilas_mem #(
parameter DATA_PATH_WIDTH = 4
)(
input up_clk,
input up_rreq,
@ -56,12 +58,14 @@ module jesd204_up_ilas_mem (
input core_ilas_config_valid,
input [1:0] core_ilas_config_addr,
input [31:0] core_ilas_config_data,
input [DATA_PATH_WIDTH*8-1:0] core_ilas_config_data,
output up_ilas_ready
);
reg [31:0] mem[0:3];
localparam ILAS_DATA_LENGTH = (DATA_PATH_WIDTH == 4) ? 4 : 2;
reg [DATA_PATH_WIDTH*8-1:0] mem[0:ILAS_DATA_LENGTH-1];
reg core_ilas_captured = 1'b0;
sync_bits i_cdc_ilas_ready (
@ -75,17 +79,27 @@ always @(posedge core_clk) begin
if (core_reset == 1'b1) begin
core_ilas_captured <= 1'b0;
end else begin
if (core_ilas_config_valid == 1'b1 && core_ilas_config_addr == 'h3) begin
if (core_ilas_config_valid == 1'b1 && core_ilas_config_addr == ILAS_DATA_LENGTH-1) begin
core_ilas_captured <= 1'b1;
end
end
end
generate
if(DATA_PATH_WIDTH == 4) begin : dp_4_gen
always @(posedge up_clk) begin
if (up_rreq == 1'b1) begin
up_rdata <= mem[up_raddr];
end
end
end else if(DATA_PATH_WIDTH == 8) begin : dp_8_gen
always @(posedge up_clk) begin
if (up_rreq == 1'b1) begin
up_rdata <= mem[up_raddr[1]] >> (up_raddr[0]*32);
end
end
end
endgenerate
always @(posedge core_clk) begin
if (core_ilas_config_valid == 1'b1) begin

View File

@ -46,7 +46,8 @@
module jesd204_up_rx # (
parameter NUM_LANES = 1,
parameter DATA_PATH_WIDTH = 2
parameter DATA_PATH_WIDTH = 4,
parameter DATA_PATH_WIDTH_LOG2 = 2
) (
input up_clk,
input up_reset,
@ -64,7 +65,7 @@ module jesd204_up_rx # (
input [NUM_LANES-1:0] core_ilas_config_valid,
input [2*NUM_LANES-1:0] core_ilas_config_addr,
input [32*NUM_LANES-1:0] core_ilas_config_data,
input [NUM_LANES*DATA_PATH_WIDTH*8-1:0] core_ilas_config_data,
input [1:0] core_status_ctrl_state,
input [2*NUM_LANES-1:0] core_status_lane_cgs_state,
@ -189,7 +190,7 @@ always @(posedge up_clk) begin
/* JESD RX configuraton */
12'h090: begin
up_cfg_buffer_early_release <= up_wdata[16];
up_cfg_buffer_delay <= up_wdata[9:DATA_PATH_WIDTH];
up_cfg_buffer_delay <= up_wdata[9:DATA_PATH_WIDTH_LOG2];
end
endcase
end else if (up_wreq == 1'b1) begin
@ -207,7 +208,9 @@ end
genvar i;
generate for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
jesd204_up_rx_lane i_up_rx_lane (
jesd204_up_rx_lane #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_up_rx_lane (
.up_clk(up_clk),
.up_reset_synchronizer(up_reset_synchronizer),
@ -225,7 +228,7 @@ generate for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.core_ilas_config_valid(core_ilas_config_valid[i]),
.core_ilas_config_addr(core_ilas_config_addr[2*i+1:2*i]),
.core_ilas_config_data(core_ilas_config_data[32*i+31:32*i]),
.core_ilas_config_data(core_ilas_config_data[(DATA_PATH_WIDTH*8*i)+(DATA_PATH_WIDTH*8)-1:DATA_PATH_WIDTH*8*i]),
.core_status_ifs_ready(core_status_lane_ifs_ready[i]),
.core_status_latency(core_status_lane_latency[14*i+13:14*i])

View File

@ -44,7 +44,9 @@
`timescale 1ns/100ps
module jesd204_up_rx_lane (
module jesd204_up_rx_lane #(
parameter DATA_PATH_WIDTH = 4
)(
input up_clk,
input up_reset_synchronizer,
@ -62,7 +64,7 @@ module jesd204_up_rx_lane (
input core_ilas_config_valid,
input [1:0] core_ilas_config_addr,
input [31:0] core_ilas_config_data,
input [DATA_PATH_WIDTH*8-1:0] core_ilas_config_data,
input core_status_ifs_ready,
input [13:0] core_status_latency
@ -133,7 +135,9 @@ always @(*) begin
end
end
jesd204_up_ilas_mem i_ilas_mem (
jesd204_up_ilas_mem #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_ilas_mem (
.up_clk(up_clk),
.up_rreq(up_rreq),

20
library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v Normal file → Executable file
View File

@ -49,7 +49,8 @@ module axi_jesd204_tx #(
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter ENABLE_LINK_STATS = 0
parameter ENABLE_LINK_STATS = 0,
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input s_axi_aclk,
input s_axi_aresetn,
@ -82,7 +83,7 @@ module axi_jesd204_tx #(
output [NUM_LANES-1:0] core_cfg_lanes_disable,
output [NUM_LINKS-1:0] core_cfg_links_disable,
output [7:0] core_cfg_beats_per_multiframe,
output [9:0] core_cfg_octets_per_multiframe,
output [7:0] core_cfg_octets_per_frame,
output [7:0] core_cfg_lmfc_offset,
output core_cfg_sysref_oneshot,
@ -96,7 +97,7 @@ module axi_jesd204_tx #(
input core_ilas_config_rd,
input [1:0] core_ilas_config_addr,
output [32*NUM_LANES-1:0] core_ilas_config_data,
output [DATA_PATH_WIDTH*8*NUM_LANES-1:0] core_ilas_config_data,
input core_event_sysref_alignment_error,
input core_event_sysref_edge,
@ -107,10 +108,10 @@ module axi_jesd204_tx #(
input [NUM_LINKS-1:0] core_status_sync
);
localparam PCORE_VERSION = 32'h00010361; // 1.03.a
localparam PCORE_VERSION = 32'h00010461; // 1.04.a
localparam PCORE_MAGIC = 32'h32303454; // 204T
localparam DATA_PATH_WIDTH = LINK_MODE == 2 ? 3 : 2;
localparam DATA_PATH_WIDTH_LOG2 = (DATA_PATH_WIDTH == 8) ? 3 : 2;
wire up_reset;
@ -178,7 +179,7 @@ jesd204_up_common #(
.ID(ID),
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2),
.NUM_IRQS(5),
.EXTRA_CFG_WIDTH(21),
.MAX_OCTETS_PER_FRAME(8),
@ -208,7 +209,7 @@ jesd204_up_common #(
.up_irq_trigger(up_irq_trigger),
.irq(irq),
.core_cfg_beats_per_multiframe(core_cfg_beats_per_multiframe),
.core_cfg_octets_per_multiframe(core_cfg_octets_per_multiframe),
.core_cfg_octets_per_frame(core_cfg_octets_per_frame),
.core_cfg_lanes_disable(core_cfg_lanes_disable),
.core_cfg_links_disable(core_cfg_links_disable),
@ -236,7 +237,7 @@ jesd204_up_common #(
);
jesd204_up_sysref #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2)
) i_up_sysref (
.up_clk(s_axi_aclk),
.up_reset(up_reset),
@ -261,7 +262,8 @@ jesd204_up_sysref #(
jesd204_up_tx #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS)
.NUM_LINKS(NUM_LINKS),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_up_tx (
.up_clk(s_axi_aclk),
.up_reset(up_reset),

View File

@ -120,7 +120,7 @@ add_interface config conduit end
set_interface_property config associatedClock core_clock
set_interface_property config associatedReset core_reset
add_interface_port config core_cfg_beats_per_multiframe beats_per_multiframe Output 8
add_interface_port config core_cfg_octets_per_multiframe octets_per_multiframe Output 10
add_interface_port config core_cfg_continuous_cgs continuous_cgs Output 1
add_interface_port config core_cfg_continuous_ilas continuous_ilas Output 1
add_interface_port config core_cfg_disable_char_replacement disable_char_replacement Output 1

View File

@ -75,7 +75,7 @@ adi_add_bus "tx_cfg" "master" \
{ \
{ "core_cfg_lanes_disable" "lanes_disable" } \
{ "core_cfg_links_disable" "links_disable" } \
{ "core_cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "core_cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "core_cfg_octets_per_frame" "octets_per_frame" } \
{ "core_cfg_lmfc_offset" "lmfc_offset" } \
{ "core_cfg_sysref_oneshot" "sysref_oneshot" } \

17
library/jesd204/axi_jesd204_tx/jesd204_up_tx.v Normal file → Executable file
View File

@ -46,7 +46,8 @@
module jesd204_up_tx # (
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1
parameter NUM_LINKS = 1,
parameter DATA_PATH_WIDTH = 4
) (
input up_clk,
input up_reset,
@ -67,7 +68,7 @@ module jesd204_up_tx # (
input core_clk,
input core_ilas_config_rd,
input [1:0] core_ilas_config_addr,
output reg [32*NUM_LANES-1:0] core_ilas_config_data,
output reg [DATA_PATH_WIDTH*8*NUM_LANES-1:0] core_ilas_config_data,
output core_ctrl_manual_sync_request,
@ -294,6 +295,8 @@ always @(posedge up_clk) begin
end
end
generate
if(DATA_PATH_WIDTH == 4) begin : gen_dp_4
always @(posedge core_clk) begin
if (core_ilas_config_rd == 1'b1) begin
for (i = 0; i < NUM_LANES; i = i + 1) begin
@ -301,5 +304,15 @@ always @(posedge core_clk) begin
end
end
end
end else if(DATA_PATH_WIDTH == 8) begin : gen_dp_8
always @(posedge core_clk) begin
if (core_ilas_config_rd == 1'b1) begin
for (i = 0; i < NUM_LANES; i = i + 1) begin
core_ilas_config_data[i*64+:64] <= {up_cfg_ilas_data[i][{core_ilas_config_addr[0], 1'b1}],up_cfg_ilas_data[i][{core_ilas_config_addr[0], 1'b0}]};
end
end
end
end
endgenerate
endmodule

View File

@ -50,7 +50,7 @@ source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl
adi_if_define "jesd204_tx_cfg"
adi_if_ports output -1 lanes_disable
adi_if_ports output -1 links_disable
adi_if_ports output 8 beats_per_multiframe
adi_if_ports output 10 octets_per_multiframe
adi_if_ports output 8 octets_per_frame
adi_if_ports output 8 lmfc_offset
adi_if_ports output 1 continuous_cgs
@ -81,7 +81,7 @@ adi_if_ports output 1 manual_sync_request
adi_if_define "jesd204_rx_cfg"
adi_if_ports output -1 lanes_disable
adi_if_ports output -1 links_disable
adi_if_ports output 8 beats_per_multiframe
adi_if_ports output 10 octets_per_multiframe
adi_if_ports output 8 octets_per_frame
adi_if_ports output 8 lmfc_offset
adi_if_ports output 1 buffer_early_release

View File

@ -7,6 +7,8 @@ LIBRARY_NAME := jesd204_common
GENERIC_DEPS += jesd204_crc12.v
GENERIC_DEPS += jesd204_eof_generator.v
GENERIC_DEPS += jesd204_frame_align_replace.v
GENERIC_DEPS += jesd204_frame_mark.v
GENERIC_DEPS += jesd204_lmfc.v
GENERIC_DEPS += jesd204_scrambler.v
GENERIC_DEPS += jesd204_scrambler_64b.v

2
library/jesd204/jesd204_common/jesd204_common_ip.tcl Normal file → Executable file
View File

@ -53,6 +53,8 @@ add_files -fileset [get_filesets sources_1] [list \
"jesd204_scrambler_64b.v" \
"jesd204_crc12.v" \
"jesd204_eof_generator.v" \
"jesd204_frame_mark.v" \
"jesd204_frame_align_replace.v" \
"pipeline_stage.v" \
]

View File

@ -0,0 +1,245 @@
//
// 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, 8
// F=1,2,3,4,6, and multiples of DATA_PATH_WIDTH
`timescale 1ns/100ps
module jesd204_frame_align_replace #(
parameter DATA_PATH_WIDTH = 4,
parameter IS_RX = 1'b1
) (
input clk,
input reset,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
input [DATA_PATH_WIDTH*8-1:0] data,
input [DATA_PATH_WIDTH-1:0] eof,
input [DATA_PATH_WIDTH-1:0] rx_char_is_a,
input [DATA_PATH_WIDTH-1:0] rx_char_is_f,
input [DATA_PATH_WIDTH-1:0] tx_eomf,
output [DATA_PATH_WIDTH*8-1:0] data_out,
output [DATA_PATH_WIDTH-1:0] charisk_out
);
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
wire single_eof = cfg_octets_per_frame >= (DATA_PATH_WIDTH-1);
reg [DATA_PATH_WIDTH*8-1:0] data_d1;
reg [DATA_PATH_WIDTH*8-1:0] data_d2;
wire [DATA_PATH_WIDTH-1:0] char_is_align;
reg [DATA_PATH_WIDTH-1:0] char_is_align_d1;
reg [DATA_PATH_WIDTH-1:0] char_is_align_d2;
wire [((DATA_PATH_WIDTH*2)+4)*8-1:0] saved_data;
wire [((DATA_PATH_WIDTH*2)+4)-1:0] saved_char_is_align;
wire [DATA_PATH_WIDTH*8-1:0] data_replaced;
wire [DATA_PATH_WIDTH*8-1:0] data_prev_eof;
wire [DATA_PATH_WIDTH*8-1:0] data_prev_prev_eof;
reg [7:0] data_prev_eof_single;
reg [7:0] data_prev_eof_single_int;
reg char_is_align_prev_single;
wire [DATA_PATH_WIDTH*8-1:0] prev_data_1;
wire [DATA_PATH_WIDTH*8-1:0] prev_prev_data_1;
wire [DATA_PATH_WIDTH-1:0] prev_char_is_align_1;
wire [DATA_PATH_WIDTH*8-1:0] prev_data_2;
wire [DATA_PATH_WIDTH*8-1:0] prev_prev_data_2;
wire [DATA_PATH_WIDTH-1:0] prev_char_is_align_2;
wire [DATA_PATH_WIDTH*8-1:0] prev_data_3;
wire [DATA_PATH_WIDTH*8-1:0] prev_prev_data_3;
wire [DATA_PATH_WIDTH-1:0] prev_char_is_align_3;
wire [DATA_PATH_WIDTH*8-1:0] prev_data_4;
wire [DATA_PATH_WIDTH*8-1:0] prev_prev_data_4;
wire [DATA_PATH_WIDTH-1:0] prev_char_is_align_4;
wire [DATA_PATH_WIDTH*8-1:0] prev_data_6;
wire [DATA_PATH_WIDTH*8-1:0] prev_prev_data_6;
wire [DATA_PATH_WIDTH-1:0] prev_char_is_align_6;
reg [DATA_PATH_WIDTH*8-1:0] prev_data;
reg [DATA_PATH_WIDTH*8-1:0] prev_prev_data;
reg [DATA_PATH_WIDTH-1:0] prev_char_is_align;
reg [DPW_LOG2:0] jj;
reg [DPW_LOG2:0] ll;
always @(posedge clk) begin
data_d1 <= data;
data_d2 <= data_d1;
end
always @(posedge clk) begin
if(reset) begin
char_is_align_d1 <= 'b0;
char_is_align_d2 <= 'b0;
end else begin
char_is_align_d1 <= char_is_align;
char_is_align_d2 <= char_is_align_d1;
end
end
// Capture single EOF in current cycle
always @(eof, data) begin
data_prev_eof_single_int = 'b0;
for(ll = 0; ll < DATA_PATH_WIDTH; ll=ll+1) begin
data_prev_eof_single_int = data_prev_eof_single_int | (data[ll*8 +: 8] & {8{eof[ll]}});
end
end
always @(posedge clk) begin
if(reset) begin
data_prev_eof_single <= 'b0;
end else begin
if(|eof && (!IS_RX || !(|char_is_align))) begin
data_prev_eof_single <= data_prev_eof_single_int;
end
end
end
always @(posedge clk) begin
if(reset) begin
char_is_align_prev_single <= 'b0;
end else begin
if(|eof) begin
char_is_align_prev_single <= |char_is_align;
end
end
end
assign saved_data = {data, data_d1, data_d2[(DATA_PATH_WIDTH*8)-1:(DATA_PATH_WIDTH-4)*8]};
assign saved_char_is_align = {char_is_align, char_is_align_d1, char_is_align_d2[DATA_PATH_WIDTH-1:DATA_PATH_WIDTH-4]};
genvar ii;
generate
for (ii = 0; ii < DATA_PATH_WIDTH; ii = ii + 1) begin: gen_replace_byte
assign prev_data_1[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+3+ii)*8 +: 8];
assign prev_data_2[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+2+ii)*8 +: 8];
assign prev_data_3[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+1+ii)*8 +: 8];
assign prev_prev_data_1[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+2+ii)*8 +: 8];
assign prev_prev_data_2[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+ii)*8 +: 8];
assign prev_prev_data_3[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH-2+ii)*8 +: 8];
assign prev_char_is_align_1[ii] = saved_char_is_align[(DATA_PATH_WIDTH+3+ii)];
assign prev_char_is_align_2[ii] = saved_char_is_align[(DATA_PATH_WIDTH+2+ii)];
assign prev_char_is_align_3[ii] = saved_char_is_align[(DATA_PATH_WIDTH+1+ii)];
if(DATA_PATH_WIDTH == 8) begin : gen_dp_8
assign prev_data_4[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH+ii)*8 +: 8];
assign prev_data_6[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH-2+ii)*8 +: 8];
assign prev_prev_data_4[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH-4+ii)*8 +: 8];
assign prev_prev_data_6[ii*8 +:8] = saved_data[(DATA_PATH_WIDTH-8+ii)*8 +: 8];
assign prev_char_is_align_4[ii] = saved_char_is_align[(DATA_PATH_WIDTH+ii)];
assign prev_char_is_align_6[ii] = saved_char_is_align[(DATA_PATH_WIDTH-2+ii)];
end else begin
assign prev_data_4[ii*8 +:8] = 'bX;
assign prev_data_6[ii*8 +:8] = 'bX;
assign prev_prev_data_4[ii*8 +:8] = 'bX;
assign prev_prev_data_6[ii*8 +:8] = 'bX;
assign prev_char_is_align_4[ii] = 'bX;
assign prev_char_is_align_6[ii] = 'bX;
end
always @(*) begin
case(cfg_octets_per_frame)
0:
begin
prev_data[ii*8 +:8] = prev_data_1[ii*8 +:8];
prev_prev_data[ii*8 +:8] = prev_prev_data_1[ii*8 +:8];
prev_char_is_align[ii] = prev_char_is_align_1[ii];
end
1:
begin
prev_data[ii*8 +:8] = prev_data_2[ii*8 +:8];
prev_prev_data[ii*8 +:8] = prev_prev_data_2[ii*8 +:8];
prev_char_is_align[ii] = prev_char_is_align_2[ii];
end
2:
begin
prev_data[ii*8 +:8] = prev_data_3[ii*8 +:8];
prev_prev_data[ii*8 +:8] = prev_prev_data_3[ii*8 +:8];
prev_char_is_align[ii] = prev_char_is_align_3[ii];
end
3:
begin
prev_data[ii*8 +:8] = prev_data_4[ii*8 +:8];
prev_prev_data[ii*8 +:8] = prev_prev_data_4[ii*8 +:8];
prev_char_is_align[ii] = prev_char_is_align_4[ii];
end
5:
begin
prev_data[ii*8 +:8] = prev_data_6[ii*8 +:8];
prev_prev_data[ii*8 +:8] = prev_prev_data_6[ii*8 +:8];
prev_char_is_align[ii] = prev_char_is_align_6[ii];
end
default:
begin
prev_data[ii*8 +:8] = 'bX;
prev_prev_data[ii*8 +:8] = 'bX;
prev_char_is_align[ii] = 1'bX;
end
endcase
end
if(IS_RX) begin : gen_rx
// RX
assign char_is_align[ii] = !reset && (rx_char_is_a[ii] | rx_char_is_f[ii]);
assign data_replaced[ii*8 +: 8] = char_is_align[ii] ? data_prev_eof[ii*8 +: 8] : data[ii*8 +: 8];
assign data_prev_eof[ii*8 +: 8] = single_eof ? data_prev_eof_single : prev_char_is_align[ii] ? data_prev_prev_eof[ii*8 +: 8] : prev_data[ii*8 +: 8];
assign data_prev_prev_eof[ii*8 +: 8] = prev_prev_data[ii*8 +: 8];
end else begin : gen_tx
// TX
assign data_prev_eof[ii*8 +: 8] = single_eof ? data_prev_eof_single : prev_data[ii*8 +: 8];
assign char_is_align[ii] = !reset && (tx_eomf[ii] || (eof[ii] && !(single_eof ? char_is_align_prev_single : prev_char_is_align[ii]))) && (data[ii*8 +: 8] == data_prev_eof[ii*8 +: 8]);
assign data_replaced[ii*8 +: 8] = char_is_align[ii] ? (tx_eomf[ii] ? 8'h7c : 8'hfc) : data[ii*8 +: 8];
end
end
endgenerate
assign data_out = (cfg_disable_char_replacement || !cfg_disable_scrambler) ? data : data_replaced;
assign charisk_out = (IS_RX || !cfg_disable_scrambler || cfg_disable_char_replacement) ? 'b0 : char_is_align;
endmodule

View File

@ -43,21 +43,19 @@
//
// Limitations:
// DATA_PATH_WIDTH = 4
// DATA_PATH_WIDTH = 4, 8
// 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 #(
module jesd204_frame_mark #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_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,
@ -65,7 +63,7 @@ module jesd204_rx_frame_mark #(
output reg [DATA_PATH_WIDTH-1:0] eomf
);
localparam MAX_OCTETS_PER_FRAME = 16;
localparam MAX_OCTETS_PER_FRAME = 32;
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 :
@ -75,21 +73,33 @@ localparam CW = MAX_OCTETS_PER_FRAME > 128 ? 8 :
MAX_OCTETS_PER_FRAME > 4 ? 3 :
MAX_OCTETS_PER_FRAME > 2 ? 2 : 1;
localparam BEATS_PER_FRAME_WIDTH = CW-DPW_LOG2;
localparam BEATS_PER_MF_WIDTH = 10-DPW_LOG2;
wire [BEATS_PER_MF_WIDTH-1:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe[9:DPW_LOG2];
// For DATA_PATH_WIDTH = 8, special case if F*K%8=4
wire octets_per_mf_4_mod_8 = (DATA_PATH_WIDTH == 8) && ~cfg_octets_per_multiframe[2];
reg [BEATS_PER_MF_WIDTH-1:0] cur_beats_per_multiframe;
reg mf_phase;
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;
reg [BEATS_PER_MF_WIDTH-1:0] beat_cnt_mf;
wire cur_somf;
wire cur_eomf;
wire [DATA_PATH_WIDTH-1:0] default_sof;
wire [DATA_PATH_WIDTH-1:0] default_eof;
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];
reg [DATA_PATH_WIDTH-1:0] sof_f_12[2:0];
reg [DATA_PATH_WIDTH-1:0] eof_f_12[2:0];
generate
if(DATA_PATH_WIDTH == 4) begin : gen_dp_4
initial begin
sof_f_3[0] = {4'b1001};
sof_f_3[1] = {4'b0100};
@ -104,8 +114,29 @@ initial begin
eof_f_6[1] = {4'b0010};
eof_f_6[2] = {4'b1000};
end
// Beat count % 3, to support F=3,6
end else if(DATA_PATH_WIDTH == 8) begin : gen_dp_8
initial begin
sof_f_3[0] = {8'b01001001};
sof_f_3[1] = {8'b10010010};
sof_f_3[2] = {8'b00100100};
eof_f_3[0] = {8'b00100100};
eof_f_3[1] = {8'b01001001};
eof_f_3[2] = {8'b10010010};
sof_f_6[0] = {8'b01000001};
sof_f_6[1] = {8'b00010000};
sof_f_6[2] = {8'b00000100};
eof_f_6[0] = {8'b00100000};
eof_f_6[1] = {8'b00001000};
eof_f_6[2] = {8'b10000010};
sof_f_12[0] = {8'b00000001};
sof_f_12[1] = {8'b00010000};
sof_f_12[2] = {8'b00000000};
eof_f_12[0] = {8'b00000000};
eof_f_12[1] = {8'b00001000};
eof_f_12[2] = {8'b10000000};
end
end
// Beat count % 3, to support F=3, 6, 12
always @(posedge clk) begin
if(reset) begin
beat_cnt_mod_3 <= 2'd0;
@ -134,7 +165,10 @@ 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'
assign default_sof = {{DATA_PATH_WIDTH-1{1'b0}}, cur_sof};
assign default_eof = {cur_eof, {DATA_PATH_WIDTH-1{1'b0}}};
// 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)
@ -153,27 +187,42 @@ always @(*) begin
sof = sof_f_3[beat_cnt_mod_3];
eof = eof_f_3[beat_cnt_mod_3];
end
8'd3:
begin
sof = {DATA_PATH_WIDTH/4{4'b0001}};
eof = {DATA_PATH_WIDTH/4{4'b1000}};
end
8'd5:
begin
sof = sof_f_6[beat_cnt_mod_3];
eof = eof_f_6[beat_cnt_mod_3];
end
8'd11:
begin
sof = (DATA_PATH_WIDTH == 4) ? default_sof : sof_f_12[beat_cnt_mod_3];
eof = (DATA_PATH_WIDTH == 4) ? default_eof : eof_f_12[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}}};
sof = default_sof;
eof = default_eof;
end
endcase
end
// Beat count per multiframe
// Only support F*K%4=0
// If DATA_PATH_WIDTH == 4, or if DATA_PATH_WIDTH == 8 and F*K%8=0,
// then multiframes always start/end at the first/last octet in the data bus
// Otherwise, start/end of multiframe have more complicated patterns
always @(posedge clk) begin
if(reset) begin
beat_cnt_mf <= 8'b0;
mf_phase <= 1'b0;
end else begin
if(beat_cnt_mf == cfg_beats_per_multiframe) begin
if(beat_cnt_mf == cur_beats_per_multiframe) begin
beat_cnt_mf <= 8'b0;
mf_phase <= ~mf_phase;
end else begin
beat_cnt_mf <= beat_cnt_mf + 1'b1;
end
@ -181,13 +230,46 @@ always @(posedge clk) begin
end
assign cur_somf = beat_cnt_mf == 0;
assign cur_eomf = beat_cnt_mf == cfg_beats_per_multiframe;
assign cur_eomf = beat_cnt_mf == cur_beats_per_multiframe;
// Only support F*K equals a multipe of DATA_PATH_WIDTH,
if(DATA_PATH_WIDTH == 4) begin : gen_mf_dp_4
always @(*) begin
cur_beats_per_multiframe = cfg_beats_per_multiframe;
somf = {{DATA_PATH_WIDTH-1{1'b0}}, cur_somf};
eomf = {cur_eomf, {DATA_PATH_WIDTH-1{1'b0}}};
end
end else if(DATA_PATH_WIDTH == 8) begin : gen_mf_dp_8
always @(*) begin
// cfg_octets_per_multiframe = 4
if(cfg_octets_per_multiframe[9:2] == 0) begin
cur_beats_per_multiframe = 8'hXX;
somf = 8'h11;
eomf = 8'h88;
end else if(~octets_per_mf_4_mod_8) begin
cur_beats_per_multiframe = cfg_beats_per_multiframe;
somf = {{DATA_PATH_WIDTH-1{1'b0}}, cur_somf};
eomf = {cur_eomf, {DATA_PATH_WIDTH-1{1'b0}}};
end else begin
cur_beats_per_multiframe = cfg_beats_per_multiframe - mf_phase;
if((mf_phase == 0) && (beat_cnt_mf == 0)) begin
somf = 8'h01;
end else if((mf_phase == 0) && (beat_cnt_mf == cur_beats_per_multiframe)) begin
somf = 8'h10;
end else begin
somf = 8'b0;
end
if((mf_phase == 0) && (beat_cnt_mf == cur_beats_per_multiframe)) begin
eomf = 8'h08;
end else if((mf_phase == 1) && (beat_cnt_mf == cur_beats_per_multiframe)) begin
eomf = 8'h80;
end else begin
eomf = 8'b0;
end
end
end
end
endgenerate
endmodule

34
library/jesd204/jesd204_common/jesd204_lmfc.v Normal file → Executable file
View File

@ -44,13 +44,16 @@
`timescale 1ns/100ps
module jesd204_lmfc (
module jesd204_lmfc #(
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input sysref,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_oneshot,
input cfg_sysref_disable,
@ -69,6 +72,12 @@ module jesd204_lmfc (
output reg sysref_alignment_error
);
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam BEATS_PER_MF_WIDTH = 10-DPW_LOG2;
wire [BEATS_PER_MF_WIDTH-1:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe[9:DPW_LOG2];
reg [BEATS_PER_MF_WIDTH:0] cfg_whole_beats_per_multiframe;
reg sysref_r = 1'b0;
reg sysref_d1 = 1'b0;
reg sysref_d2 = 1'b0;
@ -124,8 +133,21 @@ end
* setting, finally deassert reset.
*/
/*
* For DATA_PATH_WIDTH == 8, F*K%8=4, set
* cfg_beats_per_multiframe = cfg_beats_per_multiframe*2
* LMFC will be twice the actual length
*/
always @(*) begin
if (lmfc_counter == cfg_beats_per_multiframe) begin
if((LINK_MODE == 1) && (DATA_PATH_WIDTH == 8) && ~cfg_octets_per_multiframe[2]) begin
cfg_whole_beats_per_multiframe = cfg_beats_per_multiframe*2;
end else begin
cfg_whole_beats_per_multiframe = cfg_beats_per_multiframe;
end
end
always @(*) begin
if (lmfc_counter == cfg_whole_beats_per_multiframe) begin
lmfc_counter_next = 'h00;
end else begin
lmfc_counter_next = lmfc_counter + 1'b1;
@ -193,7 +215,7 @@ end
// End of Extended MultiBlock
always @(posedge clk) begin
if (lmfc_active == 1'b1) begin
eoemb <= lmfc_counter[7:5] == cfg_beats_per_multiframe[7:5];
eoemb <= lmfc_counter[7:5] == cfg_whole_beats_per_multiframe[7:5];
end else begin
eoemb <= 1'b0;
end
@ -203,9 +225,9 @@ always @(posedge clk) begin
if (reset == 1'b1) begin
lmfc_clk_p1 <= 1'b0;
end else if (lmfc_active == 1'b1) begin
if (lmfc_counter == cfg_beats_per_multiframe) begin
if (lmfc_counter == cfg_whole_beats_per_multiframe) begin
lmfc_clk_p1 <= 1'b1;
end else if (lmfc_counter == cfg_beats_per_multiframe[7:1]) begin
end else if (lmfc_counter == cfg_whole_beats_per_multiframe[7:1]) begin
lmfc_clk_p1 <= 1'b0;
end
end

View File

@ -12,8 +12,7 @@ GENERIC_DEPS += jesd204_lane_latency_monitor.v
GENERIC_DEPS += jesd204_rx.v
GENERIC_DEPS += jesd204_rx_cgs.v
GENERIC_DEPS += jesd204_rx_ctrl.v
GENERIC_DEPS += jesd204_rx_frame_align_monitor.v
GENERIC_DEPS += jesd204_rx_frame_mark.v
GENERIC_DEPS += jesd204_rx_frame_align.v
GENERIC_DEPS += jesd204_rx_lane.v
XILINX_DEPS += error_monitor.v

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

@ -48,35 +48,32 @@ module align_mux #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input [1:0] align,
input [2:0] align,
input [DATA_PATH_WIDTH*8-1:0] in_data,
input [DATA_PATH_WIDTH-1:0] in_charisk,
output reg [DATA_PATH_WIDTH*8-1:0] out_data,
output reg [DATA_PATH_WIDTH-1:0] out_charisk
output [DATA_PATH_WIDTH*8-1:0] out_data,
output [DATA_PATH_WIDTH-1:0] out_charisk
);
reg [DATA_PATH_WIDTH*8-1:0] in_data_d1;
reg [DATA_PATH_WIDTH-1:0] in_charisk_d1;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
wire [DPW_LOG2-1:0] align_int;
reg [DATA_PATH_WIDTH*8-1:0] in_data_d1;
reg [DATA_PATH_WIDTH-1:0] in_charisk_d1;
wire [(DATA_PATH_WIDTH*8*2)-1:0] data;
wire [(DATA_PATH_WIDTH*2)-1:0] charisk;
always @(posedge clk) begin
in_data_d1 <= in_data;
in_charisk_d1 <= in_charisk;
end
always @(*) begin
case (align)
'h0: out_data = in_data_d1;
'h1: out_data = {in_data[7:0],in_data_d1[31:8]};
'h2: out_data = {in_data[15:0],in_data_d1[31:16]};
'h3: out_data = {in_data[23:0],in_data_d1[31:24]};
endcase
assign data = {in_data, in_data_d1};
assign charisk = {in_charisk, in_charisk_d1};
case (align)
'h0: out_charisk = in_charisk_d1;
'h1: out_charisk = {in_charisk[0:0],in_charisk_d1[3:1]};
'h2: out_charisk = {in_charisk[1:0],in_charisk_d1[3:2]};
'h3: out_charisk = {in_charisk[2:0],in_charisk_d1[3:3]};
endcase
end
assign align_int = align[DPW_LOG2-1:0];
assign out_data = data[align_int*8 +: (DATA_PATH_WIDTH*8)];
assign out_charisk = charisk[align_int +: DATA_PATH_WIDTH];
endmodule

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

@ -50,6 +50,7 @@ module jesd204_ilas_monitor #(
input clk,
input reset,
input [9:0] cfg_octets_per_multiframe,
input [DATA_PATH_WIDTH*8-1:0] data,
input [DATA_PATH_WIDTH-1:0] charisk28,
@ -60,17 +61,19 @@ module jesd204_ilas_monitor #(
output data_ready_n
);
reg [3:0] multi_frame_counter = 'h00;
reg [7:0] frame_counter = 'h00;
reg [7:0] length = 'h00;
localparam STATE_ILAS = 1'b1;
localparam STATE_DATA = 1'b0;
localparam ILAS_DATA_LENGTH = (DATA_PATH_WIDTH == 4) ? 4 : 2;
wire octets_per_mf_4_mod_8 = (DATA_PATH_WIDTH == 8) && ~cfg_octets_per_multiframe[2];
reg state = STATE_ILAS;
reg next_state;
reg prev_was_last = 1'b0;
reg frame_length_error = 1'b0;
wire ilas_config_start;
reg ilas_config_valid_i;
reg [1:0] ilas_config_addr_i;
reg [DATA_PATH_WIDTH*8-1:0] ilas_config_data_i;
assign data_ready_n = next_state;
@ -92,7 +95,7 @@ always @(posedge clk) begin
end
always @(posedge clk) begin
if (reset == 1'b1 || (charisk28[3] == 1'b1 && data[31:29] == 3'h3)) begin
if (reset == 1'b1 || (charisk28[DATA_PATH_WIDTH-1] == 1'b1 && data[(DATA_PATH_WIDTH*8)-1:(DATA_PATH_WIDTH*8)-3] == 3'h3)) begin
prev_was_last <= 1'b1;
end else begin
prev_was_last <= 1'b0;
@ -101,61 +104,59 @@ end
always @(posedge clk) begin
if (reset == 1'b1) begin
multi_frame_counter <= 'h00;
end else if (charisk28[0] == 1'b1 && data[7:5] == 3'h0 && state == STATE_ILAS) begin
multi_frame_counter <= multi_frame_counter + 1'b1;
end
end
always @(posedge clk) begin
if (reset == 1'b1) begin
length <= 'h00;
end else if (prev_was_last == 1'b1) begin
if (length == 'h00) begin
length <= frame_counter;
ilas_config_valid_i <= 1'b0;
end else if (state == STATE_ILAS) begin
if (ilas_config_start) begin
ilas_config_valid_i <= 1'b1;
end else if (ilas_config_addr_i == (ILAS_DATA_LENGTH-1)) begin
ilas_config_valid_i <= 1'b0;
end
end
end
always @(posedge clk) begin
frame_length_error <= 1'b0;
if (prev_was_last == 1'b1) begin
if (length != 'h00 && length != frame_counter) begin
frame_length_error <= 1'b1;
end
if (ilas_config_valid_i == 1'b0) begin
ilas_config_addr_i <= 1'b0;
end else if (ilas_config_valid_i == 1'b1) begin
ilas_config_addr_i <= ilas_config_addr_i + 1'b1;
end
end
always @(posedge clk) begin
if (prev_was_last == 1'b1) begin
frame_counter <= 'h00;
end else begin
frame_counter <= frame_counter + 1'b1;
end
ilas_config_data_i <= data;
end
generate
if(DATA_PATH_WIDTH == 4) begin : gen_dp_4
assign ilas_config_start = charisk28[1] && (data[15:13] == 3'h4);
always @(*) begin
ilas_config_valid = ilas_config_valid_i;
ilas_config_addr = ilas_config_addr_i;
ilas_config_data = ilas_config_data_i;
end
end else begin : gen_dp_8
assign ilas_config_start = octets_per_mf_4_mod_8 ?
(charisk28[5] && (data[47:45] == 3'h4)) :
(charisk28[1] && (data[15:13] == 3'h4));
always @(posedge clk) begin
if (reset == 1'b1) begin
ilas_config_valid <= 1'b0;
end else if (state == STATE_ILAS) begin
if (charisk28[1] == 1'b1 && data[15:13] == 3'h4) begin
ilas_config_valid <= 1'b1;
end else if (ilas_config_addr == 'h3) begin
ilas_config_valid <= 1'b0;
end
end else begin
ilas_config_valid <= ilas_config_valid_i;
end
end
always @(posedge clk) begin
if (ilas_config_valid == 1'b0) begin
ilas_config_addr <= 1'b0;
end else if (ilas_config_valid == 1'b1) begin
ilas_config_addr <= ilas_config_addr + 1'b1;
end
ilas_config_addr <= ilas_config_addr_i;
ilas_config_data <= octets_per_mf_4_mod_8 ? {data[31:0], ilas_config_data_i[63:32]} : ilas_config_data_i;
end
always @(posedge clk) begin
ilas_config_data <= data;
end
endgenerate
endmodule

View File

@ -45,27 +45,31 @@
`timescale 1ns/100ps
module jesd204_lane_latency_monitor #(
parameter NUM_LANES = 1
parameter NUM_LANES = 1,
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [NUM_LANES-1:0] lane_ready,
input [NUM_LANES*2-1:0] lane_frame_align,
input [NUM_LANES*3-1:0] lane_frame_align,
output [14*NUM_LANES-1:0] lane_latency,
output [NUM_LANES-1:0] lane_latency_ready
);
reg [11:0] beat_counter;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam BEAT_CNT_WIDTH = 14-DPW_LOG2;
reg [11:0] lane_latency_mem[0:NUM_LANES-1];
reg [BEAT_CNT_WIDTH-1:0] beat_counter;
reg [BEAT_CNT_WIDTH-1:0] lane_latency_mem[0:NUM_LANES-1];
reg [NUM_LANES-1:0] lane_captured = 'h00;
always @(posedge clk) begin
if (reset == 1'b1) begin
beat_counter <= 'h0;
end else if (beat_counter != 'hfff) begin
end else if (beat_counter != {BEAT_CNT_WIDTH{1'b1}}) begin
beat_counter <= beat_counter + 1'b1;
end
end
@ -84,7 +88,7 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
end
end
assign lane_latency[i*14+13:i*14] = {lane_latency_mem[i],lane_frame_align[i*2+1:i*2]};
assign lane_latency[i*14+13:i*14] = {lane_latency_mem[i],lane_frame_align[(i*DPW_LOG2)+DPW_LOG2-1:i*DPW_LOG2]};
assign lane_latency_ready[i] = lane_captured[i];
end
endgenerate

View File

@ -84,7 +84,7 @@ module jesd204_rx #(
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_disable,
@ -103,7 +103,7 @@ module jesd204_rx #(
output [NUM_LANES-1:0] ilas_config_valid,
output [NUM_LANES*2-1:0] ilas_config_addr,
output [NUM_LANES*32-1:0] ilas_config_data,
output [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data,
output [1:0] status_ctrl_state,
output [2*NUM_LANES-1:0] status_lane_cgs_state,
@ -118,18 +118,19 @@ module jesd204_rx #(
* necessary.
*/
localparam CHAR_INFO_REGISTERED = 0;
localparam ALIGN_MUX_REGISTERED = 0;
localparam ALIGN_MUX_REGISTERED = 1;
localparam SCRAMBLER_REGISTERED = 0;
/*
* Maximum number of octets per multiframe for ADI JESD204 DACs is 256 (Adjust
* as necessary). Divide by data path width.
*/
localparam MAX_OCTETS_PER_FRAME = 16;
localparam MAX_OCTETS_PER_FRAME = 32;
localparam MAX_OCTETS_PER_MULTIFRAME =
(MAX_OCTETS_PER_FRAME * 32) > 1024 ? 1024 : (MAX_OCTETS_PER_FRAME * 32);
localparam MAX_BEATS_PER_MULTIFRAME = MAX_OCTETS_PER_MULTIFRAME / DATA_PATH_WIDTH;
localparam ELASTIC_BUFFER_SIZE = MAX_BEATS_PER_MULTIFRAME;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam LMFC_COUNTER_WIDTH = MAX_BEATS_PER_MULTIFRAME > 256 ? 9 :
MAX_BEATS_PER_MULTIFRAME > 128 ? 8 :
@ -145,6 +146,8 @@ localparam DW = 8*DATA_PATH_WIDTH*NUM_LANES;
localparam CW = DATA_PATH_WIDTH*NUM_LANES;
localparam HW = 2*NUM_LANES;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe[9:DPW_LOG2];
wire [NUM_LANES-1:0] cgs_reset;
wire [NUM_LANES-1:0] cgs_ready;
wire [NUM_LANES-1:0] ifs_reset;
@ -154,7 +157,6 @@ 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;
@ -171,7 +173,7 @@ wire rx_valid_s = buffer_release_d1;
wire [7:0] lmfc_counter;
wire latency_monitor_reset;
wire [2*NUM_LANES-1:0] frame_align;
wire [3*NUM_LANES-1:0] frame_align;
wire [NUM_LANES-1:0] ifs_ready;
wire event_data_phase;
@ -243,11 +245,14 @@ pipeline_stage #(
})
);
jesd204_lmfc i_lmfc (
jesd204_lmfc #(
.LINK_MODE(LINK_MODE),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_lmfc (
.clk(clk),
.reset(core_reset),
.reset(reset),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.cfg_lmfc_offset(cfg_lmfc_offset),
.cfg_sysref_oneshot(cfg_sysref_oneshot),
.cfg_sysref_disable(cfg_sysref_disable),
@ -264,21 +269,17 @@ jesd204_lmfc i_lmfc (
.sysref_alignment_error(event_sysref_alignment_error)
);
jesd204_eof_generator #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.MAX_OCTETS_PER_FRAME(MAX_OCTETS_PER_FRAME)
) i_eof_gen (
.clk(clk),
.reset(eof_reset),
.lmfc_edge(lmfc_edge),
.cfg_octets_per_frame(cfg_octets_per_frame),
.cfg_generate_eomf(1'b0),
.sof(rx_sof),
.eof(rx_eof),
.eomf()
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) i_frame_mark (
.clk (clk),
.reset (eof_reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (rx_sof),
.eof (rx_eof),
.somf (),
.eomf ()
);
generate
@ -291,10 +292,11 @@ reg unexpected_lane_state_error_d = 1'b0;
jesd204_rx_ctrl #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS)
.NUM_LINKS(NUM_LINKS),
.ENABLE_FRAME_ALIGN_ERR_RESET(ENABLE_FRAME_ALIGN_ERR_RESET)
) i_rx_ctrl (
.clk(clk),
.reset(core_reset),
.reset(reset),
.cfg_lanes_disable(cfg_lanes_disable),
.cfg_links_disable(cfg_links_disable),
@ -303,6 +305,7 @@ jesd204_rx_ctrl #(
.phy_en_char_align(phy_en_char_align),
.lmfc_edge(lmfc_edge),
.frame_align_err_thresh_met(frame_align_err_thresh_met),
.sync(sync),
.latency_monitor_reset(latency_monitor_reset),
@ -317,31 +320,6 @@ jesd204_rx_ctrl #(
.event_data_phase(event_data_phase)
);
// 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
assign err_statistics_reset = ctrl_err_statistics_reset ||
event_data_phase;
@ -361,7 +339,7 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.ENABLE_FRAME_ALIGN_CHECK(ENABLE_FRAME_ALIGN_CHECK)
) i_lane (
.clk(clk),
.reset(core_reset),
.reset(reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_charisk(phy_charisk_r[C_STOP:C_START]),
@ -378,8 +356,9 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.buffer_release_n(buffer_release_n),
.buffer_ready_n(buffer_ready_n[i]),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.cfg_octets_per_frame(cfg_octets_per_frame),
.cfg_disable_char_replacement(cfg_disable_char_replacement),
.cfg_disable_scrambler(cfg_disable_scrambler),
.err_statistics_reset(err_statistics_reset),
@ -392,7 +371,7 @@ 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[3*i+2:3*i]),
.status_frame_align_err_cnt(status_lane_frame_align_err_cnt[8*i+7:8*i])
);
@ -412,6 +391,11 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
end
end
end
end else begin : gen_no_frame_align_err_thresh
always @(*) begin
frame_align_err_thresh_met[i] <= 1'b0;
event_frame_alignment_error_per_lane[i] <= 1'b0;
end
end
end
@ -445,7 +429,8 @@ always @(*) begin
end
jesd204_lane_latency_monitor #(
.NUM_LANES(NUM_LANES)
.NUM_LANES(NUM_LANES),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_lane_latency_monitor (
.clk(clk),
.reset(latency_monitor_reset),
@ -456,21 +441,19 @@ jesd204_lane_latency_monitor #(
.lane_latency(status_lane_latency)
);
assign status_lane_emb_state = 'b0;
end
if (LINK_MODE[1] == 1) begin : mode_64b66b
wire [NUM_LANES-1:0] emb_lock;
always @(*) begin
core_reset = reset;
end
jesd204_rx_ctrl_64b #(
.NUM_LANES(NUM_LANES)
) i_jesd204_rx_ctrl_64b (
.clk(clk),
.reset(core_reset),
.reset(reset),
.cfg_lanes_disable(cfg_lanes_disable),
@ -497,7 +480,7 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE)
) i_lane (
.clk(clk),
.reset(core_reset),
.reset(reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_header(phy_header_r[H_STOP:H_START]),

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

@ -46,7 +46,8 @@
module jesd204_rx_ctrl #(
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1
parameter NUM_LINKS = 1,
parameter ENABLE_FRAME_ALIGN_ERR_RESET = 0
) (
input clk,
input reset,
@ -55,15 +56,16 @@ module jesd204_rx_ctrl #(
input [NUM_LINKS-1:0] cfg_links_disable,
input phy_ready,
output phy_en_char_align,
output [NUM_LANES-1:0] cgs_reset,
input [NUM_LANES-1:0] cgs_ready,
output [NUM_LANES-1:0] ifs_reset,
input lmfc_edge,
input [NUM_LANES-1:0] frame_align_err_thresh_met,
output [NUM_LINKS-1:0] sync,
output reg latency_monitor_reset,
@ -90,6 +92,7 @@ reg [7:0] good_counter = 'h00;
wire [7:0] good_cnt_limit_s;
wire good_cnt_limit_reached_s;
wire goto_next_state_s;
assign cgs_reset = cgs_rst;
assign ifs_reset = ifs_rst;
@ -125,7 +128,9 @@ always @(*) begin
STATE_RESET: state_good = 1'b1;
STATE_WAIT_FOR_PHY: state_good = phy_ready;
STATE_CGS: state_good = &(cgs_ready | cfg_lanes_disable);
STATE_SYNCHRONIZED: state_good = 1'b1;
STATE_SYNCHRONIZED: state_good = ENABLE_FRAME_ALIGN_ERR_RESET ?
&(~frame_align_err_thresh_met | cfg_lanes_disable) :
1'b1;
default: state_good = 1'b0;
endcase
end
@ -133,6 +138,8 @@ end
assign good_cnt_limit_s = (state == STATE_CGS) ? 'hff : 'h7;
assign good_cnt_limit_reached_s = good_counter == good_cnt_limit_s;
assign goto_next_state_s = good_cnt_limit_reached_s || (state == STATE_SYNCHRONIZED);
always @(posedge clk) begin
if (reset) begin
good_counter <= 'h00;
@ -167,7 +174,7 @@ always @(posedge clk) begin
if (reset == 1'b1) begin
state <= STATE_RESET;
end else begin
if (good_cnt_limit_reached_s) begin
if (goto_next_state_s) begin
state <= next_state;
end
end

View File

@ -44,31 +44,33 @@
`timescale 1ns/100ps
module jesd204_rx_frame_align_monitor #(
module jesd204_rx_frame_align #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
input [DATA_PATH_WIDTH-1:0] charisk28,
input [DATA_PATH_WIDTH*8-1:0] data,
output [DATA_PATH_WIDTH*8-1:0] data_replaced,
output reg [7:0] align_err_cnt
);
// Reset alignment error count on good multiframe alignment,
// or on good frame or multiframe alignment
// If disabled, misalignments could me masked if
// due to cfg_beats_per_multiframe mismatch or due to
// due to cfg_octets_per_multiframe mismatch or due to
// a slip of a multiple of cfg_octets_per_frame octets
localparam RESET_COUNT_ON_MF_ONLY = 1'b1;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 :
DATA_PATH_WIDTH == 4 ? 2 : 1;
function automatic [DPW_LOG2*2-1:0] count_ones(input [DATA_PATH_WIDTH*2-1:0] val);
function automatic [DPW_LOG2*2:0] count_ones(input [DATA_PATH_WIDTH*2-1:0] val);
reg [DPW_LOG2*2-1:0] ii;
begin
count_ones = 0;
@ -88,23 +90,21 @@ 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;
reg [DPW_LOG2*2: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)
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) i_frame_mark (
.clk (clk),
.reset (reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (),
.eof (eof),
.somf (),
.eomf (eomf)
);
genvar ii;
@ -124,8 +124,6 @@ for (ii = 0; ii < DATA_PATH_WIDTH; ii = ii + 1) begin: gen_k_char
end
end
// TODO: support cfg_disable_scrambler
always @(posedge clk) begin
if(reset) begin
eomf_err[ii] <= 1'b0;
@ -133,10 +131,10 @@ for (ii = 0; ii < DATA_PATH_WIDTH; ii = ii + 1) begin: gen_k_char
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]);
eomf_err[ii] <= char_is_a[ii] && !eomf[ii];
eomf_good[ii] <= char_is_a[ii] && eomf[ii];
eof_err[ii] <= char_is_f[ii] && !eof[ii];
eof_good[ii] <= char_is_f[ii] && eof[ii];
end
end
end
@ -178,4 +176,22 @@ always @(posedge clk) begin
end
end
jesd204_frame_align_replace #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.IS_RX (1'b1)
) i_align_replace (
.clk (clk),
.reset (reset),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.data (data),
.eof (eof),
.rx_char_is_a (char_is_a),
.rx_char_is_f (char_is_f),
.tx_eomf ({DATA_PATH_WIDTH{1'b0}}),
.data_out (data_replaced),
.charisk_out ()
);
endmodule

View File

@ -62,10 +62,10 @@ 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_frame_align.v \
jesd204_rx_constr.sdc \
../jesd204_common/jesd204_eof_generator.v \
../jesd204_common/jesd204_frame_mark.v \
../jesd204_common/jesd204_lmfc.v \
../jesd204_common/jesd204_scrambler.v \
../jesd204_common/pipeline_stage.v \
@ -125,7 +125,7 @@ add_interface config conduit end
set_interface_property config associatedClock clock
set_interface_property config associatedReset reset
add_interface_port config cfg_beats_per_multiframe beats_per_multiframe Input 8
add_interface_port config cfg_octets_per_multiframe octets_per_multiframe Input 10
add_interface_port config cfg_buffer_delay buffer_delay Input 8
add_interface_port config cfg_buffer_early_release buffer_early_release Input 1
add_interface_port config cfg_disable_char_replacement disable_char_replacement Input 1

View File

@ -58,8 +58,7 @@ 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_frame_align.v" \
"jesd204_rx_constr.ttcl" \
"jesd204_rx.v" \
]
@ -101,7 +100,7 @@ adi_add_bus "rx_cfg" "slave" \
{ \
{ "cfg_lanes_disable" "lanes_disable" } \
{ "cfg_links_disable" "links_disable" } \
{ "cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \
@ -184,7 +183,7 @@ set_property -dict [list \
# Data width selection
set param [ipx::get_user_parameters DATA_PATH_WIDTH -of_objects $cc]
set_property -dict [list \
enablement_value false \
enablement_tcl_expr {$LINK_MODE==1} \
value_tcl_expr {expr $LINK_MODE*4} \
] $param

View File

@ -70,8 +70,9 @@ module jesd204_rx_lane #(
output buffer_ready_n,
input buffer_release_n,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
output ilas_config_valid,
@ -84,11 +85,12 @@ module jesd204_rx_lane #(
output [1:0] status_cgs_state,
output status_ifs_ready,
output [1:0] status_frame_align,
output [2:0] status_frame_align,
output [7:0] status_frame_align_err_cnt
);
localparam MAX_DATA_PATH_WIDTH = 8;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
wire [7:0] char[0:DATA_PATH_WIDTH-1];
wire [DATA_PATH_WIDTH-1:0] char_is_valid;
@ -101,13 +103,15 @@ wire cgs_beat_is_cgs = &char_is_cgs;
wire cgs_beat_has_error = |char_is_error;
reg ifs_ready = 1'b0;
reg [1:0] frame_align = 'h00;
reg [2:0] frame_align = 'h00;
reg [2:0] frame_align_int;
wire [DATA_PATH_WIDTH*8-1:0] phy_data_s;
wire [DATA_PATH_WIDTH-1:0] charisk28_aligned_s;
wire [DATA_PATH_WIDTH*8-1:0] data_aligned_s;
wire [DATA_PATH_WIDTH-1:0] charisk28_aligned;
wire [DATA_PATH_WIDTH*8-1:0] data_aligned;
wire [DATA_PATH_WIDTH*8-1:0] data_replaced;
wire [DATA_PATH_WIDTH*8-1:0] data_scrambled_s;
wire [DATA_PATH_WIDTH*8-1:0] data_scrambled;
@ -117,6 +121,8 @@ reg [DATA_PATH_WIDTH-1:0] phy_char_err;
wire ilas_monitor_reset_s;
wire ilas_monitor_reset;
wire buffer_ready_n_s;
reg [DPW_LOG2:0] jj;
reg align_found;
assign status_ifs_ready = ifs_ready;
assign status_frame_align = frame_align;
@ -190,17 +196,20 @@ always @(posedge clk) begin
end
end
always @(*) begin
align_found = 1'b0;
frame_align_int = 0;
for(jj = 0; jj < DATA_PATH_WIDTH; jj=jj+1) begin
if (!align_found && (char_is_cgs[jj] == 1'b0)) begin
align_found = 1'b1;
frame_align_int = jj;
end
end
end
always @(posedge clk) begin
if (ifs_ready == 1'b0) begin
if (char_is_cgs[0] == 1'b0) begin
frame_align <= 'h0;
end else if (char_is_cgs[1] == 1'b0) begin
frame_align <= 'h1;
end else if (char_is_cgs[2] == 1'b0) begin
frame_align <= 'h2;
end else begin
frame_align <= 'h3;
end
frame_align <= frame_align_int;
end
end
@ -213,7 +222,9 @@ pipeline_stage #(
.out(phy_data_s)
);
align_mux i_align_mux (
align_mux #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_align_mux (
.clk(clk),
.align(frame_align),
.in_data(phy_data_s),
@ -242,22 +253,25 @@ pipeline_stage #(
);
generate
if(ENABLE_FRAME_ALIGN_CHECK) begin : gen_frame_align_monitor
jesd204_rx_frame_align_monitor #(
if(ENABLE_FRAME_ALIGN_CHECK) begin : gen_frame_align
jesd204_rx_frame_align #(
.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)
) i_frame_align (
.clk (clk),
.reset (buffer_ready_n_s),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.charisk28 (charisk28_aligned),
.data (data_aligned),
.data_replaced (data_replaced),
.align_err_cnt (status_frame_align_err_cnt)
);
end else begin : gen_no_frame_align_monitor
assign status_frame_align_err_cnt = 32'd0;
assign data_replaced = data_aligned;
end
endgenerate
@ -268,7 +282,7 @@ jesd204_scrambler #(
.clk(clk),
.reset(buffer_ready_n_s),
.enable(~cfg_disable_scrambler),
.data_in(data_aligned),
.data_in(data_replaced),
.data_out(data_scrambled_s)
);
@ -306,6 +320,7 @@ jesd204_ilas_monitor #(
) i_ilas_monitor (
.clk(clk),
.reset(ilas_monitor_reset),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.data(data_aligned),
.charisk28(charisk28_aligned),

View File

@ -51,13 +51,17 @@ module jesd204_rx_static_config #(
parameter FRAMES_PER_MULTIFRAME = 32,
parameter SCR = 1,
parameter BUFFER_EARLY_RELEASE = 0,
parameter LINK_MODE = 1 // 2 - 64B/66B; 1 - 8B/10B
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter SYSREF_DISABLE = 0,
parameter SYSREF_ONE_SHOT = 0,
/* Only 4, 8 are supported at the moment for 8b/10b and 8 for 64b */
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input clk,
output [NUM_LANES-1:0] cfg_lanes_disable,
output [NUM_LINKS-1:0] cfg_links_disable,
output [7:0] cfg_beats_per_multiframe,
output [9:0] cfg_octets_per_multiframe,
output [7:0] cfg_octets_per_frame,
output [7:0] cfg_lmfc_offset,
output cfg_sysref_oneshot,
@ -70,20 +74,17 @@ module jesd204_rx_static_config #(
output [7:0] cfg_frame_align_err_threshold
);
/* Only 4 is supported at the moment for 8b/10b and 8 for 64b */
localparam DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4;
assign cfg_beats_per_multiframe = (FRAMES_PER_MULTIFRAME * OCTETS_PER_FRAME / DATA_PATH_WIDTH) - 1;
assign cfg_octets_per_multiframe = (FRAMES_PER_MULTIFRAME * OCTETS_PER_FRAME) - 1;
assign cfg_octets_per_frame = OCTETS_PER_FRAME - 1;
assign cfg_lmfc_offset = 3;
assign cfg_sysref_oneshot = 1'b0;
assign cfg_sysref_disable = 1'b0;
assign cfg_lmfc_offset = 1;
assign cfg_sysref_oneshot = SYSREF_ONE_SHOT;
assign cfg_sysref_disable = SYSREF_DISABLE;
assign cfg_buffer_delay = 'h0;
assign cfg_buffer_early_release = BUFFER_EARLY_RELEASE;
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_disable_char_replacement = 1'b0;
assign cfg_frame_align_err_threshold = 8'd4;
endmodule

View File

@ -57,7 +57,7 @@ adi_add_bus "rx_cfg" "master" \
"analog.com:interface:jesd204_rx_cfg:1.0" \
{ \
{ "cfg_lanes_disable" "lanes_disable" } \
{ "cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \

113
library/jesd204/jesd204_tx/jesd204_tx.v Normal file → Executable file
View File

@ -67,11 +67,13 @@ module jesd204_tx #(
input [DATA_PATH_WIDTH*8*NUM_LANES-1:0] tx_data,
output tx_ready,
output reg [DATA_PATH_WIDTH-1:0] tx_eof,
output reg [DATA_PATH_WIDTH-1:0] tx_sof,
input tx_valid,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input [7:0] cfg_beats_per_multiframe,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_oneshot,
@ -85,7 +87,7 @@ module jesd204_tx #(
output ilas_config_rd,
output [1:0] ilas_config_addr,
input [32*NUM_LANES-1:0] ilas_config_data,
input [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data,
input ctrl_manual_sync_request,
@ -97,7 +99,7 @@ module jesd204_tx #(
);
localparam MAX_OCTETS_PER_FRAME = 8;
localparam MAX_OCTETS_PER_FRAME = 32;
localparam MAX_OCTETS_PER_MULTIFRAME =
(MAX_OCTETS_PER_FRAME * 32) > 1024 ? 1024 : (MAX_OCTETS_PER_FRAME * 32);
localparam MAX_BEATS_PER_MULTIFRAME = MAX_OCTETS_PER_MULTIFRAME / DATA_PATH_WIDTH;
@ -115,21 +117,35 @@ localparam DW = DATA_PATH_WIDTH * 8 * NUM_LANES;
localparam CW = DATA_PATH_WIDTH * NUM_LANES;
localparam HW = 2 * NUM_LANES;
wire [DW-1:0] phy_data_r;
wire [CW-1:0] phy_charisk_r;
wire [HW-1:0] phy_header_r;
wire eof_gen_reset;
reg tx_ready_64b;
wire frame_mark_reset;
reg [DATA_PATH_WIDTH-1:0] tx_somf;
reg [DATA_PATH_WIDTH-1:0] tx_eomf;
reg [DATA_PATH_WIDTH-1:0] tx_sof_early1;
reg [DATA_PATH_WIDTH-1:0] tx_eof_early1;
reg [DATA_PATH_WIDTH-1:0] tx_somf_early1;
reg [DATA_PATH_WIDTH-1:0] tx_eomf_early1;
wire [DATA_PATH_WIDTH-1:0] tx_sof_early2;
wire [DATA_PATH_WIDTH-1:0] tx_eof_early2;
wire [DATA_PATH_WIDTH-1:0] tx_somf_early2;
wire [DATA_PATH_WIDTH-1:0] tx_eomf_early2;
wire lmc_edge;
wire lmc_quarter_edge;
wire eoemb;
jesd204_lmfc i_lmfc (
jesd204_lmfc #(
.LINK_MODE(LINK_MODE),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_lmfc (
.clk(clk),
.reset(reset),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.cfg_lmfc_offset(cfg_lmfc_offset),
.cfg_sysref_oneshot(cfg_sysref_oneshot),
.cfg_sysref_disable(cfg_sysref_disable),
@ -147,22 +163,50 @@ jesd204_lmfc i_lmfc (
.eoemb(eoemb)
);
assign frame_mark_reset = (LINK_MODE == 1) ? eof_gen_reset : ~tx_ready_64b;
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) i_frame_mark (
.clk (clk),
.reset (frame_mark_reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (tx_sof_early2),
.eof (tx_eof_early2),
.somf (tx_somf_early2),
.eomf (tx_eomf_early2)
);
always @(posedge clk) begin
tx_sof_early1 <= tx_sof_early2;
tx_eof_early1 <= tx_eof_early2;
tx_somf_early1 <= tx_somf_early2;
tx_eomf_early1 <= tx_eomf_early2;
tx_sof <= tx_sof_early1;
tx_eof <= tx_eof_early1;
tx_somf <= tx_somf_early1;
tx_eomf <= tx_eomf_early1;
end
generate
genvar i;
if (LINK_MODE[0] == 1) begin : mode_8b10b
wire eof_gen_reset;
wire [DATA_PATH_WIDTH-1:0] eof;
wire eomf;
reg [DATA_PATH_WIDTH-1:0] tx_eof_d;
reg [DATA_PATH_WIDTH-1:0] tx_eomf_d;
wire [NUM_LANES-1:0] lane_cgs_enable;
wire [DW-1:0] ilas_data;
wire [DATA_PATH_WIDTH-1:0] ilas_charisk;
wire [DATA_PATH_WIDTH*NUM_LANES-1:0] ilas_charisk;
wire cfg_generate_eomf = 1'b1;
always @(posedge clk) begin
tx_eof_d <= tx_eof;
tx_eomf_d <= tx_eomf;
end
jesd204_tx_ctrl #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS),
@ -173,6 +217,9 @@ jesd204_tx_ctrl #(
.sync(sync),
.lmfc_edge(lmfc_edge),
.somf(tx_somf),
.somf_early2(tx_somf_early2),
.eomf(tx_eomf),
.lane_cgs_enable(lane_cgs_enable),
.eof_reset(eof_gen_reset),
@ -192,32 +239,13 @@ jesd204_tx_ctrl #(
.cfg_continuous_ilas(cfg_continuous_ilas),
.cfg_skip_ilas(cfg_skip_ilas),
.cfg_mframes_per_ilas(cfg_mframes_per_ilas),
.cfg_disable_char_replacement(cfg_disable_char_replacement),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.ctrl_manual_sync_request(ctrl_manual_sync_request),
.status_sync(status_sync),
.status_state(status_state)
);
jesd204_eof_generator #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.MAX_OCTETS_PER_FRAME(MAX_OCTETS_PER_FRAME)
) i_eof_gen (
.clk(clk),
.reset(eof_gen_reset),
.cfg_octets_per_frame(cfg_octets_per_frame),
.cfg_generate_eomf(cfg_generate_eomf),
.lmfc_edge(lmfc_edge),
.sof(),
.eof(eof),
.eomf(eomf)
);
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
@ -230,13 +258,13 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
) i_lane (
.clk(clk),
.eof(eof),
.eomf(eomf),
.eof(tx_eof_d),
.eomf(tx_eomf_d),
.cgs_enable(lane_cgs_enable[i]),
.ilas_data(ilas_data[D_STOP:D_START]),
.ilas_charisk(ilas_charisk),
.ilas_charisk(ilas_charisk[C_STOP:C_START]),
.tx_data(tx_data[D_STOP:D_START]),
.tx_ready(tx_ready),
@ -244,6 +272,8 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_charisk(phy_charisk_r[C_STOP:C_START]),
.cfg_octets_per_frame(cfg_octets_per_frame),
.cfg_disable_char_replacement(cfg_disable_char_replacement),
.cfg_disable_scrambler(cfg_disable_scrambler)
);
end
@ -253,7 +283,6 @@ assign phy_header_r = 'h0;
end
if (LINK_MODE[1] == 1) begin : mode_64b66b
reg tx_ready_loc;
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
@ -265,7 +294,7 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b
.reset(reset),
.tx_data(tx_data[D_STOP:D_START]),
.tx_ready(tx_ready_loc),
.tx_ready(tx_ready_64b),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_header(phy_header_r[H_STOP:H_START]),
@ -282,16 +311,16 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b
always @(posedge clk) begin
if (reset) begin
tx_ready_loc <= 1'b0;
tx_ready_64b <= 1'b0;
end else if (lmfc_edge) begin
tx_ready_loc <= 1'b1;
tx_ready_64b <= 1'b1;
end
end
assign tx_ready = tx_ready_loc;
assign tx_ready = tx_ready_64b;
// Link considered in DATA phase when SYSREF received and LEMC clock started
// running
assign status_state = {2{tx_ready_loc}};
assign status_state = {2{tx_ready_64b}};
assign phy_charisk_r = 'h0;

137
library/jesd204/jesd204_tx/jesd204_tx_ctrl.v Normal file → Executable file
View File

@ -54,6 +54,9 @@ module jesd204_tx_ctrl #(
input [NUM_LINKS-1:0] sync,
input lmfc_edge,
input [DATA_PATH_WIDTH-1:0] somf,
input [DATA_PATH_WIDTH-1:0] somf_early2,
input [DATA_PATH_WIDTH-1:0] eomf,
output reg [NUM_LANES-1:0] lane_cgs_enable,
output reg eof_reset,
@ -61,7 +64,7 @@ module jesd204_tx_ctrl #(
output reg tx_ready,
output reg [DATA_PATH_WIDTH*8*NUM_LANES-1:0] ilas_data,
output reg [DATA_PATH_WIDTH-1:0] ilas_charisk,
output reg [DATA_PATH_WIDTH*NUM_LANES-1:0] ilas_charisk,
output reg [1:0] ilas_config_addr,
output reg ilas_config_rd,
@ -73,28 +76,45 @@ module jesd204_tx_ctrl #(
input cfg_continuous_ilas,
input cfg_skip_ilas,
input [7:0] cfg_mframes_per_ilas,
input cfg_disable_char_replacement,
input [9:0] cfg_octets_per_multiframe,
input ctrl_manual_sync_request,
output [NUM_LINKS-1:0] status_sync,
output reg [1:0] status_state
);
localparam ILAS_DATA_LENGTH = (DATA_PATH_WIDTH == 4) ? 4 : 2;
localparam ILAS_COUNTER_WIDTH = (DATA_PATH_WIDTH == 4) ? 6 : 5;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam BEATS_PER_MF_WIDTH = 10-DPW_LOG2;
// For DATA_PATH_WIDTH = 8, special case if F*K%8=4
// Multiframe boundaries can occur in the middle of a beat
// jesd204_lmfc will assert lmfc_edge once per two LMFC periods
// cfg_mframes_per_ilas must be even
wire [BEATS_PER_MF_WIDTH-1:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe[9:DPW_LOG2];
wire octets_per_mf_4_mod_8 = (DATA_PATH_WIDTH == 8) && ~cfg_octets_per_multiframe[2];
wire [7:0] cfg_lmfc_per_ilas = octets_per_mf_4_mod_8 ? cfg_mframes_per_ilas/2 : cfg_mframes_per_ilas;
reg lmfc_edge_d1 = 1'b0;
reg lmfc_edge_d2 = 1'b0;
reg eof_reset_d;
reg ilas_reset = 1'b1;
reg ilas_data_reset = 1'b1;
reg sync_request = 1'b0;
reg sync_request_received = 1'b0;
reg [7:0] mframe_counter = 'h00;
reg [5:0] ilas_counter = 'h00;
reg [ILAS_COUNTER_WIDTH-1:0] ilas_counter = 'h00;
wire ilas_config_rd_start;
reg ilas_config_rd_d1 = 1'b1;
reg last_ilas_mframe = 1'b0;
reg cgs_enable = 1'b1;
wire [DATA_PATH_WIDTH*8-1:0] ilas_default_data;
wire [NUM_LINKS-1:0] status_sync_masked;
genvar ii;
genvar jj;
sync_bits #(
.NUM_OF_BITS (NUM_LINKS))
i_cdc_sync (
@ -140,13 +160,27 @@ end
always @(posedge clk) begin
if (cfg_skip_ilas == 1'b1 ||
mframe_counter == cfg_mframes_per_ilas) begin
mframe_counter == cfg_lmfc_per_ilas) begin
last_ilas_mframe <= 1'b1;
end else begin
last_ilas_mframe <= 1'b0;
end
end
always @(*) begin
if (sync_request == 1'b1 || reset == 1'b1) begin
eof_reset = 1'b1;
end else if (lmfc_edge == 1'b1 && sync_request_received == 1'b1) begin
eof_reset = 1'b0;
end else begin
eof_reset = eof_reset_d;
end
end
always @(posedge clk) begin
eof_reset_d <= eof_reset;
end
localparam STATE_WAIT = 2'b00;
localparam STATE_CGS = 2'b01;
localparam STATE_ILAS = 2'b10;
@ -155,7 +189,6 @@ localparam STATE_DATA = 2'b11;
/* Timeline
*
* #1 lmfc_edge == 1, ilas_reset update
* #2 eof_reset update
* #3 {lane_,}cgs_enable, tx_ready update
*
* One multi-frame should at least be 3 clock cycles (TBD 64-bit data path)
@ -166,7 +199,6 @@ always @(posedge clk) begin
cgs_enable <= 1'b1;
lane_cgs_enable <= {NUM_LANES{1'b1}};
tx_ready <= 1'b0;
eof_reset <= 1'b1;
ilas_reset <= 1'b1;
ilas_data_reset <= 1'b1;
@ -187,7 +219,6 @@ always @(posedge clk) begin
if (lmfc_edge_d1 == 1'b1) begin
if (last_ilas_mframe == 1'b1 && cfg_continuous_ilas == 1'b0) begin
eof_reset <= cfg_disable_char_replacement;
ilas_data_reset <= 1'b1;
end else if (cgs_enable == 1'b1) begin
ilas_data_reset <= 1'b0;
@ -215,9 +246,9 @@ end
always @(posedge clk) begin
if (ilas_reset == 1'b1) begin
ilas_config_rd <= 1'b0;
end else if (mframe_counter == 'h00 && lmfc_edge == 1'b1) begin
end else if (ilas_config_rd_start == 1'b1) begin
ilas_config_rd <= 1'b1;
end else if (ilas_config_addr == 'h3) begin
end else if (ilas_config_addr == (ILAS_DATA_LENGTH-1)) begin
ilas_config_rd <= 1'b0;
end
ilas_config_rd_d1 <= ilas_config_rd;
@ -239,41 +270,103 @@ always @(posedge clk) begin
end
end
wire [31:0] ilas_default_data = {
ilas_counter,2'h3,
ilas_counter,2'h2,
ilas_counter,2'h1,
ilas_counter,2'h0
};
generate
for(ii = 0; ii < DATA_PATH_WIDTH; ii=ii+1) begin : gen_default_data
wire [(8-ILAS_COUNTER_WIDTH)-1:0] ii_sig = ii;
assign ilas_default_data[(ii*8)+7:ii*8] = {ilas_counter, ii_sig};
end
endgenerate
generate
if(DATA_PATH_WIDTH == 4) begin : gen_dp4
assign ilas_config_rd_start = mframe_counter == 'h00 && somf_early2[0];
always @(posedge clk) begin
if (ilas_data_reset == 1'b1) begin
ilas_data <= {NUM_LANES{32'h00}};
ilas_charisk <= 4'b0000;
ilas_charisk <= {NUM_LANES{4'b0000}};
end else begin
if (ilas_config_rd_d1 == 1'b1) begin
case (ilas_config_addr)
2'h1: begin
ilas_data <= (ilas_config_data & {NUM_LANES{32'hffff0000}}) |
{NUM_LANES{16'h00,8'h9c,8'h1c}}; // /Q/ /R/
ilas_charisk <= 4'b0011;
ilas_charisk <= {NUM_LANES{4'b0011}};
end
default: begin
ilas_data <= ilas_config_data;
ilas_charisk <= 4'b0000;
ilas_charisk <= {NUM_LANES{4'b0000}};
end
endcase
end else if (lmfc_edge_d2 == 1'b1) begin
ilas_data <= {NUM_LANES{ilas_default_data[31:8],8'h1c}}; // /R/
ilas_charisk <= 4'b0001;
ilas_charisk <= {NUM_LANES{4'b0001}};
end else if (lmfc_edge_d1 == 1'b1) begin
ilas_data <= {NUM_LANES{8'h7c,ilas_default_data[23:0]}}; // /A/
ilas_charisk <= 4'b1000;
ilas_charisk <= {NUM_LANES{4'b1000}};
end else begin
ilas_data <= {NUM_LANES{ilas_default_data}};
ilas_charisk <= 4'b0000;
ilas_charisk <= {NUM_LANES{4'b0000}};
end
end
end
end else if(DATA_PATH_WIDTH == 8) begin : gen_dp8
reg [63:0] ilas_config_data_d[NUM_LANES-1:0];
reg ilas_config_rd_d2 = 1'b0;
always @(posedge clk) begin
ilas_config_rd_d2 <= ilas_config_rd_d1;
end
for(jj = 0; jj < NUM_LANES; jj = jj + 1) begin : gen_dp8_lane
assign ilas_config_rd_start = (mframe_counter == 'h00) && (octets_per_mf_4_mod_8 ? somf_early2[4] : somf_early2[0]);
always @(posedge clk) begin
ilas_config_data_d[jj] <= {32'b0, ilas_config_data[(jj*64)+32+:32]};
end
for(ii = 0; ii < DATA_PATH_WIDTH; ii=ii+1) begin : gen_ilas_data
always @(posedge clk) begin
if (ilas_data_reset) begin
ilas_data[(jj*64)+(ii*8)+:8] <= 8'h00;
ilas_charisk[(jj*8)+ii] <= 1'b0;
end else begin
if(somf[ii]) begin
ilas_data[(jj*64)+(ii*8)+:8] <= 8'h1c; // /R/
ilas_charisk[(jj*8)+ii] <= 1'b1;
end else if(eomf[ii]) begin
ilas_data[(jj*64)+(ii*8)+:8] <= 8'h7c; // /A/
ilas_charisk[(jj*8)+ii] <= 1'b1;
end else if (ilas_config_rd_d1 &&
(ilas_config_addr == 2'h1) &&
((octets_per_mf_4_mod_8 && (ii == 5)) ||
(!octets_per_mf_4_mod_8 && (ii == 1)))) begin
ilas_data[(jj*64)+(ii*8)+:8] <= 8'h9c; // /Q/
ilas_charisk[(jj*8)+ii] <= 1'b1;
end else if (octets_per_mf_4_mod_8 && ilas_config_rd_d2 && (ii < 4)) begin
ilas_data[(jj*64)+(ii*8)+:8] <= ilas_config_data_d[jj][ii*8+:8];
ilas_charisk[(jj*8)+ii] <= 1'b0;
end else if (octets_per_mf_4_mod_8 && ilas_config_rd_d1 && (ii >= 4)) begin
ilas_data[(jj*64)+(ii*8)+:8] <= ilas_config_data[(jj*64)+((ii-4)*8)+:8];
ilas_charisk[(jj*8)+ii] <= 1'b0;
end else if (!octets_per_mf_4_mod_8 && ilas_config_rd_d1) begin
ilas_data[(jj*64)+(ii*8)+:8] <= ilas_config_data[(jj*64)+(ii*8)+:8];
ilas_charisk[(jj*8)+ii] <= 1'b0;
end else begin
ilas_data[(jj*64)+(ii*8)+:8] <= ilas_default_data[ii*8+:8];
ilas_charisk[(jj*8)+ii] <= 1'b0;
end
end
end
end
end
end
endgenerate
endmodule

View File

@ -59,6 +59,8 @@ ad_ip_files jesd204_tx [list \
jesd204_tx_lane.v \
jesd204_tx_constr.sdc \
../jesd204_common/jesd204_eof_generator.v \
../jesd204_common/jesd204_frame_align_replace.v \
../jesd204_common/jesd204_frame_mark.v \
../jesd204_common/jesd204_lmfc.v \
../jesd204_common/jesd204_scrambler.v \
../jesd204_common/pipeline_stage.v \
@ -142,7 +144,7 @@ add_interface config conduit end
set_interface_property config associatedClock clock
set_interface_property config associatedReset reset
add_interface_port config cfg_beats_per_multiframe beats_per_multiframe Input 8
add_interface_port config cfg_octets_per_multiframe octets_per_multiframe Input 10
add_interface_port config cfg_continuous_cgs continuous_cgs Input 1
add_interface_port config cfg_continuous_ilas continuous_ilas Input 1
add_interface_port config cfg_disable_char_replacement disable_char_replacement Input 1

View File

@ -91,7 +91,7 @@ adi_add_bus "tx_cfg" "slave" \
{ \
{ "cfg_lanes_disable" "lanes_disable" } \
{ "cfg_links_disable" "links_disable" } \
{ "cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \
@ -170,7 +170,7 @@ set_property -dict [list \
# Data width selection
set param [ipx::get_user_parameters DATA_PATH_WIDTH -of_objects $cc]
set_property -dict [list \
enablement_value false \
enablement_tcl_expr {$LINK_MODE==1} \
value_tcl_expr {expr $LINK_MODE*4} \
] $param

84
library/jesd204/jesd204_tx/jesd204_tx_lane.v Normal file → Executable file
View File

@ -50,7 +50,7 @@ module jesd204_tx_lane #(
input clk,
input [DATA_PATH_WIDTH-1:0] eof,
input eomf,
input [DATA_PATH_WIDTH-1:0] eomf,
input cgs_enable,
@ -63,12 +63,23 @@ module jesd204_tx_lane #(
output reg [DATA_PATH_WIDTH*8-1:0] phy_data,
output reg [DATA_PATH_WIDTH-1:0] phy_charisk,
input [7:0] cfg_octets_per_frame,
input cfg_disable_char_replacement,
input cfg_disable_scrambler
);
wire [DATA_PATH_WIDTH*8-1:0] scrambled_data;
wire [7:0] scrambled_char[0:DATA_PATH_WIDTH-1];
reg [7:0] char_align[0:DATA_PATH_WIDTH-1];
wire [DATA_PATH_WIDTH*8-1:0] scrambled_data_d;
wire cgs_enable_d;
wire tx_ready_d;
wire [DATA_PATH_WIDTH-1:0] eof_d;
wire [DATA_PATH_WIDTH-1:0] eomf_d;
wire [DATA_PATH_WIDTH*8-1:0] ilas_data_d;
wire [DATA_PATH_WIDTH-1:0] ilas_charisk_d;
wire [DATA_PATH_WIDTH*8-1:0] data_replaced;
wire [DATA_PATH_WIDTH-1:0] charisk_replaced;
wire [7:0] scrambled_char[0:DATA_PATH_WIDTH-1];
reg [7:0] char_align[0:DATA_PATH_WIDTH-1];
jesd204_scrambler #(
.WIDTH(DATA_PATH_WIDTH*8),
@ -81,14 +92,57 @@ jesd204_scrambler #(
.data_out(scrambled_data)
);
pipeline_stage #(
.WIDTH((DATA_PATH_WIDTH*19) + 2),
.REGISTERED(1)
) i_lane_pipeline_stage (
.clk(clk),
.in({
cgs_enable,
tx_ready,
eof,
eomf,
scrambled_data,
ilas_data,
ilas_charisk
}),
.out({
cgs_enable_d,
tx_ready_d,
eof_d,
eomf_d,
scrambled_data_d,
ilas_data_d,
ilas_charisk_d
})
);
jesd204_frame_align_replace #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.IS_RX (1'b0)
) i_align_replace (
.clk (clk),
.reset (~tx_ready_d),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.data (scrambled_data_d),
.eof (eof_d),
.rx_char_is_a ({DATA_PATH_WIDTH{1'b0}}),
.rx_char_is_f ({DATA_PATH_WIDTH{1'b0}}),
.tx_eomf (eomf_d),
.data_out (data_replaced),
.charisk_out (charisk_replaced)
);
generate
genvar i;
for (i = 0; i < DATA_PATH_WIDTH; i = i + 1) begin: gen_char
assign scrambled_char[i] = scrambled_data[i*8+7:i*8];
assign scrambled_char[i] = scrambled_data_d[i*8+7:i*8];
always @(*) begin
if (i == DATA_PATH_WIDTH-1 && eomf == 1'b1) begin
if (eomf_d[i]) begin
char_align[i] = 8'h7c; // /A/
end else begin
char_align[i] = 8'hfc; // /F/
@ -96,12 +150,16 @@ for (i = 0; i < DATA_PATH_WIDTH; i = i + 1) begin: gen_char
end
always @(posedge clk) begin
if (cgs_enable == 1'b1) begin
phy_charisk[i] <= 1'b1;
end else if (eof[i] == 1'b1 && scrambled_char[i] == char_align[i]) begin
if (cgs_enable_d) begin
phy_charisk[i] <= 1'b1;
end else if (tx_ready_d) begin
if(!cfg_disable_scrambler) begin
phy_charisk[i] <= eof_d[i] && (scrambled_char[i] == char_align[i]);
end else begin
phy_charisk[i] <= charisk_replaced[i];
end
end else begin
phy_charisk[i] <= ilas_charisk[i];
phy_charisk[i] <= ilas_charisk_d[i];
end
end
end
@ -109,10 +167,14 @@ end
endgenerate
always @(posedge clk) begin
if (cgs_enable == 1'b1) begin
if (cgs_enable_d) begin
phy_data <= {DATA_PATH_WIDTH{8'hbc}};
end else begin
phy_data <= (tx_ready) ? scrambled_data : ilas_data;
if(tx_ready_d) begin
phy_data <= data_replaced;
end else begin
phy_data <= ilas_data_d;
end
end
end

View File

@ -60,16 +60,18 @@ module jesd204_ilas_config_static #(
parameter JESDV = 3'h1,
parameter CF = 5'h00,
parameter HD = 1'b1,
parameter NUM_LANES = 1
parameter NUM_LANES = 1,
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input [1:0] ilas_config_addr,
input ilas_config_rd,
output reg [32*NUM_LANES-1:0] ilas_config_data
output reg [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data
);
wire [31:0] ilas_mem[0:3];
reg [31:0] ilas_lane_mem[0:NUM_LANES-1][0:3];
assign ilas_mem[0][15:0] = 8'h00;
assign ilas_mem[0][23:16] = DID; // DID
@ -106,17 +108,26 @@ assign ilas_mem[3][31:24] = ilas_mem[0][23:16] + ilas_mem[0][31:24] +
generate
genvar i;
genvar j;
for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
for(j = 0; j < 4; j = j + 1) begin : gen_word
always @(*) begin
ilas_lane_mem[i][j] = ilas_mem[j];
case(j)
1: ilas_lane_mem[i][j][4:0] = i;
3: ilas_lane_mem[i][j][31:24] = ilas_mem[3][31:24] + i;
endcase
end
end
always @(posedge clk) begin
if (ilas_config_rd == 1'b1) begin
ilas_config_data[i*32+31:i*32] <= ilas_mem[ilas_config_addr];
/* Overwrite special cases */
case (ilas_config_addr)
'h1: ilas_config_data[i*32+4:i*32] <= i;
'h3: ilas_config_data[i*32+31:i*32+24] <= ilas_mem[ilas_config_addr][31:24] + i;
endcase
if(DATA_PATH_WIDTH == 4) begin
ilas_config_data[i*32+31:i*32] <= ilas_lane_mem[i][ilas_config_addr];
end else begin
ilas_config_data[i*64+63:i*64] <= {ilas_lane_mem[i][{ilas_config_addr[0], 1'b1}], ilas_lane_mem[i][{ilas_config_addr[0], 1'b0}]};
end
end
end
end

View File

@ -54,13 +54,17 @@ module jesd204_tx_static_config #(
parameter NP = 16,
parameter HIGH_DENSITY = 1,
parameter SCR = 1,
parameter LINK_MODE = 1 // 2 - 64B/66B; 1 - 8B/10B
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter SYSREF_DISABLE = 0,
parameter SYSREF_ONE_SHOT = 0,
/* Only 4, 8 are supported at the moment for 8b/10b and 8 for 64b */
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input clk,
output [NUM_LANES-1:0] cfg_lanes_disable,
output [NUM_LINKS-1:0] cfg_links_disable,
output [7:0] cfg_beats_per_multiframe,
output [9:0] cfg_octets_per_multiframe,
output [7:0] cfg_octets_per_frame,
output [7:0] cfg_lmfc_offset,
output cfg_sysref_oneshot,
@ -74,23 +78,20 @@ module jesd204_tx_static_config #(
input ilas_config_rd,
input [1:0] ilas_config_addr,
output [32*NUM_LANES-1:0] ilas_config_data
output [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data
);
/* Only 4 is supported at the moment for 8b/10b and 8 for 64b */
localparam DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4;
assign cfg_beats_per_multiframe = (FRAMES_PER_MULTIFRAME * OCTETS_PER_FRAME / DATA_PATH_WIDTH) - 1;
assign cfg_octets_per_multiframe = (FRAMES_PER_MULTIFRAME * OCTETS_PER_FRAME) - 1;
assign cfg_octets_per_frame = OCTETS_PER_FRAME - 1;
assign cfg_lmfc_offset = 3;
assign cfg_sysref_oneshot = 1'b0;
assign cfg_sysref_disable = 1'b0;
assign cfg_lmfc_offset = 1;
assign cfg_sysref_oneshot = SYSREF_ONE_SHOT;
assign cfg_sysref_disable = SYSREF_DISABLE;
assign cfg_continuous_cgs = 1'b0;
assign cfg_continuous_ilas = 1'b0;
assign cfg_skip_ilas = 1'b0;
assign cfg_mframes_per_ilas = 3;
assign cfg_disable_scrambler = SCR ? 1'b0 : 1'b1;
assign cfg_disable_char_replacement = cfg_disable_scrambler;
assign cfg_disable_char_replacement = 1'b0;
assign cfg_lanes_disable = {NUM_LANES{1'b0}};
assign cfg_links_disable = {NUM_LINKS{1'b0}};
@ -109,7 +110,8 @@ jesd204_ilas_config_static #(
.JESDV(3'h1),
.CF(5'h00),
.HD(HIGH_DENSITY),
.NUM_LANES(NUM_LANES)
.NUM_LANES(NUM_LANES),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_ilas_config (
.clk(clk),
.ilas_config_addr(ilas_config_addr),

View File

@ -58,7 +58,7 @@ adi_add_bus "tx_cfg" "master" \
"analog.com:interface:jesd204_tx_cfg:1.0" \
{ \
{ "cfg_lanes_disable" "lanes_disable" } \
{ "cfg_beats_per_multiframe" "beats_per_multiframe" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \

View File

@ -2,11 +2,11 @@
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_common/pipeline_stage.v ../jesd204_common/jesd204_frame_mark.v ../jesd204_common/jesd204_frame_align_replace.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/jesd204_rx_frame_align.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"

View File

@ -48,17 +48,27 @@ 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 OCTETS_PER_FRAME = 3;
parameter FRAMES_PER_MULTIFRAME = 8;
parameter NUM_CONVERTERS = 1;
parameter N = 16;
parameter NP = 16;
parameter HIGH_DENSITY = 1'b0;
parameter ENABLE_SCRAMBLER = 0;
parameter BUFFER_EARLY_RELEASE = 1;
parameter SYSREF_DISABLE = 1;
parameter SYSREF_ONE_SHOT = 0;
parameter LANE_DELAY = 1;
parameter DATA_PATH_WIDTH = 8;
parameter DATA_RANDOM = ENABLE_SCRAMBLER ? 0 : 1;
parameter ALIGN_ERROR_PERCENT = 50;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
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;
wire [31:0] RX_LATENCY = 3 + i_rx.CHAR_INFO_REGISTERED + i_rx.ALIGN_MUX_REGISTERED + i_rx.SCRAMBLER_REGISTERED;
wire [31:0] BASE_LATENCY = TX_LATENCY + RX_LATENCY;
localparam SYSREF_HALF_COUNT = OCTETS_PER_FRAME * FRAMES_PER_MULTIFRAME;
`define TIMEOUT 1000000
@ -66,10 +76,13 @@ module frame_align_tb;
reg [5:0] tx_counter = 'h00;
reg [5:0] rx_counter = 'h00;
reg [NUM_LANES*32-1:0] rx_mask = 'hffff0000;
reg [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_mask = 64'hffffffffffff0000;
wire tx_ready;
wire rx_valid;
wire [NUM_LANES*32-1:0] rx_data;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_data;
wire [DATA_PATH_WIDTH-1:0] rx_eof;
wire [DATA_PATH_WIDTH-1:0] rx_sof;
wire cur_data_mismatch;
reg data_mismatch = 1'b1;
wire [NUM_LINKS-1:0] sync;
@ -85,45 +98,63 @@ module frame_align_tb;
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
rx_mask <= {NUM_LANES{64'hffffffffffff0000}}; // First two octets are invalid due to scrambling
end else begin
rx_mask <= {NUM_LANES{32'hffffffff}};
rx_mask <= {NUM_LANES{64'hffffffffffffffff}};
end
end else if (rx_valid == 1'b1) begin
rx_counter <= rx_counter + 1'b1;
rx_mask <= {NUM_LANES{32'hffffffff}};
rx_mask <= {NUM_LANES{64'hffffffffffffffff}};
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};
reg [(DATA_PATH_WIDTH*8)-1:0] tx_random_data;
wire [(DATA_PATH_WIDTH*8)-1:0] tx_data;
wire [(DATA_PATH_WIDTH*8)-1:0] rx_ref_data;
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;
genvar ii;
generate
for(ii = 0; ii < DATA_PATH_WIDTH; ii=ii+1) begin : data_gen
wire [1:0] ii_sig = ii;
always @(posedge clk) begin
tx_random_data[ii*8+:8] <= $urandom();
end
assign tx_data[ii*8+:8] = DATA_RANDOM ? tx_random_data[ii*8+:8] : {tx_counter, ii_sig};
assign rx_ref_data[ii*8+:8] = {rx_counter, ii_sig};
end
endgenerate
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] phy_data_out;
wire [NUM_LANES*DATA_PATH_WIDTH-1:0] phy_charisk_out;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] phy_data_delayed;
wire [NUM_LANES*DATA_PATH_WIDTH-1:0] phy_charisk_delayed;
reg [NUM_LANES*DATA_PATH_WIDTH*8-1:0] phy_data_in;
reg [NUM_LANES*DATA_PATH_WIDTH-1:0] phy_charisk_in;
reg align_err_mf;
reg align_err_f;
reg cur_err;
reg [5:0] sysref_counter = 'h00;
reg [9:0] sysref_counter = 'h00;
reg sysref_rx = 1'b0;
reg sysref_tx = 1'b0;
always @(posedge clk) begin
if (sysref_counter == 'h2f)
if (sysref_counter == (SYSREF_HALF_COUNT-1)) begin
sysref_rx <= ~sysref_rx;
sysref_counter <= 'b0;
end else begin
sysref_counter <= sysref_counter + 1'b1;
end
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];
reg [DATA_PATH_WIDTH*9*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};
@ -156,6 +187,7 @@ module frame_align_tb;
align_err_f = 1'b0;
align_err_mf = 1'b0;
#100000;
$finish;
end
always @(posedge clk) begin
@ -169,10 +201,10 @@ module frame_align_tb;
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];
assign phy_data_delayed[DATA_PATH_WIDTH*8*i+(DATA_PATH_WIDTH*8)-1:DATA_PATH_WIDTH*8*i] =
phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][DATA_PATH_WIDTH*8*i+(DATA_PATH_WIDTH*8)-1:DATA_PATH_WIDTH*8*i];
assign phy_charisk_delayed[DATA_PATH_WIDTH*i+DATA_PATH_WIDTH-1:DATA_PATH_WIDTH*i]=
phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][DATA_PATH_WIDTH*i+DATA_PATH_WIDTH-1+NUM_LANES*DATA_PATH_WIDTH*8:DATA_PATH_WIDTH*i+DATA_PATH_WIDTH*8*NUM_LANES];
end endgenerate
always @(*) begin
@ -193,7 +225,7 @@ module frame_align_tb;
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 [9:0] tx_cfg_octets_per_multiframe;
wire [7:0] tx_cfg_octets_per_frame;
wire [7:0] tx_cfg_lmfc_offset;
wire tx_cfg_sysref_disable;
@ -204,23 +236,39 @@ module frame_align_tb;
wire [7:0] tx_cfg_mframes_per_ilas;
wire tx_cfg_disable_char_replacement;
wire tx_cfg_disable_scrambler;
wire tx_lmfc_edge;
wire tx_lmfc_clk;
wire [DATA_PATH_WIDTH-1:0] tx_eof;
wire [DATA_PATH_WIDTH-1:0] tx_sof;
wire tx_ilas_config_rd;
wire [1:0] tx_ilas_config_addr;
wire [32*NUM_LANES-1:0] tx_ilas_config_data;
wire [DATA_PATH_WIDTH*8*NUM_LANES-1:0] tx_ilas_config_data;
wire tx_event_sysref_edge;
wire tx_event_sysref_alignment_error;
wire [NUM_LINKS-1:0] tx_status_sync;
wire [1:0] tx_status_state;
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)
.NUM_CONVERTERS(NUM_CONVERTERS),
.N(N),
.NP(NP),
.HIGH_DENSITY(HIGH_DENSITY),
.SCR(ENABLE_SCRAMBLER),
.LINK_MODE(1),
.SYSREF_DISABLE(SYSREF_DISABLE),
.SYSREF_ONE_SHOT(SYSREF_ONE_SHOT),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) 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_multiframe(tx_cfg_octets_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),
@ -239,14 +287,33 @@ module frame_align_tb;
jesd204_tx #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS)
.NUM_LINKS(NUM_LINKS),
.NUM_OUTPUT_PIPELINE(0),
.LINK_MODE(1),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_tx (
.clk(clk),
.reset(reset),
.phy_data(phy_data_out),
.phy_charisk(phy_charisk_out),
.phy_header(),
.sysref(sysref_tx),
.lmfc_edge(tx_lmfc_edge),
.lmfc_clk(tx_lmfc_clk),
.sync(sync),
.tx_data({NUM_LANES{tx_data}}),
.tx_ready(tx_ready),
.tx_eof(tx_eof),
.tx_sof(tx_sof),
.tx_valid(1'b1),
.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_multiframe(tx_cfg_octets_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),
@ -264,23 +331,21 @@ module frame_align_tb;
.ctrl_manual_sync_request(1'b0),
.tx_ready(tx_ready),
.tx_data({NUM_LANES{tx_data}}),
.sync(sync),
.sysref(sysref_tx),
.event_sysref_edge (tx_event_sysref_edge),
.event_sysref_alignment_error (tx_event_sysref_alignment_error),
.phy_data(phy_data_out),
.phy_charisk(phy_charisk_out)
.status_sync (tx_status_sync),
.status_state (tx_status_state)
);
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 [9:0] rx_cfg_octets_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_sysref_disable;
wire rx_cfg_sysref_oneshot;
wire rx_cfg_disable_scrambler;
wire rx_cfg_disable_char_replacement;
wire rx_cfg_buffer_early_release;
@ -289,19 +354,35 @@ module frame_align_tb;
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;
wire [32*NUM_LANES-1:0] rx_status_err_statistics_cnt;
wire rx_lmfc_edge;
wire rx_lmfc_clk;
wire rx_event_sysref_alignment_error;
wire rx_event_sysref_edge;
wire [NUM_LANES-1:0] rx_ilas_config_valid;
wire [NUM_LANES*2-1:0] rx_ilas_config_addr;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_ilas_config_data;
wire [1:0] rx_status_ctrl_state;
wire [2*NUM_LANES-1:0] rx_status_lane_cgs_state;
wire rx_phy_en_char_align;
jesd204_rx_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),
.BUFFER_EARLY_RELEASE(BUFFER_EARLY_RELEASE)
.BUFFER_EARLY_RELEASE(BUFFER_EARLY_RELEASE),
.LINK_MODE(1),
.SYSREF_DISABLE(SYSREF_DISABLE),
.SYSREF_ONE_SHOT(SYSREF_ONE_SHOT),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) 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_multiframe(rx_cfg_octets_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),
@ -315,46 +396,78 @@ module frame_align_tb;
jesd204_rx #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS),
.NUM_INPUT_PIPELINE(1),
.LINK_MODE(1),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.ENABLE_FRAME_ALIGN_CHECK(1),
.ENABLE_FRAME_ALIGN_ERR_RESET(1)
) i_rx (
.clk(clk),
.reset(reset),
.phy_data(phy_data_in),
.phy_header({2*NUM_LANES{1'b0}}),
.phy_charisk(phy_charisk_in),
.phy_notintable({NUM_LANES*DATA_PATH_WIDTH{1'b0}}),
.phy_disperr({NUM_LANES*DATA_PATH_WIDTH{1'b0}}),
.phy_block_sync({NUM_LANES{1'b0}}),
.sysref(sysref_rx),
.lmfc_edge(rx_lmfc_edge),
.lmfc_clk(rx_lmfc_clk),
.event_sysref_alignment_error(rx_event_sysref_alignment_error),
.event_sysref_edge(rx_event_sysref_edge),
.sync(sync),
.phy_en_char_align(rx_phy_en_char_align),
.rx_data(rx_data),
.rx_valid(rx_valid),
.rx_eof(rx_eof),
.rx_sof(rx_sof),
.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_multiframe(rx_cfg_octets_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_buffer_delay(rx_cfg_buffer_delay),
.cfg_disable_char_replacement(rx_cfg_disable_char_replacement),
.cfg_disable_scrambler(rx_cfg_disable_scrambler),
.ctrl_err_statistics_reset(1'b0),
.ctrl_err_statistics_mask(7'b0),
.cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold),
.sync(sync),
.sysref(sysref_rx),
.status_err_statistics_cnt(rx_status_err_statistics_cnt),
.rx_data(rx_data),
.rx_valid(rx_valid),
.ilas_config_valid(rx_ilas_config_valid),
.ilas_config_addr(rx_ilas_config_addr),
.ilas_config_data(rx_ilas_config_data),
.phy_data(phy_data_in),
.phy_charisk(phy_charisk_in),
.phy_notintable({NUM_LANES{4'b0000}}),
.phy_disperr({NUM_LANES{4'b0000}}),
.status_ctrl_state(rx_status_ctrl_state),
.status_lane_cgs_state(rx_status_lane_cgs_state),
.status_lane_ifs_ready(rx_status_lane_ifs_ready),
.status_lane_latency(rx_status_lane_latency),
.status_lane_emb_state(),
.status_lane_frame_align_err_cnt(rx_status_lane_frame_align_err_cnt)
);
assign cur_data_mismatch = (rx_data & rx_mask) !== ({NUM_LANES{rx_ref_data}} & rx_mask);
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
if (cur_data_mismatch) begin
data_mismatch <= 1'b1;
end
end
@ -363,11 +476,11 @@ module frame_align_tb;
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;
wire [31:0] 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
rx_status_lane_latency[i*14+13:i*14+DPW_LOG2] == LANE_OFFSET) begin
lane_latency_match[i] <= 1'b1;
end else begin
lane_latency_match[i] <= 1'b0;

View File

@ -0,0 +1,7 @@
#!/bin/bash
SOURCE="jesd204_frame_align_replace_tb.v"
SOURCE+=" ../jesd204_common/jesd204_frame_align_replace.v"
cd `dirname $0`
source run_tb.sh

View File

@ -0,0 +1,105 @@
//
// 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_frame_align_replace_tb;
parameter VCD_FILE = "jesd204_frame_align_replace_tb.vcd";
`define TIMEOUT 1000000
`include "tb_base.v"
localparam DATA_PATH_WIDTH = 8;
localparam IS_RX = 1'b1;
wire [7:0] cfg_octets_per_frame = 5;
wire cfg_disable_char_replacement = 1'b0;
wire cfg_disable_scrambler = 1'b1;
reg [DATA_PATH_WIDTH*8-1:0] data;
reg [DATA_PATH_WIDTH-1:0] eof;
reg [DATA_PATH_WIDTH-1:0] eomf;
reg [DATA_PATH_WIDTH-1:0] char_is_a;
reg [DATA_PATH_WIDTH-1:0] char_is_f;
wire [DATA_PATH_WIDTH*8-1:0] data_out;
wire [DATA_PATH_WIDTH-1:0] charisk_out;
reg [31:00] ii;
initial begin
#10000;
$finish;
end
initial begin
forever begin
for(ii = 0; ii < DATA_PATH_WIDTH; ii = ii + 1) begin
eof[ii] = $urandom_range(cfg_octets_per_frame) == 0;
eomf[ii] = $urandom_range(cfg_octets_per_frame*4) == 0;
char_is_a[ii] = $urandom_range(cfg_octets_per_frame*2) == 0;
char_is_f[ii] = $urandom_range(cfg_octets_per_frame*2) == 0;
end
data = {$urandom, $urandom};
@(negedge clk);
end
end
jesd204_frame_align_replace #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.IS_RX (IS_RX)
) frame_align_replace (
.clk (clk),
.reset (reset),
.cfg_octets_per_frame (cfg_octets_per_frame),
.cfg_disable_char_replacement (cfg_disable_char_replacement),
.cfg_disable_scrambler (cfg_disable_scrambler),
.data (data),
.eof (eof),
.rx_char_is_a (char_is_a),
.rx_char_is_f (char_is_f),
.tx_eomf (eomf),
.data_out (data_out),
.charisk_out (charisk_out)
);
endmodule

View File

@ -0,0 +1,7 @@
#!/bin/bash
SOURCE="jesd204_frame_mark_tb.v"
SOURCE+=" ../jesd204_common/jesd204_frame_mark.v"
cd `dirname $0`
source run_tb.sh

View File

@ -0,0 +1,77 @@
//
// 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_frame_mark_tb;
parameter VCD_FILE = "jesd204_frame_mark_tb.vcd";
`define TIMEOUT 1000000
`include "tb_base.v"
localparam DATA_PATH_WIDTH = 8;
wire [9:0] cfg_octets_per_multiframe = 23;
wire [7:0] cfg_octets_per_frame = 5;
wire [DATA_PATH_WIDTH-1:0] sof;
wire [DATA_PATH_WIDTH-1:0] somf;
wire [DATA_PATH_WIDTH-1:0] eof;
wire [DATA_PATH_WIDTH-1:0] eomf;
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) frame_mark (
.clk (clk),
.reset (reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (sof),
.eof (eof),
.somf (somf),
.eomf (eomf)
);
endmodule

View File

@ -2,11 +2,11 @@
SOURCE="loopback_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_common/pipeline_stage.v ../jesd204_common/jesd204_frame_mark.v ../jesd204_common/jesd204_frame_align_replace.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/jesd204_rx_frame_align.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"

View File

@ -48,25 +48,38 @@ module loopback_tb;
parameter VCD_FILE = "loopback_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 OCTETS_PER_FRAME = 1;
parameter FRAMES_PER_MULTIFRAME = 28;
parameter NUM_CONVERTERS = 1;
parameter N = 16;
parameter NP = 16;
parameter HIGH_DENSITY = 1'b0;
parameter ENABLE_SCRAMBLER = 0;
parameter BUFFER_EARLY_RELEASE = 1;
parameter SYSREF_DISABLE = 0;
parameter SYSREF_ONE_SHOT = 0;
parameter LANE_DELAY = 1;
parameter DATA_PATH_WIDTH = 4;
parameter DATA_RANDOM = ENABLE_SCRAMBLER ? 0 : 1;
localparam DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
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;
wire [31:0] RX_LATENCY = 3 + i_rx.CHAR_INFO_REGISTERED + i_rx.ALIGN_MUX_REGISTERED + i_rx.SCRAMBLER_REGISTERED;
wire [31:0] BASE_LATENCY = TX_LATENCY + RX_LATENCY;
localparam SYSREF_HALF_COUNT = OCTETS_PER_FRAME * FRAMES_PER_MULTIFRAME;
`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;
reg [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_mask = 64'hffffffffffff0000;
wire tx_ready;
wire rx_valid;
wire [NUM_LANES*32-1:0] rx_data;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_data;
wire [DATA_PATH_WIDTH-1:0] rx_eof;
wire [DATA_PATH_WIDTH-1:0] rx_sof;
reg data_mismatch = 1'b1;
wire [NUM_LINKS-1:0] sync;
@ -82,39 +95,58 @@ module loopback_tb;
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
rx_mask <= {NUM_LANES{64'hffffffffffff0000}}; // First two octets are invalid due to scrambling
end else begin
rx_mask <= {NUM_LANES{32'hffffffff}};
rx_mask <= {NUM_LANES{64'hffffffffffffffff}};
end
end else if (rx_valid == 1'b1) begin
rx_counter <= rx_counter + 1'b1;
rx_mask <= {NUM_LANES{32'hffffffff}};
rx_mask <= {NUM_LANES{64'hffffffffffffffff}};
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_in;
wire [NUM_LANES*4-1:0] phy_charisk_in;
reg [(DATA_PATH_WIDTH*8)-1:0] tx_random_data;
wire [(DATA_PATH_WIDTH*8)-1:0] tx_data;
wire [(DATA_PATH_WIDTH*8)-1:0] rx_ref_data;
reg [5:0] sysref_counter = 'h00;
genvar ii;
generate
for(ii = 0; ii < DATA_PATH_WIDTH; ii=ii+1) begin : data_gen
wire [1:0] ii_sig = ii;
always @(posedge clk) begin
tx_random_data[ii*8+:8] <= $urandom();
end
assign tx_data[ii*8+:8] = DATA_RANDOM ? tx_random_data[ii*8+:8] : {tx_counter, ii_sig};
assign rx_ref_data[ii*8+:8] = {rx_counter, ii_sig};
end
endgenerate
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] phy_data_out;
wire [NUM_LANES*DATA_PATH_WIDTH-1:0] phy_charisk_out;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] phy_data_in;
wire [NUM_LANES*DATA_PATH_WIDTH-1:0] phy_charisk_in;
reg [9:0] sysref_counter = 'h00;
reg sysref_rx = 1'b0;
reg sysref_tx = 1'b0;
always @(posedge clk) begin
if (sysref_counter == 'h2f)
if (sysref_counter == (SYSREF_HALF_COUNT-1)) begin
sysref_rx <= ~sysref_rx;
sysref_counter <= sysref_counter + 1'b1;
sysref_counter <= 'b0;
end else begin
sysref_counter <= sysref_counter + 1'b1;
end
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];
reg [DATA_PATH_WIDTH*9*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};
@ -129,15 +161,15 @@ module loopback_tb;
genvar i;
generate for (i = 0; i < NUM_LANES; i = i + 1) begin
localparam OFF = MAX_LANE_DELAY - (i + LANE_DELAY);
assign phy_data_in[32*i+31:32*i] =
phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][32*i+31:32*i];
assign phy_charisk_in[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];
assign phy_data_in[DATA_PATH_WIDTH*8*i+(DATA_PATH_WIDTH*8)-1:DATA_PATH_WIDTH*8*i] =
phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][DATA_PATH_WIDTH*8*i+(DATA_PATH_WIDTH*8)-1:DATA_PATH_WIDTH*8*i];
assign phy_charisk_in[DATA_PATH_WIDTH*i+DATA_PATH_WIDTH-1:DATA_PATH_WIDTH*i] =
phy_delay_fifo[(phy_delay_fifo_wr + OFF) % MAX_LANE_DELAY][DATA_PATH_WIDTH*i+DATA_PATH_WIDTH-1+NUM_LANES*DATA_PATH_WIDTH*8:DATA_PATH_WIDTH*i+DATA_PATH_WIDTH*8*NUM_LANES];
end endgenerate
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 [9:0] tx_cfg_octets_per_multiframe;
wire [7:0] tx_cfg_octets_per_frame;
wire [7:0] tx_cfg_lmfc_offset;
wire tx_cfg_sysref_disable;
@ -148,23 +180,39 @@ module loopback_tb;
wire [7:0] tx_cfg_mframes_per_ilas;
wire tx_cfg_disable_char_replacement;
wire tx_cfg_disable_scrambler;
wire tx_lmfc_edge;
wire tx_lmfc_clk;
wire [DATA_PATH_WIDTH-1:0] tx_eof;
wire [DATA_PATH_WIDTH-1:0] tx_sof;
wire tx_ilas_config_rd;
wire [1:0] tx_ilas_config_addr;
wire [32*NUM_LANES-1:0] tx_ilas_config_data;
wire [DATA_PATH_WIDTH*8*NUM_LANES-1:0] tx_ilas_config_data;
wire tx_event_sysref_edge;
wire tx_event_sysref_alignment_error;
wire [NUM_LINKS-1:0] tx_status_sync;
wire [1:0] tx_status_state;
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)
.NUM_CONVERTERS(NUM_CONVERTERS),
.N(N),
.NP(NP),
.HIGH_DENSITY(HIGH_DENSITY),
.SCR(ENABLE_SCRAMBLER),
.LINK_MODE(1),
.SYSREF_DISABLE(SYSREF_DISABLE),
.SYSREF_ONE_SHOT(SYSREF_ONE_SHOT),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) 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_multiframe(tx_cfg_octets_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),
@ -183,14 +231,33 @@ module loopback_tb;
jesd204_tx #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS)
.NUM_LINKS(NUM_LINKS),
.NUM_OUTPUT_PIPELINE(0),
.LINK_MODE(1),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_tx (
.clk(clk),
.reset(reset),
.phy_data(phy_data_out),
.phy_charisk(phy_charisk_out),
.phy_header(),
.sysref(sysref_tx),
.lmfc_edge(tx_lmfc_edge),
.lmfc_clk(tx_lmfc_clk),
.sync(sync),
.tx_data({NUM_LANES{tx_data}}),
.tx_ready(tx_ready),
.tx_eof(tx_eof),
.tx_sof(tx_sof),
.tx_valid(1'b1),
.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_multiframe(tx_cfg_octets_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),
@ -208,63 +275,57 @@ module loopback_tb;
.ctrl_manual_sync_request(1'b0),
.tx_ready(tx_ready),
.tx_data({NUM_LANES{tx_data}}),
.event_sysref_edge (tx_event_sysref_edge),
.event_sysref_alignment_error (tx_event_sysref_alignment_error),
.sync(sync),
.sysref(sysref_tx),
.phy_data(phy_data_out),
.phy_charisk(phy_charisk_out)
.status_sync (tx_status_sync),
.status_state (tx_status_state)
);
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 [9:0] rx_cfg_octets_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_sysref_disable;
wire rx_cfg_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*32-1:0] rx_status_lane_frame_align_err_cnt;
wire [31:0] rx_cfg_frame_align_err_threshold = 32'd4; // TODO: static config
wire [NUM_LANES*8-1:0] rx_status_lane_frame_align_err_cnt;
wire [7:0] rx_cfg_frame_align_err_threshold;
wire [32*NUM_LANES-1:0] rx_status_err_statistics_cnt;
wire rx_lmfc_edge;
wire rx_lmfc_clk;
wire rx_event_sysref_alignment_error;
wire rx_event_sysref_edge;
wire [NUM_LANES-1:0] rx_ilas_config_valid;
wire [NUM_LANES*2-1:0] rx_ilas_config_addr;
wire [NUM_LANES*DATA_PATH_WIDTH*8-1:0] rx_ilas_config_data;
wire [1:0] rx_status_ctrl_state;
wire [2*NUM_LANES-1:0] rx_status_lane_cgs_state;
wire rx_phy_en_char_align;
jesd204_rx_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),
.BUFFER_EARLY_RELEASE(BUFFER_EARLY_RELEASE)
.BUFFER_EARLY_RELEASE(BUFFER_EARLY_RELEASE),
.LINK_MODE(1),
.SYSREF_DISABLE(SYSREF_DISABLE),
.SYSREF_ONE_SHOT(SYSREF_ONE_SHOT),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) 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)
);
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_multiframe(rx_cfg_octets_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),
@ -273,21 +334,72 @@ 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),
.cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold)
);
jesd204_rx #(
.NUM_LANES(NUM_LANES),
.NUM_LINKS(NUM_LINKS),
.NUM_INPUT_PIPELINE(1),
.LINK_MODE(1),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.ENABLE_FRAME_ALIGN_CHECK(1),
.ENABLE_FRAME_ALIGN_ERR_RESET(1)
) i_rx (
.clk(clk),
.reset(reset),
.phy_data(phy_data_in),
.phy_header({2*NUM_LANES{1'b0}}),
.phy_charisk(phy_charisk_in),
.phy_notintable({NUM_LANES*DATA_PATH_WIDTH{1'b0}}),
.phy_disperr({NUM_LANES*DATA_PATH_WIDTH{1'b0}}),
.phy_block_sync({NUM_LANES{1'b0}}),
.sysref(sysref_rx),
.lmfc_edge(rx_lmfc_edge),
.lmfc_clk(rx_lmfc_clk),
.event_sysref_alignment_error(rx_event_sysref_alignment_error),
.event_sysref_edge(rx_event_sysref_edge),
.sync(sync),
.sysref(sysref_rx),
.phy_en_char_align(rx_phy_en_char_align),
.rx_data(rx_data),
.rx_valid(rx_valid),
.rx_eof(rx_eof),
.rx_sof(rx_sof),
.phy_data(phy_data_in),
.phy_charisk(phy_charisk_in),
.phy_notintable({NUM_LANES{4'b0000}}),
.phy_disperr({NUM_LANES{4'b0000}}),
.cfg_lanes_disable(rx_cfg_lanes_disable),
.cfg_links_disable(rx_cfg_links_disable),
.cfg_octets_per_multiframe(rx_cfg_octets_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_buffer_early_release(rx_cfg_buffer_early_release),
.cfg_buffer_delay(rx_cfg_buffer_delay),
.cfg_disable_char_replacement(rx_cfg_disable_char_replacement),
.cfg_disable_scrambler(rx_cfg_disable_scrambler),
.ctrl_err_statistics_reset(1'b0),
.ctrl_err_statistics_mask(7'b0),
.cfg_frame_align_err_threshold(rx_cfg_frame_align_err_threshold),
.status_err_statistics_cnt(rx_status_err_statistics_cnt),
.ilas_config_valid(rx_ilas_config_valid),
.ilas_config_addr(rx_ilas_config_addr),
.ilas_config_data(rx_ilas_config_data),
.status_ctrl_state(rx_status_ctrl_state),
.status_lane_cgs_state(rx_status_lane_cgs_state),
.status_lane_ifs_ready(rx_status_lane_ifs_ready),
.status_lane_latency(rx_status_lane_latency),
.status_lane_emb_state(),
.status_lane_frame_align_err_cnt(rx_status_lane_frame_align_err_cnt)
);
@ -304,11 +416,11 @@ module loopback_tb;
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;
wire [31:0] 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
rx_status_lane_latency[i*14+13:i*14+DPW_LOG2] == LANE_OFFSET) begin
lane_latency_match[i] <= 1'b1;
end else begin
lane_latency_match[i] <= 1'b0;

View File

@ -11,7 +11,7 @@ case "$SIMULATOR" in
# Xcelium flow
xmvlog -NOWARN NONPRT ${SOURCE} || exit 1
xmelab -access +rc ${NAME}
xmsim ${NAME} -run -gui || exit 1
xmsim ${NAME} -gui || exit 1
;;
xsim)
# xsim flow