jesd204: Xilinx: NP=12 support

To support deterministic latency with non-power of two octets per frame
(F=3,6) the interface width towards the transport layer must be resized
to match integer multiple of frames.

e.g  Input datapath width = 4; Output datpath width = 6;
  for F=3 one beat contains 2 frames
  for F=6 one beat contains 1 frame

The width change is realized with a gearbox.

Due the interface width change the single clock domain core is split
in two clock domains.
  - Link clock : lane rate / 40 for input datapath width of 4 octets 8b10b
  -              lane rate / 20 for input datapath width of 8 octets 8b10b
  -              lane rate / 66 for input datapath width of 8 octets 64b66b

  - Device clock : Link clock * input data path width / output datapath width

Interface to transport layer and SYSREF handling is moved to device clock domain.

The configuration interface reflects the dual clock domain.

If Input and Output datapath width matches, the gearbox is no longer
required, a single clock can be connected to both clocks.
main
Laszlo Nagy 2020-10-27 15:40:37 +00:00 committed by Laszlo Nagy
parent e909962fb0
commit 454b900f90
35 changed files with 1100 additions and 252 deletions

View File

@ -34,6 +34,7 @@ module ad_ip_jesd204_tpl_adc #(
parameter SAMPLES_PER_FRAME = 1,
parameter CONVERTER_RESOLUTION = 14,
parameter BITS_PER_SAMPLE = 16,
parameter DMA_BITS_PER_SAMPLE = 16,
parameter OCTETS_PER_BEAT = 4,
parameter TWOS_COMPLEMENT = 1
) (
@ -51,7 +52,7 @@ module ad_ip_jesd204_tpl_adc #(
output [NUM_CHANNELS-1:0] enable,
output [NUM_CHANNELS-1:0] adc_valid,
output [NUM_LANES*8*OCTETS_PER_BEAT-1:0] adc_data,
output [DMA_BITS_PER_SAMPLE * OCTETS_PER_BEAT * 8 * NUM_LANES / BITS_PER_SAMPLE-1:0] adc_data,
input adc_dovf,
input adc_sync_in,
@ -90,7 +91,7 @@ module ad_ip_jesd204_tpl_adc #(
// Number of samples per channel that are processed in parallel.
localparam DATA_PATH_WIDTH = OCTETS_PER_BEAT * 8 * NUM_LANES / NUM_CHANNELS / BITS_PER_SAMPLE;
localparam LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8;
localparam DMA_DATA_WIDTH = BITS_PER_SAMPLE * DATA_PATH_WIDTH * NUM_CHANNELS;
localparam DMA_DATA_WIDTH = DMA_BITS_PER_SAMPLE * DATA_PATH_WIDTH * NUM_CHANNELS;
localparam BYTES_PER_FRAME = (NUM_CHANNELS * BITS_PER_SAMPLE * SAMPLES_PER_FRAME) / ( 8 * NUM_LANES);
@ -180,7 +181,8 @@ module ad_ip_jesd204_tpl_adc #(
.LINK_DATA_WIDTH (LINK_DATA_WIDTH),
.DMA_DATA_WIDTH (DMA_DATA_WIDTH),
.TWOS_COMPLEMENT (TWOS_COMPLEMENT),
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.DMA_BITS_PER_SAMPLE (DMA_BITS_PER_SAMPLE)
) i_core (
.clk (link_clk),

View File

@ -29,10 +29,11 @@ module ad_ip_jesd204_tpl_adc_core #(
parameter SAMPLES_PER_FRAME = 1,
parameter CONVERTER_RESOLUTION = 14,
parameter BITS_PER_SAMPLE = 16,
parameter DMA_BITS_PER_SAMPLE = 16,
parameter OCTETS_PER_BEAT = 4,
parameter DATA_PATH_WIDTH = 1,
parameter LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8,
parameter DMA_DATA_WIDTH = DATA_PATH_WIDTH * BITS_PER_SAMPLE * NUM_CHANNELS,
parameter DMA_DATA_WIDTH = DATA_PATH_WIDTH * DMA_BITS_PER_SAMPLE * NUM_CHANNELS,
parameter TWOS_COMPLEMENT = 1
) (
input clk,
@ -61,7 +62,7 @@ module ad_ip_jesd204_tpl_adc_core #(
// Raw and formatted channel data widths
localparam CDW_RAW = CONVERTER_RESOLUTION * DATA_PATH_WIDTH;
localparam ADC_DATA_WIDTH = CDW_RAW * NUM_CHANNELS;
localparam CDW_FMT = BITS_PER_SAMPLE * DATA_PATH_WIDTH;
localparam CDW_FMT = DMA_BITS_PER_SAMPLE * DATA_PATH_WIDTH;
wire [ADC_DATA_WIDTH-1:0] raw_data_s;
@ -109,7 +110,7 @@ module ad_ip_jesd204_tpl_adc_core #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.CONVERTER_RESOLUTION (CONVERTER_RESOLUTION),
.TWOS_COMPLEMENT (TWOS_COMPLEMENT),
.BITS_PER_SAMPLE (BITS_PER_SAMPLE)
.BITS_PER_SAMPLE (DMA_BITS_PER_SAMPLE)
) i_channel (
.clk (clk),

View File

@ -74,9 +74,10 @@ foreach {p v} {
"NUM_LANES" "1 2 3 4 8 16" \
"NUM_CHANNELS" "1 2 4 6 8 16 32 64" \
"BITS_PER_SAMPLE" "8 12 16" \
"DMA_BITS_PER_SAMPLE" "8 12 16" \
"CONVERTER_RESOLUTION" "8 11 12 16" \
"SAMPLES_PER_FRAME" "1 2 3 4 6 8 12 16" \
"OCTETS_PER_BEAT" "4 8" \
"OCTETS_PER_BEAT" "4 6 8 12" \
} { \
set_property -dict [list \
"value_validation_type" "list" \
@ -104,6 +105,7 @@ foreach {k v} { \
"NUM_LANES" "Number of Lanes (L)" \
"NUM_CHANNELS" "Number of Conveters (M)" \
"BITS_PER_SAMPLE" "Bits per Sample (N')" \
"DMA_BITS_PER_SAMPLE" "DMA Bits per Sample" \
"CONVERTER_RESOLUTION" "Converter Resolution (N)" \
"SAMPLES_PER_FRAME" "Samples per Frame (S)" \
"OCTETS_PER_BEAT" "Octets per Beat" \

View File

@ -32,8 +32,9 @@ module ad_ip_jesd204_tpl_dac #(
parameter NUM_LANES = 4,
parameter NUM_CHANNELS = 2,
parameter SAMPLES_PER_FRAME = 1,
parameter CONVERTER_RESOLUTION = 16,
parameter BITS_PER_SAMPLE = 16,
parameter CONVERTER_RESOLUTION = 16, // JESD_N
parameter BITS_PER_SAMPLE = 16, // JESD_NP
parameter DMA_BITS_PER_SAMPLE = 16,
parameter OCTETS_PER_BEAT = 4,
parameter DDS_TYPE = 1,
parameter DDS_CORDIC_DW = 16,
@ -55,7 +56,7 @@ module ad_ip_jesd204_tpl_dac #(
output [NUM_CHANNELS-1:0] enable,
output [NUM_CHANNELS-1:0] dac_valid,
input [NUM_LANES*8*OCTETS_PER_BEAT-1:0] dac_ddata,
input [DMA_BITS_PER_SAMPLE * OCTETS_PER_BEAT * 8 * NUM_LANES / BITS_PER_SAMPLE-1:0] dac_ddata,
input dac_dunf,
// external sync, should be on the link_clk clock domain
@ -94,7 +95,7 @@ module ad_ip_jesd204_tpl_dac #(
localparam DATA_PATH_WIDTH = OCTETS_PER_BEAT * 8 * NUM_LANES / NUM_CHANNELS / BITS_PER_SAMPLE;
localparam LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8;
localparam DMA_DATA_WIDTH = BITS_PER_SAMPLE * DATA_PATH_WIDTH * NUM_CHANNELS;
localparam DMA_DATA_WIDTH = DMA_BITS_PER_SAMPLE * DATA_PATH_WIDTH * NUM_CHANNELS;
localparam BYTES_PER_FRAME = (NUM_CHANNELS * BITS_PER_SAMPLE * SAMPLES_PER_FRAME) / ( 8 * NUM_LANES);
@ -119,6 +120,8 @@ module ad_ip_jesd204_tpl_dac #(
wire [NUM_CHANNELS*16-1:0] dac_iqcor_coeff_2;
wire [NUM_CHANNELS*8-1:0] dac_src_chan_sel;
reg [LINK_DATA_WIDTH-1:0] dac_ddata_cr;
// regmap
ad_ip_jesd204_tpl_dac_regmap #(
@ -205,7 +208,6 @@ module ad_ip_jesd204_tpl_dac #(
.OCTETS_PER_BEAT (OCTETS_PER_BEAT),
.DATA_PATH_WIDTH (DATA_PATH_WIDTH),
.LINK_DATA_WIDTH (LINK_DATA_WIDTH),
.DMA_DATA_WIDTH (DMA_DATA_WIDTH),
.DDS_TYPE (DDS_TYPE),
.DDS_CORDIC_DW (DDS_CORDIC_DW),
.DDS_CORDIC_PHASE_DW (DDS_CORDIC_PHASE_DW),
@ -220,7 +222,7 @@ module ad_ip_jesd204_tpl_dac #(
.enable (enable),
.dac_valid (dac_valid),
.dac_ddata (dac_ddata),
.dac_ddata (dac_ddata_cr),
.dac_sync (dac_sync),
.dac_sync_in_status (dac_sync_in_status),
@ -246,4 +248,12 @@ module ad_ip_jesd204_tpl_dac #(
);
// Drop DMA padding bits from the MSB
integer i;
always @(*) begin
for (i=0;i<NUM_CHANNELS*DATA_PATH_WIDTH;i=i+1) begin
dac_ddata_cr[i*BITS_PER_SAMPLE +: BITS_PER_SAMPLE] = dac_ddata[i*DMA_BITS_PER_SAMPLE +: BITS_PER_SAMPLE];
end
end
endmodule

View File

@ -35,7 +35,6 @@ module ad_ip_jesd204_tpl_dac_core #(
parameter OCTETS_PER_BEAT = 4,
parameter DATA_PATH_WIDTH = 4,
parameter LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8,
parameter DMA_DATA_WIDTH = DATA_PATH_WIDTH * BITS_PER_SAMPLE * NUM_CHANNELS,
parameter DDS_TYPE = 1,
parameter DDS_CORDIC_DW = 16,
parameter DDS_CORDIC_PHASE_DW = 16,
@ -50,7 +49,7 @@ module ad_ip_jesd204_tpl_dac_core #(
// dma interface
output [NUM_CHANNELS-1:0] dac_valid,
input [DMA_DATA_WIDTH-1:0] dac_ddata,
input [LINK_DATA_WIDTH-1:0] dac_ddata,
// Configuration interface
@ -86,11 +85,9 @@ module ad_ip_jesd204_tpl_dac_core #(
localparam DAC_CDW = CONVERTER_RESOLUTION * DATA_PATH_WIDTH;
localparam DAC_DATA_WIDTH = DAC_CDW * NUM_CHANNELS;
localparam DMA_CDW = DATA_PATH_WIDTH * BITS_PER_SAMPLE;
wire [DAC_DATA_WIDTH-1:0] dac_data_s;
wire [DMA_DATA_WIDTH-1:0] dac_ddata_muxed;
wire [DAC_DATA_WIDTH-1:0] dac_ddata_muxed;
wire [DAC_CDW-1:0] pn7_data;
wire [DAC_CDW-1:0] pn15_data;
@ -158,23 +155,22 @@ module ad_ip_jesd204_tpl_dac_core #(
localparam IQ_PAIR_CH_INDEX = (NUM_CHANNELS%2) ? i :
(i%2) ? i-1 : i+1;
if (XBAR_ENABLE == 1) begin
// NUM_CHANNELS : 1 mux
ad_mux #(
.CH_W (DMA_CDW),
.CH_W (DAC_CDW),
.CH_CNT (NUM_CHANNELS),
.EN_REG (1)
) channel_mux (
.clk (clk),
.data_in (dac_ddata),
.ch_sel (dac_src_chan_sel[8*i+:8]),
.data_out (dac_ddata_muxed[DMA_CDW*i+:DMA_CDW])
.data_out (dac_ddata_muxed[DAC_CDW*i+:DAC_CDW])
);
end else begin
assign dac_ddata_muxed[DMA_CDW*i+:DMA_CDW] = dac_ddata[DMA_CDW*i+:DMA_CDW];
assign dac_ddata_muxed[DAC_CDW*i+:DAC_CDW] = dac_ddata[DAC_CDW*i+:DAC_CDW];
end
ad_ip_jesd204_tpl_dac_channel #(
@ -191,7 +187,7 @@ module ad_ip_jesd204_tpl_dac_core #(
.clk (clk),
.dac_enable (enable[i]),
.dac_data (dac_data_s[DAC_CDW*i+:DAC_CDW]),
.dma_data (dac_ddata_muxed[DMA_CDW*i+:DMA_CDW]),
.dma_data (dac_ddata_muxed[DAC_CDW*i+:DAC_CDW]),
.pn7_data (pn7_data),
.pn15_data (pn15_data),
@ -215,7 +211,7 @@ module ad_ip_jesd204_tpl_dac_core #(
.dac_iqcor_enb (dac_iqcor_enb[i]),
.dac_iqcor_coeff_1 (dac_iqcor_coeff_1[16*i+:16]),
.dac_iqcor_coeff_2 (dac_iqcor_coeff_2[16*i+:16]),
.dac_iqcor_data_in (dac_ddata_muxed[DMA_CDW*IQ_PAIR_CH_INDEX+:DMA_CDW])
.dac_iqcor_data_in (dac_ddata_muxed[DAC_CDW*IQ_PAIR_CH_INDEX+:DAC_CDW])
);
end

View File

@ -97,9 +97,10 @@ foreach {p v} {
"NUM_LANES" "1 2 3 4 8 16" \
"NUM_CHANNELS" "1 2 4 6 8 16 32 64" \
"BITS_PER_SAMPLE" "8 12 16" \
"DMA_BITS_PER_SAMPLE" "8 12 16" \
"CONVERTER_RESOLUTION" "8 11 12 16" \
"SAMPLES_PER_FRAME" "1 2 3 4 6 8 12 16" \
"OCTETS_PER_BEAT" "4 8" \
"OCTETS_PER_BEAT" "4 6 8 12" \
} { \
set_property -dict [list \
"value_validation_type" "list" \
@ -127,6 +128,7 @@ foreach {k v} { \
"NUM_LANES" "Number of Lanes (L)" \
"NUM_CHANNELS" "Number of Conveters (M)" \
"BITS_PER_SAMPLE" "Bits per Sample (N')" \
"DMA_BITS_PER_SAMPLE" "DMA Bits per Sample" \
"CONVERTER_RESOLUTION" "Converter Resolution (N)" \
"SAMPLES_PER_FRAME" "Samples per Frame (S)" \
"OCTETS_PER_BEAT" "Octets per Beat" \

View File

@ -51,9 +51,9 @@ module jesd204_up_common # (
parameter NUM_LANES = 1,
parameter NUM_LINKS = 1,
parameter DATA_PATH_WIDTH_LOG2 = 2,
parameter MAX_OCTETS_PER_FRAME = 256,
parameter NUM_IRQS = 1,
parameter EXTRA_CFG_WIDTH = 1,
parameter DEV_EXTRA_CFG_WIDTH = 1,
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
parameter ENABLE_LINK_STATS = 0
) (
@ -68,6 +68,9 @@ module jesd204_up_common # (
input core_reset_ext,
output core_reset,
input device_clk,
output device_reset,
input [11:0] up_raddr,
output reg [31:0] up_rdata,
@ -76,25 +79,33 @@ module jesd204_up_common # (
input [31:0] up_wdata,
input [EXTRA_CFG_WIDTH-1:0] up_extra_cfg,
input [DEV_EXTRA_CFG_WIDTH-1:0] up_dev_extra_cfg,
input [NUM_IRQS-1:0] up_irq_trigger,
output reg irq,
output up_cfg_is_writeable,
output reg [NUM_LANES-1:0] core_cfg_lanes_disable,
output reg [NUM_LINKS-1:0] core_cfg_links_disable,
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
output reg [NUM_LANES-1:0] core_cfg_lanes_disable = {NUM_LANES{1'b0}},
output reg [NUM_LINKS-1:0] core_cfg_links_disable = {NUM_LINKS{1'b0}},
output reg [9:0] core_cfg_octets_per_multiframe = 'h00,
output reg [7:0] core_cfg_octets_per_frame = 'h00,
output reg core_cfg_disable_scrambler = 'h00,
output reg core_cfg_disable_char_replacement = 'h00,
output reg [EXTRA_CFG_WIDTH-1:0] core_extra_cfg = 'h00,
output reg [DEV_EXTRA_CFG_WIDTH-1:0] device_extra_cfg = 'h00,
output reg [9:0] device_cfg_octets_per_multiframe = 'h00,
output reg [7:0] device_cfg_octets_per_frame = 'h00,
output reg [7:0] device_cfg_beats_per_multiframe = 'h00
);
reg [31:0] up_scratch = 32'h00000000;
reg [7:0] up_cfg_octets_per_frame = 'h00;
reg [9:0] up_cfg_octets_per_multiframe = 'h00;
reg [9:0] up_cfg_octets_per_multiframe = {DATA_PATH_WIDTH_LOG2{1'b1}};
reg [7:0] up_cfg_beats_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;
@ -108,6 +119,9 @@ assign up_reset = up_reset_vector[0];
reg [4:0] core_reset_vector = 5'b11111;
assign core_reset = core_reset_vector[0];
reg [4:0] device_reset_vector = 5'b11111;
assign device_reset = device_reset_vector[0];
/* Transfer the reset signal back to the up domain, used to keep the
* synchronizers in reset until the core is ready. This is done in order to
* prevent bogus data to propagate to the register map. */
@ -127,6 +141,9 @@ assign up_core_reset_ext = up_core_reset_ext_synchronizer_vector[0];
wire core_cfg_transfer_en;
assign core_cfg_transfer_en = core_reset_vector[2] ^ core_reset_vector[1];
wire device_cfg_transfer_en;
assign device_cfg_transfer_en = device_reset_vector[2] ^ device_reset_vector[1];
reg up_reset_core = 1'b1;
assign up_cfg_is_writeable = up_reset_core;
@ -149,6 +166,14 @@ always @(posedge core_clk or posedge core_reset_all) begin
end
end
always @(posedge device_clk or posedge core_reset_all) begin
if (core_reset_all == 1'b1) begin
device_reset_vector <= 5'b11111;
end else begin
device_reset_vector <= {1'b0,device_reset_vector[4:1]};
end
end
always @(posedge up_clk or posedge core_reset) begin
if (core_reset == 1'b1) begin
up_reset_synchronizer_vector <= 2'b11;
@ -177,6 +202,15 @@ always @(posedge core_clk) begin
end
end
always @(posedge device_clk) begin
if (device_cfg_transfer_en == 1'b1) begin
device_cfg_octets_per_multiframe <= up_cfg_octets_per_multiframe;
device_cfg_octets_per_frame <= up_cfg_octets_per_frame;
device_cfg_beats_per_multiframe <= up_cfg_beats_per_multiframe;
device_extra_cfg <= up_dev_extra_cfg;
end
end
/* Interupt handling */
reg [NUM_IRQS-1:0] up_irq_enable = {NUM_IRQS{1'b0}};
reg [NUM_IRQS-1:0] up_irq_source = 'h00;
@ -251,6 +285,7 @@ end
endgenerate
wire [20:0] clk_mon_count;
wire [20:0] device_clk_mon_count;
always @(*) begin
case (up_raddr)
@ -277,7 +312,8 @@ always @(*) begin
12'h030: up_rdata = up_reset_core;
12'h031: up_rdata = {up_core_reset_ext, up_reset_synchronizer}; /* core ready */
12'h032: up_rdata = {11'h00, clk_mon_count}; /* Make it 16.16 */
/* 0x32-0x34 reserver for future use */
12'h033: up_rdata = {11'h00, device_clk_mon_count}; /* Make it 16.16 */
/* 0x34-0x34 reserver for future use */
12'h080: up_rdata = up_cfg_lanes_disable;
/* 0x82-0x83 reserved for future lane disable bits (max 128 lanes) */
@ -293,7 +329,8 @@ always @(*) begin
/* 00 */ up_cfg_disable_scrambler /* Disable scrambler */
};
12'h086: up_rdata = up_cfg_links_disable;
/* 0x87-0x8f reserved for future use */
12'h087: up_rdata = up_cfg_beats_per_multiframe;
/* 0x88-0x8f reserved for future use */
/* 0x90-0x9f reserved for core specific configuration options */
@ -325,9 +362,10 @@ always @(posedge up_clk) begin
up_reset_core <= 1'b1;
up_cfg_octets_per_frame <= 'h00;
up_cfg_octets_per_multiframe <= 'h00;
up_cfg_octets_per_multiframe <= {DATA_PATH_WIDTH_LOG2{1'b1}};
up_cfg_lanes_disable <= {NUM_LANES{1'b0}};
up_cfg_links_disable <= {NUM_LINKS{1'b0}};
up_cfg_beats_per_multiframe <= 'h00;
up_cfg_disable_char_replacement <= 1'b0;
up_cfg_disable_scrambler <= 1'b0;
@ -356,7 +394,8 @@ always @(posedge up_clk) begin
end
12'h084: begin
up_cfg_octets_per_frame <= up_wdata[23:16];
up_cfg_octets_per_multiframe <= up_wdata[9:0];
up_cfg_octets_per_multiframe <= {up_wdata[9:DATA_PATH_WIDTH_LOG2],
{DATA_PATH_WIDTH_LOG2{1'b1}}};
end
12'h085: begin
up_cfg_disable_char_replacement <= up_wdata[1];
@ -365,6 +404,9 @@ always @(posedge up_clk) begin
12'h086: begin
up_cfg_links_disable <= up_wdata[NUM_LINKS-1:0];
end
12'h087: begin
up_cfg_beats_per_multiframe <= up_wdata[7:0];
end
endcase
end
end
@ -380,4 +422,14 @@ up_clock_mon #(
.d_clk(core_clk)
);
up_clock_mon #(
.TOTAL_WIDTH(21)
) i_dev_clock_mon (
.up_rstn(~up_reset),
.up_clk(up_clk),
.up_d_count(device_clk_mon_count),
.d_rst(1'b0),
.d_clk(device_clk)
);
endmodule

View File

@ -52,6 +52,8 @@ module jesd204_up_sysref #(
input core_clk,
input device_clk,
input [11:0] up_raddr,
output reg [31:0] up_rdata,
@ -65,8 +67,8 @@ module jesd204_up_sysref #(
output reg [7:0] up_cfg_lmfc_offset,
output reg up_cfg_sysref_disable,
input core_event_sysref_alignment_error,
input core_event_sysref_edge
input device_event_sysref_alignment_error,
input device_event_sysref_edge
);
reg [1:0] up_sysref_status;
@ -76,10 +78,10 @@ wire [1:0] up_sysref_event;
sync_event #(
.NUM_OF_EVENTS(2)
) i_cdc_sysref_event (
.in_clk(core_clk),
.in_clk(device_clk),
.in_event({
core_event_sysref_alignment_error,
core_event_sysref_edge
device_event_sysref_alignment_error,
device_event_sysref_edge
}),
.out_clk(up_clk),
.out_event(up_sysref_event)
@ -127,8 +129,8 @@ always @(posedge up_clk) begin
up_cfg_sysref_disable <= up_wdata[0];
end
12'h041: begin
/* Aligned to data path width */
up_cfg_lmfc_offset <= up_wdata[9:DATA_PATH_WIDTH_LOG2];
/* Must be aligned to data path width */
up_cfg_lmfc_offset <= up_wdata;
end
endcase
end

View File

@ -81,25 +81,32 @@ module axi_jesd204_rx #(
input core_reset_ext,
output core_reset,
input device_clk,
output device_reset,
output [NUM_LANES-1:0] core_cfg_lanes_disable,
output [NUM_LINKS-1:0] core_cfg_links_disable,
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,
output [7:0] core_cfg_lmfc_offset,
output core_cfg_sysref_oneshot,
output core_cfg_sysref_disable,
output core_cfg_buffer_early_release,
output [7:0] core_cfg_buffer_delay,
output [7:0] core_cfg_frame_align_err_threshold,
output [9:0] device_cfg_octets_per_multiframe,
output [7:0] device_cfg_octets_per_frame,
output [7:0] device_cfg_beats_per_multiframe,
output [7:0] device_cfg_lmfc_offset,
output device_cfg_sysref_oneshot,
output device_cfg_sysref_disable,
output device_cfg_buffer_early_release,
output [7:0] device_cfg_buffer_delay,
input [NUM_LANES-1:0] core_ilas_config_valid,
input [2*NUM_LANES-1:0] core_ilas_config_addr,
input [NUM_LANES*DATA_PATH_WIDTH*8-1:0] core_ilas_config_data,
input core_event_sysref_alignment_error,
input core_event_sysref_edge,
input device_event_sysref_alignment_error,
input device_event_sysref_edge,
input core_event_frame_alignment_error,
input core_event_unexpected_lane_state_error,
@ -135,7 +142,7 @@ wire [31:0] up_rdata_common;
wire [31:0] up_rdata_sysref;
wire [31:0] up_rdata_rx;
wire [4:0] up_irq_trigger = 5'b00000;
wire [4:0] up_irq_trigger;
wire up_cfg_is_writeable;
wire up_cfg_sysref_oneshot;
@ -206,7 +213,8 @@ jesd204_up_common #(
.NUM_LINKS(NUM_LINKS),
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2),
.NUM_IRQS(5),
.EXTRA_CFG_WIDTH(27),
.EXTRA_CFG_WIDTH(8),
.DEV_EXTRA_CFG_WIDTH(19),
.LINK_MODE(LINK_MODE),
.ENABLE_LINK_STATS(ENABLE_LINK_STATS)
) i_up_common (
@ -220,6 +228,9 @@ jesd204_up_common #(
.core_reset_ext(core_reset_ext),
.core_reset(core_reset),
.device_clk(device_clk),
.device_reset(device_reset),
.up_raddr(up_raddr),
.up_rdata(up_rdata_common),
.up_wreq(up_wreq),
@ -239,20 +250,29 @@ jesd204_up_common #(
.core_cfg_disable_char_replacement(core_cfg_disable_char_replacement),
.up_extra_cfg({
/* 19-26 */ up_cfg_frame_align_err_threshold,
/* 00-07 */ up_cfg_frame_align_err_threshold
}),
.core_extra_cfg({
/* 00-07 */ core_cfg_frame_align_err_threshold
}),
.device_cfg_octets_per_multiframe(device_cfg_octets_per_multiframe),
.device_cfg_octets_per_frame(device_cfg_octets_per_frame),
.device_cfg_beats_per_multiframe(device_cfg_beats_per_multiframe),
.up_dev_extra_cfg({
/* 18 */ up_cfg_sysref_disable,
/* 17 */ up_cfg_sysref_oneshot,
/* 16 */ up_cfg_buffer_early_release,
/* 08-15 */ up_cfg_buffer_delay,
/* 15-08 */ up_cfg_buffer_delay,
/* 00-07 */ up_cfg_lmfc_offset
}),
.core_extra_cfg({
/* 19-26 */ core_cfg_frame_align_err_threshold,
/* 18 */ core_cfg_sysref_disable,
/* 17 */ core_cfg_sysref_oneshot,
/* 16 */ core_cfg_buffer_early_release,
/* 08-15 */ core_cfg_buffer_delay,
/* 00-07 */ core_cfg_lmfc_offset
.device_extra_cfg({
/* 18 */ device_cfg_sysref_disable,
/* 17 */ device_cfg_sysref_oneshot,
/* 16 */ device_cfg_buffer_early_release,
/* 15-08 */ device_cfg_buffer_delay,
/* 00-07 */ device_cfg_lmfc_offset
})
);
@ -263,8 +283,9 @@ jesd204_up_sysref #(
.up_reset(up_reset),
.core_clk(core_clk),
.core_event_sysref_edge(core_event_sysref_edge),
.core_event_sysref_alignment_error(core_event_sysref_alignment_error),
.device_clk(device_clk),
.device_event_sysref_edge(device_event_sysref_edge),
.device_event_sysref_alignment_error(device_event_sysref_alignment_error),
.up_raddr(up_raddr),
.up_rdata(up_rdata_sysref),

View File

@ -44,6 +44,7 @@
set axi_clk [get_clocks -of_objects [get_ports s_axi_aclk]]
set core_clk [get_clocks -of_objects [get_ports core_clk]]
set device_clk [get_clocks -of_objects [get_ports device_clk]]
set_property ASYNC_REG TRUE \
[get_cells -hier {*cdc_sync_stage1_reg*}] \
@ -130,6 +131,10 @@ set_false_path \
-from [get_pins {i_up_common/up_reset_core_reg/C}] \
-to [get_pins {i_up_common/core_reset_vector_reg[*]/PRE}]
set_false_path \
-from [get_pins {i_up_common/up_reset_core_reg/C}] \
-to [get_pins {i_up_common/device_reset_vector_reg[*]/PRE}]
set_false_path \
-from [get_pins {i_up_common/core_reset_vector_reg[0]/C}] \
-to [get_pins {i_up_common/up_reset_synchronizer_vector_reg[*]/PRE}]
@ -142,12 +147,22 @@ set_max_delay -datapath_only \
-to [get_pins {i_up_common/core_cfg_*_reg*/D}] \
[get_property -min PERIOD $core_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_common/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/device_cfg_*_reg*/D}] \
[get_property -min PERIOD $device_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_rx/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/core_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $core_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_rx/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/device_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $device_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_sysref/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/core_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $core_clk]
-to [get_pins {i_up_common/device_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $device_clk]

View File

@ -79,16 +79,19 @@ adi_add_bus "rx_cfg" "master" \
{ "core_cfg_links_disable" "links_disable" } \
{ "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" } \
{ "core_cfg_sysref_disable" "sysref_disable" } \
{ "core_ctrl_err_statistics_reset" "err_statistics_reset" } \
{ "core_ctrl_err_statistics_mask" "err_statistics_mask" } \
{ "core_cfg_buffer_early_release" "buffer_early_release" } \
{ "core_cfg_buffer_delay" "buffer_delay" } \
{ "core_cfg_disable_char_replacement" "disable_char_replacement" } \
{ "core_cfg_disable_scrambler" "disable_scrambler" } \
{ "core_cfg_frame_align_err_threshold" "frame_align_err_threshold" } \
{ "device_cfg_octets_per_multiframe" "device_octets_per_multiframe" } \
{ "device_cfg_octets_per_frame" "device_octets_per_frame" } \
{ "device_cfg_beats_per_multiframe" "device_beats_per_multiframe" } \
{ "device_cfg_lmfc_offset" "device_lmfc_offset" } \
{ "device_cfg_sysref_oneshot" "device_sysref_oneshot" } \
{ "device_cfg_sysref_disable" "device_sysref_disable" } \
{ "device_cfg_buffer_early_release" "device_buffer_early_release" } \
{ "device_cfg_buffer_delay" "device_buffer_delay" } \
{ "core_ctrl_err_statistics_reset" "err_statistics_reset" } \
{ "core_ctrl_err_statistics_mask" "err_statistics_mask" } \
}
adi_add_bus "rx_ilas_config" "slave" \
@ -104,8 +107,8 @@ adi_add_bus "rx_event" "slave" \
"analog.com:interface:jesd204_rx_event_rtl:1.0" \
"analog.com:interface:jesd204_rx_event:1.0" \
{ \
{ "core_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "core_event_sysref_edge" "sysref_edge" } \
{ "device_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "device_event_sysref_edge" "sysref_edge" } \
{ "core_event_frame_alignment_error" "frame_alignment_error" } \
{ "core_event_unexpected_lane_state_error" "unexpected_lane_state_error" } \
}

View File

@ -81,13 +81,13 @@ module axi_jesd204_tx #(
input core_reset_ext,
output core_reset,
input device_clk,
output device_reset,
output [NUM_LANES-1:0] core_cfg_lanes_disable,
output [NUM_LINKS-1:0] core_cfg_links_disable,
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,
output core_cfg_sysref_disable,
output core_cfg_continuous_cgs,
output core_cfg_continuous_ilas,
output core_cfg_skip_ilas,
@ -95,12 +95,19 @@ module axi_jesd204_tx #(
output core_cfg_disable_char_replacement,
output core_cfg_disable_scrambler,
output [7:0] device_cfg_octets_per_multiframe,
output [7:0] device_cfg_octets_per_frame,
output [7:0] device_cfg_beats_per_multiframe,
output [7:0] device_cfg_lmfc_offset,
output device_cfg_sysref_oneshot,
output device_cfg_sysref_disable,
input core_ilas_config_rd,
input [1:0] core_ilas_config_addr,
output [DATA_PATH_WIDTH*8*NUM_LANES-1:0] core_ilas_config_data,
input core_event_sysref_alignment_error,
input core_event_sysref_edge,
input device_event_sysref_alignment_error,
input device_event_sysref_edge,
output core_ctrl_manual_sync_request,
@ -181,8 +188,9 @@ jesd204_up_common #(
.NUM_LINKS(NUM_LINKS),
.DATA_PATH_WIDTH_LOG2(DATA_PATH_WIDTH_LOG2),
.NUM_IRQS(5),
.EXTRA_CFG_WIDTH(21),
.MAX_OCTETS_PER_FRAME(8),
.EXTRA_CFG_WIDTH(11),
.DEV_EXTRA_CFG_WIDTH(10),
.MAX_OCTETS_PER_FRAME(10),
.LINK_MODE(LINK_MODE),
.ENABLE_LINK_STATS(ENABLE_LINK_STATS)
) i_up_common (
@ -197,6 +205,9 @@ jesd204_up_common #(
.core_reset_ext(core_reset_ext),
.core_reset(core_reset),
.device_clk(device_clk),
.device_reset(device_reset),
.up_raddr(up_raddr),
.up_rdata(up_rdata_common),
@ -217,22 +228,31 @@ jesd204_up_common #(
.core_cfg_disable_char_replacement(core_cfg_disable_char_replacement),
.up_extra_cfg({
/* 20 */ up_cfg_sysref_disable,
/* 19 */ up_cfg_sysref_oneshot,
/* 18 */ up_cfg_continuous_cgs,
/* 17 */ up_cfg_continuous_ilas,
/* 16 */ up_cfg_skip_ilas,
/* 08-15 */ up_cfg_lmfc_offset,
/* 10 */ up_cfg_continuous_cgs,
/* 09 */ up_cfg_continuous_ilas,
/* 08 */ up_cfg_skip_ilas,
/* 00-07 */ up_cfg_mframes_per_ilas
}),
.core_extra_cfg({
/* 20 */ core_cfg_sysref_disable,
/* 19 */ core_cfg_sysref_oneshot,
/* 18 */ core_cfg_continuous_cgs,
/* 17 */ core_cfg_continuous_ilas,
/* 16 */ core_cfg_skip_ilas,
/* 08-15 */ core_cfg_lmfc_offset,
/* 10 */ core_cfg_continuous_cgs,
/* 09 */ core_cfg_continuous_ilas,
/* 08 */ core_cfg_skip_ilas,
/* 00-07 */ core_cfg_mframes_per_ilas
}),
.device_cfg_octets_per_multiframe(device_cfg_octets_per_multiframe),
.device_cfg_octets_per_frame(device_cfg_octets_per_frame),
.device_cfg_beats_per_multiframe(device_cfg_beats_per_multiframe),
.up_dev_extra_cfg({
/* 09 */ up_cfg_sysref_disable,
/* 08 */ up_cfg_sysref_oneshot,
/* 00-07 */ up_cfg_lmfc_offset
}),
.device_extra_cfg({
/* 09 */ device_cfg_sysref_disable,
/* 08 */ device_cfg_sysref_oneshot,
/* 00-07 */ device_cfg_lmfc_offset
})
);
@ -243,8 +263,9 @@ jesd204_up_sysref #(
.up_reset(up_reset),
.core_clk(core_clk),
.core_event_sysref_alignment_error(core_event_sysref_alignment_error),
.core_event_sysref_edge(core_event_sysref_edge),
.device_clk(device_clk),
.device_event_sysref_alignment_error(device_event_sysref_alignment_error),
.device_event_sysref_edge(device_event_sysref_edge),
.up_cfg_lmfc_offset(up_cfg_lmfc_offset),
.up_cfg_sysref_oneshot(up_cfg_sysref_oneshot),

View File

@ -44,6 +44,7 @@
set axi_clk [get_clocks -of_objects [get_ports s_axi_aclk]]
set core_clk [get_clocks -of_objects [get_ports core_clk]]
set device_clk [get_clocks -of_objects [get_ports device_clk]]
set_property ASYNC_REG TRUE \
[get_cells -hier {*cdc_sync_stage1_reg*}] \
@ -90,6 +91,10 @@ set_false_path \
-from [get_pins {i_up_common/up_reset_core_reg/C}] \
-to [get_pins {i_up_common/core_reset_vector_reg[*]/PRE}]
set_false_path \
-from [get_pins {i_up_common/up_reset_core_reg/C}] \
-to [get_pins {i_up_common/device_reset_vector_reg[*]/PRE}]
set_false_path \
-from [get_pins {i_up_common/core_reset_vector_reg[0]/C}] \
-to [get_pins {i_up_common/up_reset_synchronizer_vector_reg[*]/PRE}]
@ -102,6 +107,11 @@ set_max_delay -datapath_only \
-to [get_pins {i_up_common/core_cfg_*_reg*/D}] \
[get_property -min PERIOD $core_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_common/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/device_cfg_*_reg*/D}] \
[get_property -min PERIOD $device_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_tx/up_cfg_ilas_data_*_reg*/C}] \
-to [get_cells {i_up_tx/*core_ilas_config_data_reg*}] \
@ -112,10 +122,15 @@ set_max_delay -datapath_only \
-to [get_pins {i_up_common/core_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $core_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_tx/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/device_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $device_clk]
set_max_delay -datapath_only \
-from [get_pins {i_up_sysref/up_cfg_*_reg*/C}] \
-to [get_pins {i_up_common/core_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $core_clk]
-to [get_pins {i_up_common/device_extra_cfg_reg[*]/D}] \
[get_property -min PERIOD $device_clk]
set_false_path \
-from [get_pins {i_up_tx/i_cdc_manual_sync_request/out_toggle_d1_reg/C}] \

View File

@ -77,15 +77,18 @@ adi_add_bus "tx_cfg" "master" \
{ "core_cfg_links_disable" "links_disable" } \
{ "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" } \
{ "core_cfg_sysref_disable" "sysref_disable" } \
{ "core_cfg_continuous_cgs" "continuous_cgs" } \
{ "core_cfg_continuous_ilas" "continuous_ilas" } \
{ "core_cfg_skip_ilas" "skip_ilas" } \
{ "core_cfg_mframes_per_ilas" "mframes_per_ilas" } \
{ "core_cfg_disable_char_replacement" "disable_char_replacement" } \
{ "core_cfg_disable_scrambler" "disable_scrambler" } \
{ "device_cfg_octets_per_multiframe" "device_octets_per_multiframe" } \
{ "device_cfg_octets_per_frame" "device_octets_per_frame" } \
{ "device_cfg_beats_per_multiframe" "device_beats_per_multiframe" } \
{ "device_cfg_lmfc_offset" "device_lmfc_offset" } \
{ "device_cfg_sysref_oneshot" "device_sysref_oneshot" } \
{ "device_cfg_sysref_disable" "device_sysref_disable" } \
}
adi_add_bus "tx_ilas_config" "slave" \
@ -101,8 +104,8 @@ adi_add_bus "tx_event" "slave" \
"analog.com:interface:jesd204_tx_event_rtl:1.0" \
"analog.com:interface:jesd204_tx_event:1.0" \
{ \
{ "core_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "core_event_sysref_edge" "sysref_edge" } \
{ "device_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "device_event_sysref_edge" "sysref_edge" } \
}
adi_add_bus "tx_status" "slave" \

View File

@ -52,13 +52,18 @@ adi_if_ports output -1 lanes_disable
adi_if_ports output -1 links_disable
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
adi_if_ports output 1 continuous_ilas
adi_if_ports output 1 skip_ilas
adi_if_ports output 8 mframes_per_ilas
adi_if_ports output 1 disable_char_replacement
adi_if_ports output 1 disable_scrambler
adi_if_ports output 10 device_octets_per_multiframe
adi_if_ports output 8 device_octets_per_frame
adi_if_ports output 8 device_beats_per_multiframe
adi_if_ports output 8 device_lmfc_offset
adi_if_ports output 1 device_sysref_oneshot
adi_if_ports output 1 device_sysref_disable
adi_if_define "jesd204_tx_ilas_config"
adi_if_ports output 1 rd
@ -83,12 +88,17 @@ adi_if_ports output -1 lanes_disable
adi_if_ports output -1 links_disable
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
adi_if_ports output 1 buffer_delay
adi_if_ports output 1 disable_char_replacement
adi_if_ports output 1 disable_scrambler
adi_if_ports output 8 frame_align_err_threshold
adi_if_ports output 10 device_octets_per_multiframe
adi_if_ports output 8 device_octets_per_frame
adi_if_ports output 8 device_beats_per_multiframe
adi_if_ports output 8 device_lmfc_offset
adi_if_ports output 1 device_sysref_oneshot
adi_if_ports output 1 device_sysref_disable
adi_if_ports output 1 device_buffer_early_release
adi_if_ports output 1 device_buffer_delay
adi_if_ports output 1 err_statistics_reset
adi_if_ports output 7 err_statistics_mask

View File

@ -43,9 +43,13 @@
//
// Limitations:
// 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
// for 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
// for DATA_PATH_WIDTH = 6
// F=3,6
// for DATA_PATH_WIDTH = 12
// F=3,6,12
`timescale 1ns/100ps
@ -55,6 +59,7 @@ module jesd204_frame_mark #(
input clk,
input reset,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_beats_per_multiframe,
input [7:0] cfg_octets_per_frame,
output reg [DATA_PATH_WIDTH-1:0] sof,
@ -75,7 +80,6 @@ localparam CW = MAX_OCTETS_PER_FRAME > 128 ? 8 :
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;
@ -114,6 +118,21 @@ initial begin
eof_f_6[1] = {4'b0010};
eof_f_6[2] = {4'b1000};
end
end else if(DATA_PATH_WIDTH == 6) begin : gen_dp_6
initial begin
sof_f_3[0] = {6'b001001};
sof_f_3[1] = {6'b001001};
sof_f_3[2] = {6'b001001};
eof_f_3[0] = {6'b100100};
eof_f_3[1] = {6'b100100};
eof_f_3[2] = {6'b100100};
sof_f_6[0] = {6'b000001};
sof_f_6[1] = {6'b000001};
sof_f_6[2] = {6'b000001};
eof_f_6[0] = {6'b100000};
eof_f_6[1] = {6'b100000};
eof_f_6[2] = {6'b100000};
end
end else if(DATA_PATH_WIDTH == 8) begin : gen_dp_8
initial begin
sof_f_3[0] = {8'b01001001};
@ -232,7 +251,7 @@ end
assign cur_somf = beat_cnt_mf == 0;
assign cur_eomf = beat_cnt_mf == cur_beats_per_multiframe;
if(DATA_PATH_WIDTH == 4) begin : gen_mf_dp_4
if(DATA_PATH_WIDTH == 4 || DATA_PATH_WIDTH == 6) begin : gen_mf_dp_4_6
always @(*) begin
cur_beats_per_multiframe = cfg_beats_per_multiframe;
somf = {{DATA_PATH_WIDTH-1{1'b0}}, cur_somf};

View File

@ -54,6 +54,7 @@ module jesd204_lmfc #(
input sysref,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_beats_per_multiframe,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_oneshot,
input cfg_sysref_disable,
@ -75,7 +76,7 @@ module jesd204_lmfc #(
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];
//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;

View File

@ -30,6 +30,7 @@ XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_ilas_config.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_ilas_config_rtl.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_status.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_rx_status_rtl.xml
XILINX_DEPS += bd/bd.tcl
XILINX_LIB_DEPS += jesd204/jesd204_common

View File

@ -0,0 +1,44 @@
proc init {cellpath otherInfo} {
set ip [get_bd_cells $cellpath]
bd::mark_propagate_override $ip \
"ASYNC_CLK"
}
proc detect_async_clk { cellpath ip param_name clk_a clk_b } {
set param_src [get_property "CONFIG.$param_name.VALUE_SRC" $ip]
if {[string equal $param_src "USER"]} {
return;
}
set clk_domain_a [get_property CONFIG.CLK_DOMAIN $clk_a]
set clk_domain_b [get_property CONFIG.CLK_DOMAIN $clk_b]
set clk_freq_a [get_property CONFIG.FREQ_HZ $clk_a]
set clk_freq_b [get_property CONFIG.FREQ_HZ $clk_b]
set clk_phase_a [get_property CONFIG.PHASE $clk_a]
set clk_phase_b [get_property CONFIG.PHASE $clk_b]
# Only mark it as sync if we can make sure that it is sync, if the
# relationship of the clocks is unknown mark it as async
if {$clk_domain_a != {} && $clk_domain_b != {} && \
$clk_domain_a == $clk_domain_b && $clk_freq_a == $clk_freq_b && \
$clk_phase_a == $clk_phase_b} {
set clk_async 0
} else {
set clk_async 1
}
set_property "CONFIG.$param_name" $clk_async $ip
}
proc propagate {cellpath otherinfo} {
set ip [get_bd_cells $cellpath]
set link_clk [get_bd_pins "$ip/clk"]
set device_clk [get_bd_pins "$ip/device_clk"]
detect_async_clk $cellpath $ip "ASYNC_CLK" $link_clk $device_clk
}

View File

@ -45,15 +45,20 @@
`timescale 1ns/100ps
module elastic_buffer #(
parameter WIDTH = 32,
parameter SIZE = 256
parameter IWIDTH = 32,
parameter OWIDTH = 48,
parameter SIZE = 256,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input [WIDTH-1:0] wr_data,
input device_clk,
input device_reset,
output reg [WIDTH-1:0] rd_data,
input [IWIDTH-1:0] wr_data,
output reg [OWIDTH-1:0] rd_data,
input ready_n,
input do_release_n
@ -67,20 +72,45 @@ localparam ADDR_WIDTH = SIZE > 128 ? 7 :
SIZE > 4 ? 2 :
SIZE > 2 ? 1 : 0;
localparam WIDTH = OWIDTH >= IWIDTH ? OWIDTH : IWIDTH;
reg [ADDR_WIDTH:0] wr_addr = 'h00;
reg [ADDR_WIDTH:0] rd_addr = 'h00;
reg [WIDTH-1:0] mem[0:SIZE - 1];
(* ram_style = "distributed" *) reg [WIDTH-1:0] mem[0:SIZE - 1];
wire mem_wr;
wire [WIDTH-1:0] mem_wr_data;
generate if ((OWIDTH > IWIDTH) && ASYNC_CLK) begin
ad_pack #(
.I_W(IWIDTH/8),
.O_W(OWIDTH/8),
.UNIT_W(8)
) i_ad_pack (
.clk(clk),
.reset(ready_n),
.idata(wr_data),
.ivalid(1'b1),
.odata(mem_wr_data),
.ovalid(mem_wr)
);
end else begin
assign mem_wr = 1'b1;
assign mem_wr_data = wr_data;
end
endgenerate
always @(posedge clk) begin
if (ready_n == 1'b1) begin
wr_addr <= 'h00;
end else begin
mem[wr_addr] <= wr_data;
end else if (mem_wr) begin
mem[wr_addr] <= mem_wr_data;
wr_addr <= wr_addr + 1'b1;
end
end
always @(posedge clk) begin
always @(posedge device_clk) begin
if (do_release_n == 1'b1) begin
rd_addr <= 'h00;
end else begin

View File

@ -53,11 +53,16 @@ module jesd204_rx #(
parameter DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4,
parameter ENABLE_FRAME_ALIGN_CHECK = 1,
parameter ENABLE_FRAME_ALIGN_ERR_RESET = 0,
parameter ENABLE_CHAR_REPLACE = 0
parameter ENABLE_CHAR_REPLACE = 0,
parameter ASYNC_CLK = 1,
parameter TPL_DATA_PATH_WIDTH = LINK_MODE == 2 ? 8 : 4
) (
input clk,
input clk, // Link clock, lane rate / 40 or lane rate / 20 or lane rate / 66
input reset,
input device_clk, // Integer multiple of frame clock
input device_reset,
input [DATA_PATH_WIDTH*8*NUM_LANES-1:0] phy_data,
input [2*NUM_LANES-1:0] phy_header,
input [DATA_PATH_WIDTH*NUM_LANES-1:0] phy_charisk,
@ -69,8 +74,8 @@ module jesd204_rx #(
output lmfc_edge,
output lmfc_clk,
output event_sysref_alignment_error,
output event_sysref_edge,
output device_event_sysref_alignment_error,
output device_event_sysref_edge,
output event_frame_alignment_error,
output event_unexpected_lane_state_error,
@ -78,30 +83,33 @@ module jesd204_rx #(
output phy_en_char_align,
output [DATA_PATH_WIDTH*8*NUM_LANES-1:0] rx_data,
output [TPL_DATA_PATH_WIDTH*8*NUM_LANES-1:0] rx_data,
output rx_valid,
output [DATA_PATH_WIDTH-1:0] rx_eof,
output [DATA_PATH_WIDTH-1:0] rx_sof,
output [DATA_PATH_WIDTH-1:0] rx_eomf,
output [DATA_PATH_WIDTH-1:0] rx_somf,
output [TPL_DATA_PATH_WIDTH-1:0] rx_eof,
output [TPL_DATA_PATH_WIDTH-1:0] rx_sof,
output [TPL_DATA_PATH_WIDTH-1:0] rx_eomf,
output [TPL_DATA_PATH_WIDTH-1:0] rx_somf,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_disable,
input cfg_sysref_oneshot,
input cfg_buffer_early_release,
input [7:0] cfg_buffer_delay,
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
input cfg_disable_char_replacement,
input [7:0] cfg_frame_align_err_threshold,
input [9:0] device_cfg_octets_per_multiframe,
input [7:0] device_cfg_octets_per_frame,
input [7:0] device_cfg_beats_per_multiframe,
input [7:0] device_cfg_lmfc_offset,
input device_cfg_sysref_oneshot,
input device_cfg_sysref_disable,
input device_cfg_buffer_early_release,
input [7:0] device_cfg_buffer_delay,
input ctrl_err_statistics_reset,
input [6:0] ctrl_err_statistics_mask,
input [7:0] cfg_frame_align_err_threshold,
output [32*NUM_LANES-1:0] status_err_statistics_cnt,
output [NUM_LANES-1:0] ilas_config_valid,
@ -146,10 +154,12 @@ localparam LMFC_COUNTER_WIDTH = MAX_BEATS_PER_MULTIFRAME > 256 ? 9 :
/* Helper for common expressions */
localparam DW = 8*DATA_PATH_WIDTH*NUM_LANES;
localparam ODW = 8*TPL_DATA_PATH_WIDTH*NUM_LANES;
localparam CW = DATA_PATH_WIDTH*NUM_LANES;
localparam HW = 2*NUM_LANES;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe[9:DPW_LOG2];
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe >> DPW_LOG2;
wire [7:0] device_cfg_beats_per_multiframe_s;
wire [NUM_LANES-1:0] cgs_reset;
wire [NUM_LANES-1:0] cgs_ready;
@ -159,6 +169,7 @@ reg buffer_release_n = 1'b1;
reg buffer_release_d1 = 1'b0;
wire [NUM_LANES-1:0] buffer_ready_n;
wire all_buffer_ready_n;
wire dev_all_buffer_ready_n;
reg eof_reset = 1'b1;
@ -169,7 +180,7 @@ wire [CW-1:0] phy_notintable_r;
wire [CW-1:0] phy_disperr_r;
wire [NUM_LANES-1:0] phy_block_sync_r;
wire [DW-1:0] rx_data_s;
wire [ODW-1:0] rx_data_s;
wire rx_valid_s = buffer_release_d1;
@ -182,14 +193,16 @@ wire [NUM_LANES-1:0] ifs_ready;
wire event_data_phase;
wire err_statistics_reset;
wire lmfc_edge_synced;
reg [NUM_LANES-1:0] frame_align_err_thresh_met = {NUM_LANES{1'b0}};
reg [NUM_LANES-1:0] event_frame_alignment_error_per_lane = {NUM_LANES{1'b0}};
reg buffer_release_opportunity = 1'b0;
always @(posedge clk) begin
if (lmfc_counter == cfg_buffer_delay ||
cfg_buffer_early_release == 1'b1) begin
always @(posedge device_clk) begin
if (lmfc_counter == device_cfg_buffer_delay ||
device_cfg_buffer_early_release == 1'b1) begin
buffer_release_opportunity <= 1'b1;
end else begin
buffer_release_opportunity <= 1'b0;
@ -198,12 +211,22 @@ end
assign all_buffer_ready_n = |(buffer_ready_n & ~cfg_lanes_disable);
always @(posedge clk) begin
if (reset == 1'b1) begin
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_all_buffer_ready_cdc (
.in_bits(all_buffer_ready_n),
.out_clk(device_clk),
.out_resetn(1'b1),
.out_bits(dev_all_buffer_ready_n)
);
always @(posedge device_clk) begin
if (device_reset == 1'b1) begin
buffer_release_n <= 1'b1;
end else begin
if (buffer_release_opportunity == 1'b1) begin
buffer_release_n <= all_buffer_ready_n;
buffer_release_n <= dev_all_buffer_ready_n;
end
end
buffer_release_d1 <= ~buffer_release_n;
@ -234,31 +257,40 @@ pipeline_stage #(
);
pipeline_stage #(
.WIDTH(DW+1),
.WIDTH(ODW+2),
.REGISTERED(1)
) i_output_pipeline_stage (
.clk(clk),
.clk(device_clk),
.in({
eof_reset,
rx_data_s,
rx_valid_s
}),
.out({
eof_reset_d,
rx_data,
rx_valid
})
);
// If input and output widths are symmetric keep the calculation for backwards
// compatibility of the software.
assign device_cfg_beats_per_multiframe_s = (TPL_DATA_PATH_WIDTH == DATA_PATH_WIDTH) ?
device_cfg_octets_per_multiframe >> DPW_LOG2 :
device_cfg_beats_per_multiframe;
jesd204_lmfc #(
.LINK_MODE(LINK_MODE),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
.DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH)
) i_lmfc (
.clk(clk),
.reset(reset),
.clk(device_clk),
.reset(device_reset),
.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),
.cfg_octets_per_multiframe(device_cfg_octets_per_multiframe),
.cfg_beats_per_multiframe(device_cfg_beats_per_multiframe_s),
.cfg_lmfc_offset(device_cfg_lmfc_offset),
.cfg_sysref_oneshot(device_cfg_sysref_oneshot),
.cfg_sysref_disable(device_cfg_sysref_disable),
.sysref(sysref),
.lmfc_edge(lmfc_edge),
@ -268,17 +300,18 @@ jesd204_lmfc #(
.lmc_quarter_edge(),
.eoemb(),
.sysref_edge(event_sysref_edge),
.sysref_alignment_error(event_sysref_alignment_error)
.sysref_edge(device_event_sysref_edge),
.sysref_alignment_error(device_event_sysref_alignment_error)
);
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
.DATA_PATH_WIDTH (TPL_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),
.clk (device_clk),
.reset (eof_reset_d),
.cfg_beats_per_multiframe (device_cfg_beats_per_multiframe_s),
.cfg_octets_per_multiframe (device_cfg_octets_per_multiframe),
.cfg_octets_per_frame (device_cfg_octets_per_frame),
.sof (rx_sof),
.eof (rx_eof),
.somf (rx_somf),
@ -288,6 +321,16 @@ jesd204_frame_mark #(
generate
genvar i;
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_sync_lmfc (
.in_clk(device_clk),
.in_event(lmfc_edge),
.out_clk(clk),
.out_event(lmfc_edge_synced)
);
if (LINK_MODE[0] == 1) begin : mode_8b10b
wire unexpected_lane_state_error;
@ -307,7 +350,7 @@ jesd204_rx_ctrl #(
.phy_ready(1'b1),
.phy_en_char_align(phy_en_char_align),
.lmfc_edge(lmfc_edge),
.lmfc_edge(lmfc_edge_synced),
.frame_align_err_thresh_met(frame_align_err_thresh_met),
.sync(sync),
@ -330,21 +373,28 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
localparam D_STOP = D_START + DATA_PATH_WIDTH*8-1;
localparam OD_START = i * TPL_DATA_PATH_WIDTH*8;
localparam OD_STOP = OD_START + TPL_DATA_PATH_WIDTH*8-1;
localparam C_START = i * DATA_PATH_WIDTH;
localparam C_STOP = C_START + DATA_PATH_WIDTH-1;
jesd204_rx_lane #(
.DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.TPL_DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH),
.CHAR_INFO_REGISTERED(CHAR_INFO_REGISTERED),
.ALIGN_MUX_REGISTERED(ALIGN_MUX_REGISTERED),
.SCRAMBLER_REGISTERED(SCRAMBLER_REGISTERED),
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE),
.ENABLE_FRAME_ALIGN_CHECK(ENABLE_FRAME_ALIGN_CHECK),
.ENABLE_CHAR_REPLACE(ENABLE_CHAR_REPLACE)
.ENABLE_CHAR_REPLACE(ENABLE_CHAR_REPLACE),
.ASYNC_CLK(ASYNC_CLK)
) i_lane (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_charisk(phy_charisk_r[C_STOP:C_START]),
.phy_notintable(phy_notintable_r[C_STOP:C_START]),
@ -355,7 +405,7 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.ifs_reset(ifs_reset[i]),
.rx_data(rx_data_s[D_STOP:D_START]),
.rx_data(rx_data_s[OD_STOP:OD_START]),
.buffer_release_n(buffer_release_n),
.buffer_ready_n(buffer_ready_n[i]),
@ -452,6 +502,17 @@ end
if (LINK_MODE[1] == 1) begin : mode_64b66b
wire [NUM_LANES-1:0] emb_lock;
wire link_buffer_release_n;
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_buffer_release_cdc (
.in_bits(buffer_release_n),
.out_clk(clk),
.out_resetn(1'b1),
.out_bits(link_buffer_release_n)
);
jesd204_rx_ctrl_64b #(
.NUM_LANES(NUM_LANES)
@ -465,7 +526,7 @@ jesd204_rx_ctrl_64b #(
.emb_lock(emb_lock),
.all_emb_lock(all_emb_lock),
.buffer_release_n(buffer_release_n),
.buffer_release_n(link_buffer_release_n),
.status_state(status_ctrl_state),
.event_unexpected_lane_state_error(event_unexpected_lane_state_error)
@ -475,17 +536,24 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
localparam D_START = i * DATA_PATH_WIDTH*8;
localparam D_STOP = D_START + DATA_PATH_WIDTH*8-1;
localparam TPL_D_START = i * TPL_DATA_PATH_WIDTH*8;
localparam TPL_D_STOP = TPL_D_START + TPL_DATA_PATH_WIDTH*8-1;
localparam H_START = i * 2;
localparam H_STOP = H_START + 2-1;
wire [7:0] status_lane_skew;
jesd204_rx_lane_64b #(
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE)
.ELASTIC_BUFFER_SIZE(ELASTIC_BUFFER_SIZE),
.TPL_DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH),
.ASYNC_CLK(ASYNC_CLK)
) i_lane (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_header(phy_header_r[H_STOP:H_START]),
.phy_block_sync(phy_block_sync_r[i]),
@ -495,13 +563,13 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.cfg_rx_thresh_emb_err(5'd8),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.rx_data(rx_data_s[D_STOP:D_START]),
.rx_data(rx_data_s[TPL_D_STOP:TPL_D_START]),
.buffer_release_n(buffer_release_n),
.buffer_ready_n(buffer_ready_n[i]),
.all_buffer_ready_n(all_buffer_ready_n),
.lmfc_edge(lmfc_edge),
.lmfc_edge(lmfc_edge_synced),
.emb_lock(emb_lock[i]),
.ctrl_err_statistics_reset(ctrl_err_statistics_reset),

View File

@ -47,6 +47,8 @@
<: setFileExtension ".xdc" :>
<: setFileProcessingOrder late :>
<: set sysref_iob [get_property PARAM_VALUE.SYSREF_IOB] :>
<: set async_clk [getBooleanValue "ASYNC_CLK"] :>
<: set link_mode [getBooleanValue "LINK_MODE"] :>
set_property ASYNC_REG TRUE \
[get_cells {i_lmfc/sysref_d1_reg}] \
@ -56,3 +58,42 @@ set_property ASYNC_REG TRUE \
# predictable
set_property IOB <=: $sysref_iob :> \
[get_cells {i_lmfc/sysref_r_reg}]
<: if {$async_clk} { :>
set link_clk [get_clocks -of_objects [get_ports -quiet {clk}]]
set device_clk [get_clocks -of_objects [get_ports -quiet {device_clk}]]
# sync bits
set_false_path \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_all_buffer_ready_cdc* && IS_SEQUENTIAL}]
# sync event i_sync_lmfc
set_false_path -quiet \
-from $device_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_out* && IS_SEQUENTIAL}]
set_false_path -quiet \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_in* && IS_SEQUENTIAL}]
# elastic buffer distributed RAM
set_false_path -quiet \
-from $link_clk \
-to [get_cells -quiet -hier *rd_data_reg* \
-filter {NAME =~ *i_elastic_buffer* && IS_SEQUENTIAL}]
<: if {$link_mode == 2} { :>
# sync bits i_buffer_release_cdc 64b66b
set_false_path \
-from $device_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_buffer_release_cdc* && IS_SEQUENTIAL}]
<: } :>
<: } :>

View File

@ -94,6 +94,7 @@ reg align_err;
reg [DPW_LOG2*2:0] cur_align_err_cnt;
wire [8:0] align_err_cnt_next;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe>>DPW_LOG2;
jesd204_frame_mark #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
@ -101,6 +102,7 @@ jesd204_frame_mark #(
.clk (clk),
.reset (reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_beats_per_multiframe (cfg_beats_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (),
.eof (eof),

View File

@ -61,13 +61,17 @@ adi_ip_files jesd204_rx [list \
"jesd204_rx_frame_align.v" \
"jesd204_rx_constr.ttcl" \
"jesd204_rx.v" \
"../../common/ad_pack.v" \
"bd/bd.tcl"
]
adi_ip_properties_lite jesd204_rx
adi_ip_ttcl jesd204_rx "jesd204_rx_constr.ttcl"
adi_ip_bd jesd204_rx "bd/bd.tcl"
adi_ip_add_core_dependencies { \
analog.com:user:jesd204_common:1.0 \
analog.com:user:util_cdc:1.0 \
}
set_property display_name "ADI JESD204 Receive" [ipx::current_core]
@ -102,16 +106,19 @@ adi_add_bus "rx_cfg" "slave" \
{ "cfg_links_disable" "links_disable" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \
{ "cfg_sysref_disable" "sysref_disable" } \
{ "cfg_buffer_delay" "buffer_delay" } \
{ "cfg_buffer_early_release" "buffer_early_release" } \
{ "cfg_disable_scrambler" "disable_scrambler" } \
{ "cfg_disable_char_replacement" "disable_char_replacement" } \
{ "cfg_frame_align_err_threshold" "frame_align_err_threshold" } \
{ "device_cfg_octets_per_multiframe" "device_octets_per_multiframe" } \
{ "device_cfg_octets_per_frame" "device_octets_per_frame" } \
{ "device_cfg_beats_per_multiframe" "device_beats_per_multiframe" } \
{ "device_cfg_lmfc_offset" "device_lmfc_offset" } \
{ "device_cfg_sysref_oneshot" "device_sysref_oneshot" } \
{ "device_cfg_sysref_disable" "device_sysref_disable" } \
{ "device_cfg_buffer_delay" "device_buffer_delay" } \
{ "device_cfg_buffer_early_release" "device_buffer_early_release" } \
{ "ctrl_err_statistics_reset" "err_statistics_reset" } \
{ "ctrl_err_statistics_mask" "err_statistics_mask" } \
{ "cfg_disable_scrambler" "disable_scrambler" } \
{ "cfg_frame_align_err_threshold" "frame_align_err_threshold" } \
}
adi_add_bus "rx_status" "master" \
@ -140,13 +147,14 @@ adi_add_bus "rx_event" "master" \
"analog.com:interface:jesd204_rx_event_rtl:1.0" \
"analog.com:interface:jesd204_rx_event:1.0" \
{ \
{ "event_sysref_alignment_error" "sysref_alignment_error" } \
{ "event_sysref_edge" "sysref_edge" } \
{ "device_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "device_event_sysref_edge" "sysref_edge" } \
{ "event_frame_alignment_error" "frame_alignment_error" } \
{ "event_unexpected_lane_state_error" "unexpected_lane_state_error" } \
}
adi_add_bus_clock "clk" "rx_cfg:rx_ilas_config:rx_event:rx_status:rx_data" "reset"
adi_add_bus_clock "clk" "rx_cfg:rx_ilas_config:rx_event:rx_status" "reset"
adi_add_bus_clock "device_clk" "rx_data" "device_reset"
adi_set_bus_dependency "rx_ilas_config" "rx_ilas_config" \
"(spirit:decode(id('MODELPARAM_VALUE.LINK_MODE')) = 1)"
@ -198,5 +206,15 @@ set_property -dict [list \
show_label true \
] $param
set clk_group [ipgui::add_group -name {Clock Domain Configuration} -component $cc \
-parent $page0 -display_name {Clock Domain Configuration}]
set p [ipgui::get_guiparamspec -name "ASYNC_CLK" -component $cc]
ipgui::move_param -component $cc -order 0 $p -parent $clk_group
set_property -dict [list \
"display_name" "Link and Device Clock Asynchronous" \
"widget" "checkBox" \
] $p
ipx::create_xgui_files [ipx::current_core]
ipx::save_core [ipx::current_core]

View File

@ -46,16 +46,21 @@
module jesd204_rx_lane #(
parameter DATA_PATH_WIDTH = 4,
parameter TPL_DATA_PATH_WIDTH = 4,
parameter CHAR_INFO_REGISTERED = 0,
parameter ALIGN_MUX_REGISTERED = 0,
parameter SCRAMBLER_REGISTERED = 0,
parameter ELASTIC_BUFFER_SIZE = 256,
parameter ENABLE_FRAME_ALIGN_CHECK = 0,
parameter ENABLE_CHAR_REPLACE = 0
parameter ENABLE_CHAR_REPLACE = 0,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input device_clk,
input device_reset,
input [DATA_PATH_WIDTH*8-1:0] phy_data,
input [DATA_PATH_WIDTH-1:0] phy_charisk,
input [DATA_PATH_WIDTH-1:0] phy_notintable,
@ -66,7 +71,7 @@ module jesd204_rx_lane #(
input ifs_reset,
output [DATA_PATH_WIDTH*8-1:0] rx_data,
output [TPL_DATA_PATH_WIDTH*8-1:0] rx_data,
output buffer_ready_n,
input buffer_release_n,
@ -304,12 +309,17 @@ pipeline_stage #(
);
elastic_buffer #(
.WIDTH(DATA_PATH_WIDTH*8),
.SIZE(ELASTIC_BUFFER_SIZE)
.IWIDTH(DATA_PATH_WIDTH*8),
.OWIDTH(TPL_DATA_PATH_WIDTH*8),
.SIZE(ELASTIC_BUFFER_SIZE),
.ASYNC_CLK(ASYNC_CLK)
) i_elastic_buffer (
.clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.wr_data(data_scrambled),
.rd_data(rx_data),

View File

@ -45,16 +45,21 @@
`timescale 1ns/100ps
module jesd204_rx_lane_64b #(
parameter ELASTIC_BUFFER_SIZE = 256
parameter ELASTIC_BUFFER_SIZE = 256,
parameter TPL_DATA_PATH_WIDTH = 8,
parameter ASYNC_CLK = 0
) (
input clk,
input reset,
input device_clk,
input device_reset,
input [63:0] phy_data,
input [1:0] phy_header,
input phy_block_sync,
output [63:0] rx_data,
output [TPL_DATA_PATH_WIDTH*8-1:0] rx_data,
output reg buffer_ready_n = 'b1,
input all_buffer_ready_n,
@ -80,6 +85,7 @@ reg [11:0] crc12_calculated_prev;
wire [63:0] data_descrambled_s;
wire [63:0] data_descrambled;
wire [63:0] data_descrambled_reordered;
wire [11:0] crc12_received;
wire [11:0] crc12_calculated;
@ -108,7 +114,7 @@ jesd204_rx_header i_rx_header (
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.emb_lock(emb_lock),
.valid_eomb(eomb),
.valid_eoemb(eoemb),
.crc12(crc12_received),
@ -217,14 +223,19 @@ end
elastic_buffer #(
.WIDTH(64),
.SIZE(ELASTIC_BUFFER_SIZE)
.IWIDTH(64),
.OWIDTH(TPL_DATA_PATH_WIDTH*8),
.SIZE(ELASTIC_BUFFER_SIZE),
.ASYNC_CLK(ASYNC_CLK)
) i_elastic_buffer (
.clk(clk),
.reset(reset),
.wr_data(data_descrambled),
.rd_data(rx_data_msb_s),
.device_clk(device_clk),
.device_reset(device_reset),
.wr_data(data_descrambled_reordered),
.rd_data(rx_data),
.ready_n(buffer_ready_n),
.do_release_n(buffer_release_n)
@ -242,7 +253,7 @@ end
genvar i;
generate
for (i = 0; i < 64; i = i + 8) begin: g_link_data
assign rx_data[i+:8] = rx_data_msb_s[64-1-i-:8];
assign data_descrambled_reordered[i+:8] = data_descrambled[64-1-i-:8];
end
endgenerate

View File

@ -24,6 +24,7 @@ XILINX_DEPS += ../../jesd204/interfaces/jesd204_tx_ilas_config.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_tx_ilas_config_rtl.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_tx_status.xml
XILINX_DEPS += ../../jesd204/interfaces/jesd204_tx_status_rtl.xml
XILINX_DEPS += bd/bd.tcl
XILINX_LIB_DEPS += jesd204/jesd204_common
XILINX_LIB_DEPS += util_cdc

View File

@ -0,0 +1,44 @@
proc init {cellpath otherInfo} {
set ip [get_bd_cells $cellpath]
bd::mark_propagate_override $ip \
"ASYNC_CLK"
}
proc detect_async_clk { cellpath ip param_name clk_a clk_b } {
set param_src [get_property "CONFIG.$param_name.VALUE_SRC" $ip]
if {[string equal $param_src "USER"]} {
return;
}
set clk_domain_a [get_property CONFIG.CLK_DOMAIN $clk_a]
set clk_domain_b [get_property CONFIG.CLK_DOMAIN $clk_b]
set clk_freq_a [get_property CONFIG.FREQ_HZ $clk_a]
set clk_freq_b [get_property CONFIG.FREQ_HZ $clk_b]
set clk_phase_a [get_property CONFIG.PHASE $clk_a]
set clk_phase_b [get_property CONFIG.PHASE $clk_b]
# Only mark it as sync if we can make sure that it is sync, if the
# relationship of the clocks is unknown mark it as async
if {$clk_domain_a != {} && $clk_domain_b != {} && \
$clk_domain_a == $clk_domain_b && $clk_freq_a == $clk_freq_b && \
$clk_phase_a == $clk_phase_b} {
set clk_async 0
} else {
set clk_async 1
}
set_property "CONFIG.$param_name" $clk_async $ip
}
proc propagate {cellpath otherinfo} {
set ip [get_bd_cells $cellpath]
set link_clk [get_bd_pins "$ip/clk"]
set device_clk [get_bd_pins "$ip/device_clk"]
detect_async_clk $cellpath $ip "ASYNC_CLK" $link_clk $device_clk
}

View File

@ -51,11 +51,16 @@ module jesd204_tx #(
parameter LINK_MODE = 1, // 2 - 64B/66B; 1 - 8B/10B
/* Only 4 is supported at the moment for 8b/10b and 8 for 64b */
parameter DATA_PATH_WIDTH = LINK_MODE[1] ? 8 : 4,
parameter ENABLE_CHAR_REPLACE = 1'b0
parameter TPL_DATA_PATH_WIDTH = LINK_MODE[1] ? 8 : 4,
parameter ENABLE_CHAR_REPLACE = 1'b0,
parameter ASYNC_CLK = 1
) (
input clk,
input reset,
input device_clk,
input device_reset,
output [DATA_PATH_WIDTH*8*NUM_LANES-1:0] phy_data,
output [DATA_PATH_WIDTH*NUM_LANES-1:0] phy_charisk,
output [2*NUM_LANES-1:0] phy_header,
@ -66,21 +71,18 @@ module jesd204_tx #(
input [NUM_LINKS-1:0] sync,
input [DATA_PATH_WIDTH*8*NUM_LANES-1:0] tx_data,
input [TPL_DATA_PATH_WIDTH*8*NUM_LANES-1:0] tx_data,
output tx_ready,
output [DATA_PATH_WIDTH-1:0] tx_eof,
output [DATA_PATH_WIDTH-1:0] tx_sof,
output [DATA_PATH_WIDTH-1:0] tx_somf,
output [DATA_PATH_WIDTH-1:0] tx_eomf,
output [TPL_DATA_PATH_WIDTH-1:0] tx_eof,
output [TPL_DATA_PATH_WIDTH-1:0] tx_sof,
output [TPL_DATA_PATH_WIDTH-1:0] tx_somf,
output [TPL_DATA_PATH_WIDTH-1:0] tx_eomf,
input tx_valid,
input [NUM_LANES-1:0] cfg_lanes_disable,
input [NUM_LINKS-1:0] cfg_links_disable,
input [9:0] cfg_octets_per_multiframe,
input [7:0] cfg_octets_per_frame,
input [7:0] cfg_lmfc_offset,
input cfg_sysref_oneshot,
input cfg_sysref_disable,
input cfg_continuous_cgs,
input cfg_continuous_ilas,
input cfg_skip_ilas,
@ -88,14 +90,21 @@ module jesd204_tx #(
input cfg_disable_char_replacement,
input cfg_disable_scrambler,
input [9:0] device_cfg_octets_per_multiframe,
input [7:0] device_cfg_octets_per_frame,
input [7:0] device_cfg_beats_per_multiframe,
input [7:0] device_cfg_lmfc_offset,
input device_cfg_sysref_oneshot,
input device_cfg_sysref_disable,
output ilas_config_rd,
output [1:0] ilas_config_addr,
input [NUM_LANES*DATA_PATH_WIDTH*8-1:0] ilas_config_data,
input ctrl_manual_sync_request,
output event_sysref_edge,
output event_sysref_alignment_error,
output device_event_sysref_edge,
output device_event_sysref_alignment_error,
output [NUM_LINKS-1:0] status_sync,
output [1:0] status_state
@ -107,6 +116,8 @@ 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 DPW_LOG2 = DATA_PATH_WIDTH == 8 ? 3 : DATA_PATH_WIDTH == 4 ? 2 : 1;
localparam LMFC_COUNTER_WIDTH = MAX_BEATS_PER_MULTIFRAME > 256 ? 9 :
MAX_BEATS_PER_MULTIFRAME > 128 ? 8 :
MAX_BEATS_PER_MULTIFRAME > 64 ? 7 :
@ -140,35 +151,191 @@ reg [DATA_PATH_WIDTH-1:0] tx_sof_fm_d2;
reg [DATA_PATH_WIDTH-1:0] tx_eof_fm_d2;
reg [DATA_PATH_WIDTH-1:0] tx_somf_fm_d2;
reg [DATA_PATH_WIDTH-1:0] tx_eomf_fm_d2;
wire lmfc_edge_synced;
wire lmc_edge;
wire lmc_quarter_edge;
wire eoemb;
wire [DATA_PATH_WIDTH*8*NUM_LANES-1:0] gearbox_data;
wire tx_ready_nx;
wire link_lmfc_edge;
wire link_lmfc_clk;
wire device_lmfc_edge;
wire device_lmfc_clk;
wire device_lmc_edge;
wire device_lmc_quarter_edge;
wire device_eoemb;
wire tx_next_mf_ready;
wire link_tx_ready;
wire [7:0] cfg_beats_per_multiframe = cfg_octets_per_multiframe >> DPW_LOG2;
wire [7:0] device_cfg_beats_per_multiframe_s;
// If input and output widths are symmetric keep the calculation for backwards
// compatibility of the software.
assign device_cfg_beats_per_multiframe_s = (TPL_DATA_PATH_WIDTH == DATA_PATH_WIDTH) ?
device_cfg_octets_per_multiframe >> DPW_LOG2 :
device_cfg_beats_per_multiframe;
jesd204_lmfc #(
.LINK_MODE(LINK_MODE),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
.DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH)
) i_lmfc (
.clk(clk),
.reset(reset),
.clk(device_clk),
.reset(device_reset),
.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),
.cfg_octets_per_multiframe(device_cfg_octets_per_multiframe),
.cfg_lmfc_offset(device_cfg_lmfc_offset),
.cfg_beats_per_multiframe(device_cfg_beats_per_multiframe_s),
.cfg_sysref_oneshot(device_cfg_sysref_oneshot),
.cfg_sysref_disable(device_cfg_sysref_disable),
.sysref(sysref),
.sysref_edge(event_sysref_edge),
.sysref_alignment_error(event_sysref_alignment_error),
.sysref_edge(device_event_sysref_edge),
.sysref_alignment_error(device_event_sysref_alignment_error),
.lmfc_edge(lmfc_edge),
.lmfc_clk(lmfc_clk),
.lmfc_edge(device_lmfc_edge),
.lmfc_clk(device_lmfc_clk),
.lmfc_counter(),
.lmc_edge(lmc_edge),
.lmc_quarter_edge(lmc_quarter_edge),
.eoemb(eoemb)
.lmc_edge(device_lmc_edge),
.lmc_quarter_edge(device_lmc_quarter_edge),
.eoemb(device_eoemb)
);
generate
if (ASYNC_CLK) begin : dual_lmfc_mode
reg link_lmfc_reset = 1'b1;
reg device_lmfc_edge_d1 = 1'b0;
reg device_tx_ready = 1'b0;
jesd204_lmfc #(
.LINK_MODE(LINK_MODE),
.DATA_PATH_WIDTH(DATA_PATH_WIDTH)
) i_link_lmfc (
.clk(clk),
.reset(link_lmfc_reset),
.cfg_octets_per_multiframe(cfg_octets_per_multiframe),
.cfg_lmfc_offset('h0),
.cfg_beats_per_multiframe(cfg_beats_per_multiframe),
.cfg_sysref_oneshot(1'b0),
.cfg_sysref_disable(1'b1),
.sysref(sysref),
.sysref_edge(),
.sysref_alignment_error(),
.lmfc_edge(link_lmfc_edge),
.lmfc_clk(link_lmfc_clk),
.lmfc_counter(),
.lmc_edge(lmc_edge),
.lmc_quarter_edge(lmc_quarter_edge),
.eoemb(eoemb)
);
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_link_reset_done_cdc (
.in_bits(~reset),
.out_clk(device_clk),
.out_resetn(~device_reset),
.out_bits(link_reset_n)
);
sync_event #(
.NUM_OF_EVENTS (1)
) i_sync_lmfc (
.in_clk(device_clk),
.in_event(device_lmfc_edge & link_reset_n),
.out_clk(clk),
.out_event(lmfc_edge_synced)
);
always @(posedge clk) begin
if (reset) begin
link_lmfc_reset <= 1'b1;
end else if (lmfc_edge_synced) begin
link_lmfc_reset <= 1'b0;
end
end
jesd204_tx_gearbox #(
.IN_DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH),
.OUT_DATA_PATH_WIDTH(DATA_PATH_WIDTH),
.NUM_LANES(NUM_LANES),
.DEPTH(8)
) i_tx_gearbox(
.link_clk(clk),
.reset(reset),
.device_clk(device_clk),
.device_reset(device_reset),
.device_data(tx_data),
.device_lmfc_edge(device_lmfc_edge_d1),
.link_data(gearbox_data),
.output_ready(tx_ready_nx)
);
always @(posedge device_clk) begin
device_lmfc_edge_d1 <= device_lmfc_edge;
end
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK(ASYNC_CLK)
) i_next_mf_ready_cdc (
.in_bits(tx_next_mf_ready),
.out_clk(device_clk),
.out_resetn(1'b1),
.out_bits(device_tx_next_mf_ready)
);
always @(posedge device_clk) begin
if (device_reset) begin
device_tx_ready <= 1'b0;
end else if (device_lmfc_edge & device_tx_next_mf_ready) begin
device_tx_ready <= 1'b1;
end
end
jesd204_frame_mark #(
.DATA_PATH_WIDTH(TPL_DATA_PATH_WIDTH)
) i_device_frame_mark (
.clk(device_clk),
.reset(~device_tx_ready),
.cfg_octets_per_multiframe(device_cfg_octets_per_multiframe),
.cfg_beats_per_multiframe(device_cfg_beats_per_multiframe_s),
.cfg_octets_per_frame(device_cfg_octets_per_frame),
.sof(tx_sof),
.eof(tx_eof),
.somf(tx_somf),
.eomf(tx_eomf)
);
assign tx_ready = device_tx_ready;
end else begin
assign link_lmfc_edge = device_lmfc_edge;
assign link_lmfc_clk = device_lmfc_clk;
assign lmc_edge = device_lmc_edge;
assign lmc_quarter_edge = device_lmc_quarter_edge;
assign eoemb = device_eoemb;
assign gearbox_data = tx_data;
assign tx_sof = (LINK_MODE == 1) ? tx_sof_fm_d2 : tx_sof_fm;
assign tx_eof = (LINK_MODE == 1) ? tx_eof_fm_d2 : tx_eof_fm;
assign tx_somf = (LINK_MODE == 1) ? tx_somf_fm_d2 : tx_somf_fm;
assign tx_eomf = (LINK_MODE == 1) ? tx_eomf_fm_d2 : tx_eomf_fm;
assign tx_ready = link_tx_ready;
end
endgenerate
assign lmfc_edge = device_lmfc_edge;
assign lmfc_clk = device_lmfc_clk;
assign frame_mark_reset = (LINK_MODE == 1) ? eof_gen_reset : ~tx_ready_64b_next;
jesd204_frame_mark #(
@ -177,6 +344,7 @@ jesd204_frame_mark #(
.clk (clk),
.reset (frame_mark_reset),
.cfg_octets_per_multiframe (cfg_octets_per_multiframe),
.cfg_beats_per_multiframe (cfg_beats_per_multiframe),
.cfg_octets_per_frame (cfg_octets_per_frame),
.sof (tx_sof_fm),
.eof (tx_eof_fm),
@ -195,11 +363,6 @@ always @(posedge clk) begin
tx_eomf_fm_d2 <= tx_eomf_fm_d1;
end
assign tx_sof = (LINK_MODE == 1) ? tx_sof_fm_d2 : tx_sof_fm;
assign tx_eof = (LINK_MODE == 1) ? tx_eof_fm_d2 : tx_eof_fm;
assign tx_somf = (LINK_MODE == 1) ? tx_somf_fm_d2 : tx_somf_fm;
assign tx_eomf = (LINK_MODE == 1) ? tx_eomf_fm_d2 : tx_eomf_fm;
generate
genvar i;
@ -227,7 +390,7 @@ jesd204_tx_ctrl #(
.reset(reset),
.sync(sync),
.lmfc_edge(lmfc_edge),
.lmfc_edge(link_lmfc_edge),
.somf(tx_somf_fm_d2),
.somf_early2(tx_somf_fm),
.eomf(tx_eomf_fm_d2),
@ -235,7 +398,9 @@ jesd204_tx_ctrl #(
.lane_cgs_enable(lane_cgs_enable),
.eof_reset(eof_gen_reset),
.tx_ready(tx_ready),
.tx_ready(link_tx_ready),
.tx_ready_nx(tx_ready_nx),
.tx_next_mf_ready(tx_next_mf_ready),
.ilas_data(ilas_data),
.ilas_charisk(ilas_charisk),
@ -278,8 +443,8 @@ for (i = 0; i < NUM_LANES; i = i + 1) begin: gen_lane
.ilas_data(ilas_data[D_STOP:D_START]),
.ilas_charisk(ilas_charisk[C_STOP:C_START]),
.tx_data(tx_data[D_STOP:D_START]),
.tx_ready(tx_ready),
.tx_data(gearbox_data[D_STOP:D_START]),
.tx_ready(link_tx_ready),
.phy_data(phy_data_r[D_STOP:D_START]),
.phy_charisk(phy_charisk_r[C_STOP:C_START]),
@ -305,7 +470,7 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b
.clk(clk),
.reset(reset),
.tx_data(tx_data[D_STOP:D_START]),
.tx_data(gearbox_data[D_STOP:D_START]),
.tx_ready(tx_ready_64b),
.phy_data(phy_data_r[D_STOP:D_START]),
@ -321,7 +486,7 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b
);
end
assign tx_ready_64b_next = reset ? 1'b0 : (lmfc_edge || tx_ready_64b);
assign tx_ready_64b_next = reset ? 1'b0 : (link_lmfc_edge || tx_ready_64b);
always @(posedge clk) begin
if (reset) begin
@ -331,7 +496,10 @@ if (LINK_MODE[1] == 1) begin : mode_64b66b
end
end
assign tx_ready = tx_ready_64b;
assign tx_ready_nx = tx_ready_64b_next;
assign tx_next_mf_ready = 1'b1;
assign link_tx_ready = tx_ready_64b;
// Link considered in DATA phase when SYSREF received and LEMC clock started
// running
assign status_state = {2{tx_ready_64b}};

View File

@ -47,6 +47,7 @@
<: setFileExtension ".xdc" :>
<: setFileProcessingOrder late :>
<: set sysref_iob [get_property PARAM_VALUE.SYSREF_IOB] :>
<: set async_clk [getBooleanValue "ASYNC_CLK"] :>
set_property ASYNC_REG TRUE \
[get_cells {i_lmfc/sysref_d1_reg}] \
@ -56,3 +57,45 @@ set_property ASYNC_REG TRUE \
# predictable
set_property IOB <=: $sysref_iob :> \
[get_cells {i_lmfc/sysref_r_reg}]
<: if {$async_clk} { :>
set link_clk [get_clocks -of_objects [get_ports -quiet {clk}]]
set device_clk [get_clocks -of_objects [get_ports -quiet {device_clk}]]
# sync event i_sync_lmfc
set_false_path -quiet \
-from $device_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_out* && IS_SEQUENTIAL}]
set_false_path -quiet \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_lmfc/i_sync_in* && IS_SEQUENTIAL}]
# sync bits i_next_mf_ready_cdc
set_false_path \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_next_mf_ready_cdc* && IS_SEQUENTIAL}]
# sync bits i_link_reset_done_cdc
set_false_path \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_link_reset_done_cdc* && IS_SEQUENTIAL}]
# sync bits gearbox/i_sync_ready
set_false_path \
-from $link_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_ready* && IS_SEQUENTIAL}]
# gearbox distributed RAM
set_false_path -quiet \
-from $device_clk \
-to [get_cells -quiet -hier *mem_rd_data_reg* \
-filter {NAME =~ *i_tx_gearbox* && IS_SEQUENTIAL}]
<: } :>

View File

@ -62,6 +62,8 @@ module jesd204_tx_ctrl #(
output reg eof_reset,
output reg tx_ready,
output tx_ready_nx,
output tx_next_mf_ready,
output reg [DATA_PATH_WIDTH*8*NUM_LANES-1:0] ilas_data,
output reg [DATA_PATH_WIDTH*NUM_LANES-1:0] ilas_charisk,
@ -102,11 +104,11 @@ reg ilas_reset = 1'b1;
reg ilas_data_reset = 1'b1;
reg sync_request = 1'b0;
reg sync_request_received = 1'b0;
reg last_ilas_mframe = 1'b0;
reg [7:0] mframe_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;
@ -123,6 +125,7 @@ i_cdc_sync (
.out_resetn(1'b1),
.out_bits(status_sync)
);
assign status_sync_masked = status_sync | cfg_links_disable;
always @(posedge clk) begin
@ -235,6 +238,9 @@ always @(posedge clk) begin
end
end
assign tx_next_mf_ready = sync_request_received & last_ilas_mframe & ~cfg_continuous_ilas;
assign tx_ready_nx = tx_ready | (tx_next_mf_ready & lmfc_edge_d2);
always @(posedge clk) begin
if (ilas_reset == 1'b1) begin
mframe_counter <= 'h00;

View File

@ -0,0 +1,144 @@
//
// The ADI JESD204 Core is released under the following license, which is
// different than all other HDL cores in this repository.
//
// Please read this, and understand the freedoms and responsibilities you have
// by using this source code/core.
//
// The JESD204 HDL, is copyright © 2016-2017 Analog Devices Inc.
//
// This core is free software, you can use run, copy, study, change, ask
// questions about and improve this core. Distribution of source, or resulting
// binaries (including those inside an FPGA or ASIC) require you to release the
// source of the entire project (excluding the system libraries provide by the
// tools/compiler/FPGA vendor). These are the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// This core is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License version 2
// along with this source code, and binary. If not, see
// <http://www.gnu.org/licenses/>.
//
// Commercial licenses (with commercial support) of this JESD204 core are also
// available under terms different than the General Public License. (e.g. they
// do not require you to accompany any image (FPGA or ASIC) using the JESD204
// core with any corresponding source code.) For these alternate terms you must
// purchase a license from Analog Devices Technology Licensing Office. Users
// interested in such a license should contact jesd204-licensing@analog.com for
// more information. This commercial license is sub-licensable (if you purchase
// chips from Analog Devices, incorporate them into your PCB level product, and
// purchase a JESD204 license, end users of your product will also have a
// license to use this core in a commercial setting without releasing their
// source code).
//
// In addition, we kindly ask you to acknowledge ADI in any program, application
// or publication in which you use this JESD204 HDL core. (You are not required
// to do so; it is up to your common sense to decide whether you want to comply
// with this request or not.) For general publications, we suggest referencing :
// The design and implementation of the JESD204 HDL Core used in this project
// is copyright © 2016-2017, Analog Devices, Inc.
//
`timescale 1ns/100ps
// Constraints:
// - IN_DATA_PATH_WIDTH >= OUT_DATA_PATH_WIDTH
//
module jesd204_tx_gearbox #(
parameter IN_DATA_PATH_WIDTH = 6,
parameter OUT_DATA_PATH_WIDTH = 4,
parameter NUM_LANES = 1,
parameter DEPTH = 16
) (
input link_clk,
input reset,
input device_clk,
input device_reset,
input [NUM_LANES*IN_DATA_PATH_WIDTH*8-1:0] device_data,
input device_lmfc_edge,
output [NUM_LANES*OUT_DATA_PATH_WIDTH*8-1:0] link_data,
input output_ready
);
localparam MEM_W = IN_DATA_PATH_WIDTH*8*NUM_LANES;
localparam D_LOG2 = $clog2(DEPTH);
reg [MEM_W-1:0] mem [0:DEPTH-1];
reg [D_LOG2-1:0] in_addr ='h00;
reg [D_LOG2-1:0] out_addr = 'b0;
reg mem_rd_valid = 'b0;
reg [MEM_W-1:0] mem_rd_data;
wire mem_wr_en = 1'b1;
wire mem_rd_en;
wire [D_LOG2-1:0] in_out_addr;
wire [D_LOG2-1:0] out_in_addr;
wire [NUM_LANES-1:0] unpacker_ready;
wire output_ready_sync;
sync_bits i_sync_ready (
.in_bits(output_ready),
.out_resetn(~device_reset),
.out_clk(device_clk),
.out_bits(output_ready_sync)
);
always @(posedge device_clk) begin
if (device_lmfc_edge & ~output_ready_sync) begin
in_addr <= 'h01;
end else if (mem_wr_en) begin
in_addr <= in_addr + 1;
end
end
always @(posedge device_clk) begin
if (mem_wr_en) begin
mem[in_addr] <= device_data;
end
end
assign mem_rd_en = output_ready&unpacker_ready[0];
always @(posedge link_clk) begin
if (mem_rd_en) begin
mem_rd_data <= mem[out_addr];
end
mem_rd_valid <= mem_rd_en;
end
always @(posedge link_clk) begin
if (reset) begin
out_addr <= 'b0;
end else if (mem_rd_en) begin
out_addr <= out_addr + 1;
end
end
genvar i;
generate for (i = 0; i < NUM_LANES; i=i+1) begin: unpacker
ad_upack #(
.I_W(IN_DATA_PATH_WIDTH),
.O_W(OUT_DATA_PATH_WIDTH),
.UNIT_W(8),
.O_REG(0)
) i_ad_upack (
.clk(link_clk),
.reset(reset),
.idata(mem_rd_data[i*IN_DATA_PATH_WIDTH*8+:IN_DATA_PATH_WIDTH*8]),
.ivalid(mem_rd_valid),
.iready(unpacker_ready[i]),
.odata(link_data[i*OUT_DATA_PATH_WIDTH*8+:OUT_DATA_PATH_WIDTH*8]),
.ovalid()
);
end
endgenerate
endmodule

View File

@ -50,13 +50,17 @@ adi_ip_files jesd204_tx [list \
"jesd204_tx_lane.v" \
"jesd204_tx_lane_64b.v" \
"jesd204_tx_header.v" \
"jesd204_tx_gearbox.v" \
"jesd204_tx_ctrl.v" \
"jesd204_tx_constr.ttcl" \
"jesd204_tx.v"
"../../common/ad_upack.v" \
"jesd204_tx.v" \
"bd/bd.tcl"
]
adi_ip_properties_lite jesd204_tx
adi_ip_ttcl jesd204_tx "jesd204_tx_constr.ttcl"
adi_ip_bd jesd204_tx "bd/bd.tcl"
adi_ip_add_core_dependencies { \
analog.com:user:jesd204_common:1.0 \
@ -93,15 +97,18 @@ adi_add_bus "tx_cfg" "slave" \
{ "cfg_links_disable" "links_disable" } \
{ "cfg_octets_per_multiframe" "octets_per_multiframe" } \
{ "cfg_octets_per_frame" "octets_per_frame" } \
{ "cfg_lmfc_offset" "lmfc_offset" } \
{ "cfg_sysref_oneshot" "sysref_oneshot" } \
{ "cfg_sysref_disable" "sysref_disable" } \
{ "cfg_continuous_cgs" "continuous_cgs" } \
{ "cfg_continuous_ilas" "continuous_ilas" } \
{ "cfg_skip_ilas" "skip_ilas" } \
{ "cfg_mframes_per_ilas" "mframes_per_ilas" } \
{ "cfg_disable_char_replacement" "disable_char_replacement" } \
{ "cfg_disable_scrambler" "disable_scrambler" } \
{ "device_cfg_octets_per_multiframe" "device_octets_per_multiframe" } \
{ "device_cfg_octets_per_frame" "device_octets_per_frame" } \
{ "device_cfg_beats_per_multiframe" "device_beats_per_multiframe" } \
{ "device_cfg_lmfc_offset" "device_lmfc_offset" } \
{ "device_cfg_sysref_oneshot" "device_sysref_oneshot" } \
{ "device_cfg_sysref_disable" "device_sysref_disable" } \
}
adi_add_bus "tx_ilas_config" "master" \
@ -117,8 +124,8 @@ adi_add_bus "tx_event" "master" \
"analog.com:interface:jesd204_tx_event_rtl:1.0" \
"analog.com:interface:jesd204_tx_event:1.0" \
{ \
{ "event_sysref_alignment_error" "sysref_alignment_error" } \
{ "event_sysref_edge" "sysref_edge" } \
{ "device_event_sysref_alignment_error" "sysref_alignment_error" } \
{ "device_event_sysref_edge" "sysref_edge" } \
}
adi_add_bus "tx_status" "master" \
@ -136,8 +143,9 @@ adi_add_bus "tx_ctrl" "slave" \
{ "ctrl_manual_sync_request" "manual_sync_request" } \
}
adi_add_bus_clock "clk" "tx_data:tx_cfg:tx_ilas_config:tx_event:tx_status:tx_ctrl" \
"reset"
adi_add_bus_clock "clk" "tx_cfg:tx_ilas_config:tx_event:tx_status:tx_ctrl" "reset"
adi_add_bus_clock "device_clk" "tx_data" "device_reset"
adi_set_bus_dependency "tx_ilas_config" "tx_ilas_config" \
"(spirit:decode(id('MODELPARAM_VALUE.LINK_MODE')) = 1)"
@ -186,5 +194,16 @@ set_property -dict [list \
show_label true \
] $param
set clk_group [ipgui::add_group -name {Clock Domain Configuration} -component $cc \
-parent $page0 -display_name {Clock Domain Configuration}]
set p [ipgui::get_guiparamspec -name "ASYNC_CLK" -component $cc]
ipgui::move_param -component $cc -order 0 $p -parent $clk_group
set_property -dict [list \
"display_name" "Link and Device Clock Asynchronous" \
"widget" "checkBox" \
] $p
ipx::create_xgui_files [ipx::current_core]
ipx::save_core [ipx::current_core]

View File

@ -69,6 +69,7 @@ proc adi_axi_jesd204_tx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
ad_ip_parameter "${ip_name}/tx" CONFIG.LINK_MODE $link_mode
ad_connect "${ip_name}/tx_axi/core_reset" "${ip_name}/tx/reset"
ad_connect "${ip_name}/tx_axi/device_reset" "${ip_name}/tx/device_reset"
if {$link_mode == 1} {ad_connect "${ip_name}/tx_axi/tx_ctrl" "${ip_name}/tx/tx_ctrl"}
ad_connect "${ip_name}/tx_axi/tx_cfg" "${ip_name}/tx/tx_cfg"
ad_connect "${ip_name}/tx/tx_event" "${ip_name}/tx_axi/tx_event"
@ -87,14 +88,17 @@ proc adi_axi_jesd204_tx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
ad_connect "${ip_name}/tx_axi/irq" "${ip_name}/irq"
# JESD204 processing
create_bd_pin -dir I -type clk "${ip_name}/link_clk"
create_bd_pin -dir I -type clk "${ip_name}/device_clk"
if {$link_mode == 1} {create_bd_pin -dir I -from [expr $num_links - 1] -to 0 "${ip_name}/sync"}
create_bd_pin -dir I "${ip_name}/sysref"
create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:axis_rtl:1.0 "${ip_name}/tx_data"
ad_connect "${ip_name}/device_clk" "${ip_name}/tx_axi/core_clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/tx/clk"
ad_connect "${ip_name}/link_clk" "${ip_name}/tx_axi/core_clk"
ad_connect "${ip_name}/link_clk" "${ip_name}/tx/clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/tx_axi/device_clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/tx/device_clk"
if {$link_mode == 1} {ad_connect "${ip_name}/sync" "${ip_name}/tx/sync"}
ad_connect "${ip_name}/sysref" "${ip_name}/tx/sysref"
ad_connect "${ip_name}/tx_data" "${ip_name}/tx/tx_data"
@ -143,6 +147,7 @@ proc adi_axi_jesd204_rx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
ad_ip_parameter "${ip_name}/rx" CONFIG.LINK_MODE $link_mode
ad_connect "${ip_name}/rx_axi/core_reset" "${ip_name}/rx/reset"
ad_connect "${ip_name}/rx_axi/device_reset" "${ip_name}/rx/device_reset"
ad_connect "${ip_name}/rx_axi/rx_cfg" "${ip_name}/rx/rx_cfg"
ad_connect "${ip_name}/rx/rx_event" "${ip_name}/rx_axi/rx_event"
ad_connect "${ip_name}/rx/rx_status" "${ip_name}/rx_axi/rx_status"
@ -160,6 +165,7 @@ proc adi_axi_jesd204_rx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
ad_connect "${ip_name}/rx_axi/irq" "${ip_name}/irq"
# JESD204 processing
create_bd_pin -dir I -type clk "${ip_name}/link_clk"
create_bd_pin -dir I -type clk "${ip_name}/device_clk"
if {$link_mode == 1} {create_bd_pin -dir O -from [expr $num_links - 1] -to 0 "${ip_name}/sync"}
create_bd_pin -dir I "${ip_name}/sysref"
@ -172,8 +178,10 @@ proc adi_axi_jesd204_rx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
create_bd_pin -dir O "${ip_name}/rx_data_tvalid"
create_bd_pin -dir O -from [expr $num_lanes * 32 - 1] -to 0 "${ip_name}/rx_data_tdata"
ad_connect "${ip_name}/device_clk" "${ip_name}/rx_axi/core_clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/rx/clk"
ad_connect "${ip_name}/link_clk" "${ip_name}/rx_axi/core_clk"
ad_connect "${ip_name}/link_clk" "${ip_name}/rx/clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/rx_axi/device_clk"
ad_connect "${ip_name}/device_clk" "${ip_name}/rx/device_clk"
if {$link_mode == 1} {ad_connect "${ip_name}/rx/sync" "${ip_name}/sync"}
ad_connect "${ip_name}/sysref" "${ip_name}/rx/sysref"
# ad_connect "${ip_name}/phy_ready" "${ip_name}/rx/phy_ready"
@ -204,7 +212,7 @@ proc adi_axi_jesd204_rx_create {ip_name num_lanes {num_links 1} {link_mode 1}} {
# L M S N & NP
proc adi_tpl_jesd204_tx_create {ip_name num_of_lanes num_of_converters samples_per_frame sample_width {link_layer_bytes_per_beat 4}} {
proc adi_tpl_jesd204_tx_create {ip_name num_of_lanes num_of_converters samples_per_frame sample_width {link_layer_bytes_per_beat 4} {dma_sample_width 16}} {
if {$num_of_lanes < 1 || $num_of_lanes > 16} {
@ -250,6 +258,7 @@ proc adi_tpl_jesd204_tx_create {ip_name num_of_lanes num_of_converters samples_p
CONVERTER_RESOLUTION $sample_width \
BITS_PER_SAMPLE $sample_width \
OCTETS_PER_BEAT $tpl_bytes_per_beat \
DMA_BITS_PER_SAMPLE $dma_sample_width
]
if {$num_of_converters > 1} {
@ -332,7 +341,7 @@ proc adi_tpl_jesd204_tx_create {ip_name num_of_lanes num_of_converters samples_p
# L M S N & NP
proc adi_tpl_jesd204_rx_create {ip_name num_of_lanes num_of_converters samples_per_frame sample_width {link_layer_bytes_per_beat 4}} {
proc adi_tpl_jesd204_rx_create {ip_name num_of_lanes num_of_converters samples_per_frame sample_width {link_layer_bytes_per_beat 4} {dma_sample_width 16}} {
if {$num_of_lanes < 1 || $num_of_lanes > 16} {
@ -381,15 +390,16 @@ proc adi_tpl_jesd204_rx_create {ip_name num_of_lanes num_of_converters samples_p
CONVERTER_RESOLUTION $sample_width \
BITS_PER_SAMPLE $sample_width \
OCTETS_PER_BEAT $tpl_bytes_per_beat \
DMA_BITS_PER_SAMPLE $dma_sample_width
]
if {$num_of_converters > 1} {
# Slicer cores
for {set i 0} {$i < $num_of_converters} {incr i} {
ad_ip_instance xlslice ${ip_name}/data_slice_$i [list \
DIN_WIDTH [expr $sample_width*$samples_per_channel*$num_of_converters] \
DIN_FROM [expr $sample_width*$samples_per_channel*($i+1)-1] \
DIN_TO [expr $sample_width*$samples_per_channel*$i] \
DIN_WIDTH [expr $dma_sample_width*$samples_per_channel*$num_of_converters] \
DIN_FROM [expr $dma_sample_width*$samples_per_channel*($i+1)-1] \
DIN_TO [expr $dma_sample_width*$samples_per_channel*$i] \
]
ad_ip_instance xlslice "${ip_name}/enable_slice_${i}" [list \

View File

@ -180,12 +180,16 @@ proc ad_disconnect {p_name_1 p_name_2} {
# \param[a_jesd] - name of the JESD204 link IP
# \param[lane_map] - lane_map maps the logical lane $n onto the physical lane
# $lane_map[$n], otherwise logical lane $n is mapped onto physical lane $n.
# \param[device_clk] - define a custom device clock, should be a net name
# \param[link_clk] - define a custom link clock, should be a net name
# connected to the clock source. If not used, the rx|tx_clk_out_0 is used as
# link clock. This should be lane rate / (encoder_ratio*datapath width in bits)
# where encoder_ratio is 10/8 for 8b10b encoding or 66/64 for 64b66b link layer.
# \param[device_clk] - define a custom device clock, should be a net name
# connected to the clock source. If not used, the link_clk is used as
# device clock
#
proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {device_clk {}}} {
proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {link_clk {}} {device_clk {}}} {
global xcvr_index
global xcvr_tx_index
@ -244,10 +248,18 @@ proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {device_clk {}}} {
create_bd_port -dir I $m_sysref
create_bd_port -from [expr $num_of_links - 1] -to 0 -dir ${ctrl_dir} $m_sync
if {$device_clk == {}} {
set device_clk ${u_xcvr}/${txrx}_out_clk_${index}
if {$link_clk == {}} {
set link_clk ${u_xcvr}/${txrx}_out_clk_${index}
set rst_gen [regsub -all "/" ${a_jesd}_rstgen "_"]
set create_rst_gen 1
} else {
set rst_gen ${link_clk}_rstgen
# Only create one reset gen per clock
set create_rst_gen [expr {[get_bd_cells -quiet ${rst_gen}] == {}}]
}
if {$device_clk == {}} {
set device_clk $link_clk
} else {
set rst_gen ${device_clk}_rstgen
# Only create one reset gen per clock
@ -284,7 +296,7 @@ proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {device_clk {}}} {
ad_connect ${a_xcvr}/up_cm_${n} ${u_xcvr}/up_cm_${n}
}
ad_connect ${a_xcvr}/up_ch_${n} ${u_xcvr}/up_${txrx}_${phys_lane}
ad_connect ${device_clk} ${u_xcvr}/${txrx}_clk_${phys_lane}
ad_connect ${link_clk} ${u_xcvr}/${txrx}_clk_${phys_lane}
if {$phys_lane != {}} {
if {$jesd204_type == 0} {
ad_connect ${u_xcvr}/${txrx}_${phys_lane} ${a_jesd}/${txrx}_phy${n}
@ -303,6 +315,7 @@ proc ad_xcvrcon {u_xcvr a_xcvr a_jesd {lane_map {}} {device_clk {}}} {
ad_connect ${a_jesd}/sysref $m_sysref
ad_connect ${a_jesd}/sync $m_sync
ad_connect ${device_clk} ${a_jesd}/device_clk
ad_connect ${link_clk} ${a_jesd}/link_clk
} else {
ad_connect ${a_jesd}/${txrx}_sysref $m_sysref
ad_connect ${a_jesd}/${txrx}_sync $m_sync