From 400c3927f70aaf06fb62daafcc5605875e660a06 Mon Sep 17 00:00:00 2001 From: Matt Blanton Date: Thu, 30 Jan 2020 17:05:13 -0500 Subject: [PATCH] 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. --- .../axi_jesd204_common/jesd204_up_common.v | 18 +- .../axi_jesd204_common/jesd204_up_sysref.v | 4 +- .../jesd204/axi_jesd204_rx/axi_jesd204_rx.v | 20 +- .../axi_jesd204_rx/axi_jesd204_rx_constr.xdc | 4 +- .../axi_jesd204_rx/axi_jesd204_rx_hw.tcl | 2 +- .../axi_jesd204_rx/axi_jesd204_rx_ip.tcl | 2 +- .../axi_jesd204_rx/jesd204_up_ilas_mem.v | 22 +- .../jesd204/axi_jesd204_rx/jesd204_up_rx.v | 13 +- .../axi_jesd204_rx/jesd204_up_rx_lane.v | 10 +- .../jesd204/axi_jesd204_tx/axi_jesd204_tx.v | 20 +- .../axi_jesd204_tx/axi_jesd204_tx_hw.tcl | 2 +- .../axi_jesd204_tx/axi_jesd204_tx_ip.tcl | 2 +- .../jesd204/axi_jesd204_tx/jesd204_up_tx.v | 17 +- library/jesd204/interfaces/interfaces_ip.tcl | 4 +- library/jesd204/jesd204_common/Makefile | 2 + .../jesd204_common/jesd204_common_ip.tcl | 2 + .../jesd204_frame_align_replace.v | 245 +++++++++++++++++ .../jesd204_frame_mark.v} | 114 ++++++-- library/jesd204/jesd204_common/jesd204_lmfc.v | 34 ++- library/jesd204/jesd204_rx/Makefile | 3 +- library/jesd204/jesd204_rx/align_mux.v | 35 ++- .../jesd204/jesd204_rx/jesd204_ilas_monitor.v | 83 +++--- .../jesd204_rx/jesd204_lane_latency_monitor.v | 16 +- library/jesd204/jesd204_rx/jesd204_rx.v | 105 +++----- library/jesd204/jesd204_rx/jesd204_rx_ctrl.v | 15 +- ...ign_monitor.v => jesd204_rx_frame_align.v} | 64 +++-- library/jesd204/jesd204_rx/jesd204_rx_hw.tcl | 6 +- library/jesd204/jesd204_rx/jesd204_rx_ip.tcl | 7 +- library/jesd204/jesd204_rx/jesd204_rx_lane.v | 65 +++-- .../jesd204_rx_static_config.v | 21 +- .../jesd204_rx_static_config_ip.tcl | 2 +- library/jesd204/jesd204_tx/jesd204_tx.v | 113 +++++--- library/jesd204/jesd204_tx/jesd204_tx_ctrl.v | 137 ++++++++-- library/jesd204/jesd204_tx/jesd204_tx_hw.tcl | 4 +- library/jesd204/jesd204_tx/jesd204_tx_ip.tcl | 4 +- library/jesd204/jesd204_tx/jesd204_tx_lane.v | 84 +++++- .../jesd204_ilas_cfg_static.v | 29 +- .../jesd204_tx_static_config.v | 26 +- .../jesd204_tx_static_config_ip.tcl | 2 +- library/jesd204/tb/frame_align_tb | 4 +- library/jesd204/tb/frame_align_tb.v | 227 ++++++++++++---- .../jesd204/tb/jesd204_frame_align_replace_tb | 7 + .../tb/jesd204_frame_align_replace_tb.v | 105 ++++++++ library/jesd204/tb/jesd204_frame_mark_tb | 7 + library/jesd204/tb/jesd204_frame_mark_tb.v | 77 ++++++ library/jesd204/tb/loopback_tb | 4 +- library/jesd204/tb/loopback_tb.v | 254 +++++++++++++----- library/jesd204/tb/run_tb.sh | 2 +- 48 files changed, 1538 insertions(+), 507 deletions(-) mode change 100644 => 100755 library/jesd204/axi_jesd204_common/jesd204_up_common.v mode change 100644 => 100755 library/jesd204/axi_jesd204_common/jesd204_up_sysref.v mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/axi_jesd204_rx_constr.xdc mode change 100644 => 100755 library/jesd204/axi_jesd204_rx/jesd204_up_ilas_mem.v mode change 100644 => 100755 library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v mode change 100644 => 100755 library/jesd204/axi_jesd204_tx/jesd204_up_tx.v mode change 100644 => 100755 library/jesd204/jesd204_common/jesd204_common_ip.tcl create mode 100755 library/jesd204/jesd204_common/jesd204_frame_align_replace.v rename library/jesd204/{jesd204_rx/jesd204_rx_frame_mark.v => jesd204_common/jesd204_frame_mark.v} (61%) mode change 100644 => 100755 library/jesd204/jesd204_common/jesd204_lmfc.v mode change 100644 => 100755 library/jesd204/jesd204_rx/align_mux.v mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_ilas_monitor.v mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_lane_latency_monitor.v mode change 100644 => 100755 library/jesd204/jesd204_rx/jesd204_rx_ctrl.v rename library/jesd204/jesd204_rx/{jesd204_rx_frame_align_monitor.v => jesd204_rx_frame_align.v} (75%) mode change 100644 => 100755 library/jesd204/jesd204_tx/jesd204_tx.v mode change 100644 => 100755 library/jesd204/jesd204_tx/jesd204_tx_ctrl.v mode change 100644 => 100755 library/jesd204/jesd204_tx/jesd204_tx_lane.v mode change 100644 => 100755 library/jesd204/jesd204_tx_static_config/jesd204_ilas_cfg_static.v mode change 100644 => 100755 library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config.v create mode 100755 library/jesd204/tb/jesd204_frame_align_replace_tb create mode 100755 library/jesd204/tb/jesd204_frame_align_replace_tb.v create mode 100755 library/jesd204/tb/jesd204_frame_mark_tb create mode 100755 library/jesd204/tb/jesd204_frame_mark_tb.v diff --git a/library/jesd204/axi_jesd204_common/jesd204_up_common.v b/library/jesd204/axi_jesd204_common/jesd204_up_common.v old mode 100644 new mode 100755 index 65bc89411..1c1a03810 --- a/library/jesd204/axi_jesd204_common/jesd204_up_common.v +++ b/library/jesd204/axi_jesd204_common/jesd204_up_common.v @@ -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]; diff --git a/library/jesd204/axi_jesd204_common/jesd204_up_sysref.v b/library/jesd204/axi_jesd204_common/jesd204_up_sysref.v old mode 100644 new mode 100755 index e7572e577..228f9b357 --- a/library/jesd204/axi_jesd204_common/jesd204_up_sysref.v +++ b/library/jesd204/axi_jesd204_common/jesd204_up_sysref.v @@ -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 diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v index 408c88a0e..dfef9e8d7 100755 --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx.v @@ -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), diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_constr.xdc b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_constr.xdc old mode 100644 new mode 100755 index b8da2fb83..f45e34f31 --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_constr.xdc +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_constr.xdc @@ -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 \ diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl index 81a12ec7d..083ea82a7 100755 --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_hw.tcl @@ -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 diff --git a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl index e3cf5126f..9b915c796 100755 --- a/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl +++ b/library/jesd204/axi_jesd204_rx/axi_jesd204_rx_ip.tcl @@ -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" } \ diff --git a/library/jesd204/axi_jesd204_rx/jesd204_up_ilas_mem.v b/library/jesd204/axi_jesd204_rx/jesd204_up_ilas_mem.v old mode 100644 new mode 100755 index c06f0026d..5eebff043 --- a/library/jesd204/axi_jesd204_rx/jesd204_up_ilas_mem.v +++ b/library/jesd204/axi_jesd204_rx/jesd204_up_ilas_mem.v @@ -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 diff --git a/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v b/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v index 429c3153a..fbdec0432 100755 --- a/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v +++ b/library/jesd204/axi_jesd204_rx/jesd204_up_rx.v @@ -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]) diff --git a/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v b/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v index 4877c176b..8cc0941bc 100755 --- a/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v +++ b/library/jesd204/axi_jesd204_rx/jesd204_up_rx_lane.v @@ -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), diff --git a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v old mode 100644 new mode 100755 index bb8be07af..04b75e435 --- a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v +++ b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx.v @@ -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), diff --git a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_hw.tcl b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_hw.tcl index ad7d53883..e681b2dee 100644 --- a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_hw.tcl +++ b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_hw.tcl @@ -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 diff --git a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_ip.tcl b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_ip.tcl index 7cec17509..dfa9a2b9e 100644 --- a/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_ip.tcl +++ b/library/jesd204/axi_jesd204_tx/axi_jesd204_tx_ip.tcl @@ -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" } \ diff --git a/library/jesd204/axi_jesd204_tx/jesd204_up_tx.v b/library/jesd204/axi_jesd204_tx/jesd204_up_tx.v old mode 100644 new mode 100755 index 8dbd900c2..178bb0819 --- a/library/jesd204/axi_jesd204_tx/jesd204_up_tx.v +++ b/library/jesd204/axi_jesd204_tx/jesd204_up_tx.v @@ -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 diff --git a/library/jesd204/interfaces/interfaces_ip.tcl b/library/jesd204/interfaces/interfaces_ip.tcl index 8ab5fbb66..717b91eda 100755 --- a/library/jesd204/interfaces/interfaces_ip.tcl +++ b/library/jesd204/interfaces/interfaces_ip.tcl @@ -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 diff --git a/library/jesd204/jesd204_common/Makefile b/library/jesd204/jesd204_common/Makefile index c72253775..bdb51dbf2 100644 --- a/library/jesd204/jesd204_common/Makefile +++ b/library/jesd204/jesd204_common/Makefile @@ -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 diff --git a/library/jesd204/jesd204_common/jesd204_common_ip.tcl b/library/jesd204/jesd204_common/jesd204_common_ip.tcl old mode 100644 new mode 100755 index da35ec870..4e3e4dd80 --- a/library/jesd204/jesd204_common/jesd204_common_ip.tcl +++ b/library/jesd204/jesd204_common/jesd204_common_ip.tcl @@ -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" \ ] diff --git a/library/jesd204/jesd204_common/jesd204_frame_align_replace.v b/library/jesd204/jesd204_common/jesd204_frame_align_replace.v new file mode 100755 index 000000000..61e44efc6 --- /dev/null +++ b/library/jesd204/jesd204_common/jesd204_frame_align_replace.v @@ -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 +// . +// +// 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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v b/library/jesd204/jesd204_common/jesd204_frame_mark.v similarity index 61% rename from library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v rename to library/jesd204/jesd204_common/jesd204_frame_mark.v index a8d946ea3..58e1ca20b 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx_frame_mark.v +++ b/library/jesd204/jesd204_common/jesd204_frame_mark.v @@ -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 diff --git a/library/jesd204/jesd204_common/jesd204_lmfc.v b/library/jesd204/jesd204_common/jesd204_lmfc.v old mode 100644 new mode 100755 index a3fcb5ea1..1228bf286 --- a/library/jesd204/jesd204_common/jesd204_lmfc.v +++ b/library/jesd204/jesd204_common/jesd204_lmfc.v @@ -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 diff --git a/library/jesd204/jesd204_rx/Makefile b/library/jesd204/jesd204_rx/Makefile index 2f695d24d..ec176f9b9 100644 --- a/library/jesd204/jesd204_rx/Makefile +++ b/library/jesd204/jesd204_rx/Makefile @@ -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 diff --git a/library/jesd204/jesd204_rx/align_mux.v b/library/jesd204/jesd204_rx/align_mux.v old mode 100644 new mode 100755 index 491e80046..22ccef688 --- a/library/jesd204/jesd204_rx/align_mux.v +++ b/library/jesd204/jesd204_rx/align_mux.v @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_ilas_monitor.v b/library/jesd204/jesd204_rx/jesd204_ilas_monitor.v old mode 100644 new mode 100755 index 93b3a36c5..b35fe0f0e --- a/library/jesd204/jesd204_rx/jesd204_ilas_monitor.v +++ b/library/jesd204/jesd204_rx/jesd204_ilas_monitor.v @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_lane_latency_monitor.v b/library/jesd204/jesd204_rx/jesd204_lane_latency_monitor.v old mode 100644 new mode 100755 index 3f27f6a95..f27e3483e --- a/library/jesd204/jesd204_rx/jesd204_lane_latency_monitor.v +++ b/library/jesd204/jesd204_rx/jesd204_lane_latency_monitor.v @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx.v b/library/jesd204/jesd204_rx/jesd204_rx.v index 9f60aa1ab..4f00493bc 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx.v +++ b/library/jesd204/jesd204_rx/jesd204_rx.v @@ -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]), diff --git a/library/jesd204/jesd204_rx/jesd204_rx_ctrl.v b/library/jesd204/jesd204_rx/jesd204_rx_ctrl.v old mode 100644 new mode 100755 index b54a89b84..b8326f635 --- a/library/jesd204/jesd204_rx/jesd204_rx_ctrl.v +++ b/library/jesd204/jesd204_rx/jesd204_rx_ctrl.v @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v b/library/jesd204/jesd204_rx/jesd204_rx_frame_align.v similarity index 75% rename from library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v rename to library/jesd204/jesd204_rx/jesd204_rx_frame_align.v index fd039a750..ca67be057 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx_frame_align_monitor.v +++ b/library/jesd204/jesd204_rx/jesd204_rx_frame_align.v @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl b/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl index 57239c98f..ef74d2f1c 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl +++ b/library/jesd204/jesd204_rx/jesd204_rx_hw.tcl @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl b/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl index 671dbf8a7..c8aa14418 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl +++ b/library/jesd204/jesd204_rx/jesd204_rx_ip.tcl @@ -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 diff --git a/library/jesd204/jesd204_rx/jesd204_rx_lane.v b/library/jesd204/jesd204_rx/jesd204_rx_lane.v index b06e41128..b097ceaab 100755 --- a/library/jesd204/jesd204_rx/jesd204_rx_lane.v +++ b/library/jesd204/jesd204_rx/jesd204_rx_lane.v @@ -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), diff --git a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v index 249c5987a..7c4151762 100755 --- a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v +++ b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config.v @@ -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 diff --git a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl index 67b595e9c..936988fd9 100755 --- a/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl +++ b/library/jesd204/jesd204_rx_static_config/jesd204_rx_static_config_ip.tcl @@ -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" } \ diff --git a/library/jesd204/jesd204_tx/jesd204_tx.v b/library/jesd204/jesd204_tx/jesd204_tx.v old mode 100644 new mode 100755 index 6b9554274..af177da85 --- a/library/jesd204/jesd204_tx/jesd204_tx.v +++ b/library/jesd204/jesd204_tx/jesd204_tx.v @@ -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; diff --git a/library/jesd204/jesd204_tx/jesd204_tx_ctrl.v b/library/jesd204/jesd204_tx/jesd204_tx_ctrl.v old mode 100644 new mode 100755 index 81512d67c..427aa31ba --- a/library/jesd204/jesd204_tx/jesd204_tx_ctrl.v +++ b/library/jesd204/jesd204_tx/jesd204_tx_ctrl.v @@ -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 diff --git a/library/jesd204/jesd204_tx/jesd204_tx_hw.tcl b/library/jesd204/jesd204_tx/jesd204_tx_hw.tcl index 8f4db2288..b0a44eb71 100644 --- a/library/jesd204/jesd204_tx/jesd204_tx_hw.tcl +++ b/library/jesd204/jesd204_tx/jesd204_tx_hw.tcl @@ -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 diff --git a/library/jesd204/jesd204_tx/jesd204_tx_ip.tcl b/library/jesd204/jesd204_tx/jesd204_tx_ip.tcl index 4518d7356..4b82cab18 100644 --- a/library/jesd204/jesd204_tx/jesd204_tx_ip.tcl +++ b/library/jesd204/jesd204_tx/jesd204_tx_ip.tcl @@ -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 diff --git a/library/jesd204/jesd204_tx/jesd204_tx_lane.v b/library/jesd204/jesd204_tx/jesd204_tx_lane.v old mode 100644 new mode 100755 index ab14dfad8..3503d8c32 --- a/library/jesd204/jesd204_tx/jesd204_tx_lane.v +++ b/library/jesd204/jesd204_tx/jesd204_tx_lane.v @@ -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 diff --git a/library/jesd204/jesd204_tx_static_config/jesd204_ilas_cfg_static.v b/library/jesd204/jesd204_tx_static_config/jesd204_ilas_cfg_static.v old mode 100644 new mode 100755 index fe63f0ef4..6517035d4 --- a/library/jesd204/jesd204_tx_static_config/jesd204_ilas_cfg_static.v +++ b/library/jesd204/jesd204_tx_static_config/jesd204_ilas_cfg_static.v @@ -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 diff --git a/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config.v b/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config.v old mode 100644 new mode 100755 index 9777284b9..a1abd4de4 --- a/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config.v +++ b/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config.v @@ -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), diff --git a/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config_ip.tcl b/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config_ip.tcl index b1a7d69d5..e452f043b 100644 --- a/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config_ip.tcl +++ b/library/jesd204/jesd204_tx_static_config/jesd204_tx_static_config_ip.tcl @@ -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" } \ diff --git a/library/jesd204/tb/frame_align_tb b/library/jesd204/tb/frame_align_tb index 76fb9cead..d80cebd4c 100755 --- a/library/jesd204/tb/frame_align_tb +++ b/library/jesd204/tb/frame_align_tb @@ -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" diff --git a/library/jesd204/tb/frame_align_tb.v b/library/jesd204/tb/frame_align_tb.v index 2376f4803..ed6f3d101 100755 --- a/library/jesd204/tb/frame_align_tb.v +++ b/library/jesd204/tb/frame_align_tb.v @@ -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; diff --git a/library/jesd204/tb/jesd204_frame_align_replace_tb b/library/jesd204/tb/jesd204_frame_align_replace_tb new file mode 100755 index 000000000..8d12fbbbb --- /dev/null +++ b/library/jesd204/tb/jesd204_frame_align_replace_tb @@ -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 diff --git a/library/jesd204/tb/jesd204_frame_align_replace_tb.v b/library/jesd204/tb/jesd204_frame_align_replace_tb.v new file mode 100755 index 000000000..c4547c1e6 --- /dev/null +++ b/library/jesd204/tb/jesd204_frame_align_replace_tb.v @@ -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 +// . +// +// 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 \ No newline at end of file diff --git a/library/jesd204/tb/jesd204_frame_mark_tb b/library/jesd204/tb/jesd204_frame_mark_tb new file mode 100755 index 000000000..45c3a4019 --- /dev/null +++ b/library/jesd204/tb/jesd204_frame_mark_tb @@ -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 diff --git a/library/jesd204/tb/jesd204_frame_mark_tb.v b/library/jesd204/tb/jesd204_frame_mark_tb.v new file mode 100755 index 000000000..b7e8336af --- /dev/null +++ b/library/jesd204/tb/jesd204_frame_mark_tb.v @@ -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 +// . +// +// 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 \ No newline at end of file diff --git a/library/jesd204/tb/loopback_tb b/library/jesd204/tb/loopback_tb index a840ec83d..c71f1b701 100755 --- a/library/jesd204/tb/loopback_tb +++ b/library/jesd204/tb/loopback_tb @@ -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" diff --git a/library/jesd204/tb/loopback_tb.v b/library/jesd204/tb/loopback_tb.v index 67eb0da06..440663a96 100755 --- a/library/jesd204/tb/loopback_tb.v +++ b/library/jesd204/tb/loopback_tb.v @@ -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; diff --git a/library/jesd204/tb/run_tb.sh b/library/jesd204/tb/run_tb.sh index e6c857949..09476475e 100755 --- a/library/jesd204/tb/run_tb.sh +++ b/library/jesd204/tb/run_tb.sh @@ -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