axi_adrv9001: Add external sync support

The external sync must be synchronous to the reference clock, in order
to obtain a deterministic synchronization of the interface.
main
AndreiGrozav 2021-12-03 16:40:48 +02:00 committed by AndreiGrozav
parent 38c489d254
commit c2d960e029
6 changed files with 161 additions and 30 deletions

View File

@ -51,12 +51,17 @@ module axi_adrv9001 #(
parameter FPGA_FAMILY = 0, parameter FPGA_FAMILY = 0,
parameter SPEED_GRADE = 0, parameter SPEED_GRADE = 0,
parameter DEV_PACKAGE = 0, parameter DEV_PACKAGE = 0,
parameter EXT_SYNC = 0,
parameter USE_RX_CLK_FOR_TX = 0 parameter USE_RX_CLK_FOR_TX = 0
) ( ) (
input ref_clk, input ref_clk,
input mssi_sync, input mssi_sync,
input tx_output_enable, input tx_output_enable,
// external synchronization signals
input adc_sync_in,
input dac_sync_in,
// physical interface // physical interface
input rx1_dclk_in_n_NC, input rx1_dclk_in_n_NC,
input rx1_dclk_in_p_dclk_in, input rx1_dclk_in_p_dclk_in,
@ -416,7 +421,8 @@ module axi_adrv9001 #(
.FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY),
.FPGA_FAMILY (FPGA_FAMILY), .FPGA_FAMILY (FPGA_FAMILY),
.SPEED_GRADE (SPEED_GRADE), .SPEED_GRADE (SPEED_GRADE),
.DEV_PACKAGE (DEV_PACKAGE) .DEV_PACKAGE (DEV_PACKAGE),
.EXT_SYNC (EXT_SYNC)
) i_core ( ) i_core (
// ADC interface // ADC interface
.rx1_clk (adc_1_clk), .rx1_clk (adc_1_clk),
@ -530,6 +536,10 @@ module axi_adrv9001 #(
.tdd_tx2_rf_en (tdd_tx2_rf_en), .tdd_tx2_rf_en (tdd_tx2_rf_en),
.tdd_if2_mode (tdd_if2_mode), .tdd_if2_mode (tdd_if2_mode),
.ref_clk (ref_clk),
.adc_sync_in (adc_sync_in),
.dac_sync_in (dac_sync_in),
.up_rstn (up_rstn), .up_rstn (up_rstn),
.up_clk (up_clk), .up_clk (up_clk),
.up_wreq (up_wreq_s), .up_wreq (up_wreq_s),

View File

@ -13,3 +13,24 @@ set_false_path \
set_false_path \ set_false_path \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_tx1_ctrl_sync* && IS_SEQUENTIAL}] -filter {NAME =~ *i_tx1_ctrl_sync* && IS_SEQUENTIAL}]
# sync event i_rx_external_sync
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*i_rx_external_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*i_rx_external_sync/i_sync_in/cdc_sync_stage1_reg[0]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*i_rx_external_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*i_rx_external_sync/i_sync_out/cdc_sync_stage1_reg[0]/D}]
# sync event i_tx_external_sync
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*i_tx_external_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*i_tx_external_sync/i_sync_in/cdc_sync_stage1_reg[0]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*i_tx_external_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*i_tx_external_sync/i_sync_out/cdc_sync_stage1_reg[0]/D}]
# mssi_sync
set_false_path \
-to [get_cells -quiet -hier *mssi_sync_d_reg* \
-filter {NAME =~ *i_*_phy* && IS_SEQUENTIAL}]

View File

@ -51,6 +51,7 @@ module axi_ad9001_core #(
parameter FPGA_FAMILY = 0, parameter FPGA_FAMILY = 0,
parameter SPEED_GRADE = 0, parameter SPEED_GRADE = 0,
parameter DEV_PACKAGE = 0, parameter DEV_PACKAGE = 0,
parameter EXT_SYNC = 0,
parameter DAC_DDS_TYPE = 1, parameter DAC_DDS_TYPE = 1,
parameter DAC_DDS_CORDIC_DW = 20, parameter DAC_DDS_CORDIC_DW = 20,
@ -90,7 +91,7 @@ module axi_ad9001_core #(
output tx1_sdr_ddr_n, output tx1_sdr_ddr_n,
output tx1_symb_op, output tx1_symb_op,
output tx1_symb_8_16b, output tx1_symb_8_16b,
input tx2_clk, input tx2_clk,
output tx2_rst, output tx2_rst,
output tx2_data_valid, output tx2_data_valid,
@ -101,7 +102,7 @@ module axi_ad9001_core #(
output tx2_sdr_ddr_n, output tx2_sdr_ddr_n,
output tx2_symb_op, output tx2_symb_op,
output tx2_symb_8_16b, output tx2_symb_8_16b,
input [ 31:0] adc_clk_ratio, input [ 31:0] adc_clk_ratio,
input [ 31:0] dac_clk_ratio, input [ 31:0] dac_clk_ratio,
@ -169,6 +170,11 @@ module axi_ad9001_core #(
output tdd_tx2_rf_en, output tdd_tx2_rf_en,
output tdd_if2_mode, output tdd_if2_mode,
// external syncronization signals
input adc_sync_in,
input dac_sync_in,
input ref_clk,
// processor interface // processor interface
input up_rstn, input up_rstn,
@ -210,6 +216,10 @@ module axi_ad9001_core #(
wire tx2_sdr_ddr_n_loc; wire tx2_sdr_ddr_n_loc;
wire tx2_symb_op_loc; wire tx2_symb_op_loc;
wire tx2_symb_8_16b_loc; wire tx2_symb_8_16b_loc;
wire adc_sync;
wire adc_sync_m;
wire dac_sync_m;
wire dac_sync_out_1;
reg tx1_data_valid_A_d; reg tx1_data_valid_A_d;
reg [15:0] tx1_data_i_A_d; reg [15:0] tx1_data_i_A_d;
@ -220,6 +230,14 @@ module axi_ad9001_core #(
reg tx2_data_valid_A_d; reg tx2_data_valid_A_d;
reg [15:0] tx2_data_i_A_d; reg [15:0] tx2_data_i_A_d;
reg [15:0] tx2_data_q_A_d; reg [15:0] tx2_data_q_A_d;
reg sync_adc_valid = 1'b1;
reg adc_sync_armed = 1'b0;
reg adc_sync_in_d1 = 1'b0;
reg adc_sync_d1 = 1'b0;
reg dac_sync_arm = 1'b0;
reg dac_ext_sync_arm_d = 1'b0;
reg dac_sync_in_d1 = 1'b0;
reg external_dac_sync = 1'b0;
// rx1_r1_mode and tx1_r1_mode considered static during operation // rx1_r1_mode and tx1_r1_mode considered static during operation
// rx1_r1_mode should be 0 only when rx1_clk and rx2_clk have the same frequency // rx1_r1_mode should be 0 only when rx1_clk and rx2_clk have the same frequency
@ -304,6 +322,59 @@ module axi_ad9001_core #(
end end
end end
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_rx_external_sync (
.in_clk (ref_clk),
.in_event (adc_sync_in),
.out_clk (rx1_clk),
.out_event (adc_sync_m));
always @(posedge rx1_clk) begin
if (rx1_rst == 1'b1) begin
adc_sync_armed <= 1'b0;
adc_sync_in_d1 <= 1'b0;
adc_sync_d1 <= 1'b0;
sync_adc_valid <= 1'b1;
end else begin
adc_sync_in_d1 <= adc_sync_m;
adc_sync_d1 <= adc_sync;
if (~adc_sync_d1 & adc_sync) begin
sync_adc_valid <= 1'b0;
adc_sync_armed <= 1'b1;
end else if (~adc_sync_in_d1 & adc_sync_m & adc_sync_armed) begin
sync_adc_valid <= 1'b1;
adc_sync_armed <= 1'b0;
end
end
end
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_tx_external_sync (
.in_clk (ref_clk),
.in_event (dac_sync_in),
.out_clk (tx1_clk),
.out_event (dac_sync_m));
always @(posedge tx1_clk) begin
if (tx1_rst == 1'b1) begin
dac_ext_sync_arm_d <= 1'b0;
dac_sync_in_d1 <= 1'b0;
external_dac_sync <= 1'b0;
end else begin
dac_sync_in_d1 <= dac_sync_m;
dac_ext_sync_arm_d <= dac_ext_sync_arm;
if (~dac_ext_sync_arm_d & dac_ext_sync_arm) begin
external_dac_sync <= ~external_dac_sync;
end else if (~dac_sync_in_d1 & dac_sync_m) begin
external_dac_sync <= 1'b0;
end
end
end
axi_adrv9001_rx #( axi_adrv9001_rx #(
.ID (ID), .ID (ID),
.ENABLED (1), .ENABLED (1),
@ -321,11 +392,11 @@ module axi_ad9001_core #(
i_rx1 ( i_rx1 (
.adc_rst (rx1_rst), .adc_rst (rx1_rst),
.adc_clk (rx1_clk), .adc_clk (rx1_clk),
.adc_valid_A (rx1_data_valid & tdd_rx1_valid), .adc_valid_A (rx1_data_valid & tdd_rx1_valid & sync_adc_valid),
.adc_data_i_A (rx1_data_i), .adc_data_i_A (rx1_data_i),
.adc_data_q_A (rx1_data_q), .adc_data_q_A (rx1_data_q),
.adc_valid_B (rx2_data_valid & tdd_rx1_valid), .adc_valid_B (rx2_data_valid & tdd_rx1_valid & sync_adc_valid),
.adc_data_i_B (rx2_data_i), .adc_data_i_B (rx2_data_i),
.adc_data_q_B (rx2_data_q), .adc_data_q_B (rx2_data_q),
@ -357,6 +428,7 @@ module axi_ad9001_core #(
.adc_data_q1 (adc_1_data_q1[15:0]), .adc_data_q1 (adc_1_data_q1[15:0]),
.adc_dovf (adc_1_dovf), .adc_dovf (adc_1_dovf),
.adc_sync (adc_sync),
.up_rstn (up_rstn), .up_rstn (up_rstn),
.up_clk (up_clk), .up_clk (up_clk),
.up_wreq (up_wreq), .up_wreq (up_wreq),
@ -385,7 +457,7 @@ module axi_ad9001_core #(
i_rx2 ( i_rx2 (
.adc_rst (rx2_rst_loc), .adc_rst (rx2_rst_loc),
.adc_clk (rx2_clk), .adc_clk (rx2_clk),
.adc_valid_A (rx2_data_valid & tdd_rx2_valid), .adc_valid_A (rx2_data_valid & tdd_rx2_valid & sync_adc_valid),
.adc_data_i_A (rx2_data_i), .adc_data_i_A (rx2_data_i),
.adc_data_q_A (rx2_data_q), .adc_data_q_A (rx2_data_q),
@ -438,6 +510,7 @@ module axi_ad9001_core #(
.FPGA_FAMILY (FPGA_FAMILY), .FPGA_FAMILY (FPGA_FAMILY),
.SPEED_GRADE (SPEED_GRADE), .SPEED_GRADE (SPEED_GRADE),
.DEV_PACKAGE (DEV_PACKAGE), .DEV_PACKAGE (DEV_PACKAGE),
.EXT_SYNC (EXT_SYNC),
.DDS_DISABLE (DDS_DISABLE), .DDS_DISABLE (DDS_DISABLE),
.IQCORRECTION_DISABLE (1), .IQCORRECTION_DISABLE (1),
.DAC_DDS_TYPE (DAC_DDS_TYPE), .DAC_DDS_TYPE (DAC_DDS_TYPE),
@ -459,8 +532,9 @@ module axi_ad9001_core #(
.up_dac_r1_mode (up_tx1_r1_mode), .up_dac_r1_mode (up_tx1_r1_mode),
.tdd_tx_valid (tdd_tx1_valid), .tdd_tx_valid (tdd_tx1_valid),
.dac_clk_ratio (dac_clk_ratio), .dac_clk_ratio (dac_clk_ratio),
.dac_sync_in (1'b0), .dac_sync_in (external_dac_sync | dac_sync_out_1),
.dac_sync_out (), .dac_sync_out (dac_sync_out_1),
.dac_ext_sync_arm (dac_ext_sync_arm),
.dac_enable_i0 (dac_1_enable_i0), .dac_enable_i0 (dac_1_enable_i0),
.dac_valid (dac_1_valid), .dac_valid (dac_1_valid),
.dac_data_i0 (dac_1_data_i0[15:0]), .dac_data_i0 (dac_1_data_i0[15:0]),
@ -494,6 +568,7 @@ module axi_ad9001_core #(
.FPGA_FAMILY (FPGA_FAMILY), .FPGA_FAMILY (FPGA_FAMILY),
.SPEED_GRADE (SPEED_GRADE), .SPEED_GRADE (SPEED_GRADE),
.DEV_PACKAGE (DEV_PACKAGE), .DEV_PACKAGE (DEV_PACKAGE),
.EXT_SYNC (EXT_SYNC),
.DDS_DISABLE (DDS_DISABLE), .DDS_DISABLE (DDS_DISABLE),
.IQCORRECTION_DISABLE (1), .IQCORRECTION_DISABLE (1),
.DAC_DDS_TYPE (DAC_DDS_TYPE), .DAC_DDS_TYPE (DAC_DDS_TYPE),
@ -512,7 +587,7 @@ module axi_ad9001_core #(
.dac_sdr_ddr_n (tx2_sdr_ddr_n_loc), .dac_sdr_ddr_n (tx2_sdr_ddr_n_loc),
.dac_symb_op (tx2_symb_op_loc), .dac_symb_op (tx2_symb_op_loc),
.dac_symb_8_16b (tx2_symb_8_16b_loc), .dac_symb_8_16b (tx2_symb_8_16b_loc),
.dac_sync_in (1'b0), .dac_sync_in (external_dac_sync | dac_sync_out_1),
.dac_sync_out (), .dac_sync_out (),
.dac_valid (dac_2_valid), .dac_valid (dac_2_valid),
.dac_enable_i0 (dac_2_enable_i0), .dac_enable_i0 (dac_2_enable_i0),

View File

@ -62,35 +62,55 @@ adi_ip_add_core_dependencies { \
analog.com:user:util_cdc:1.0 \ analog.com:user:util_cdc:1.0 \
} }
ipx::infer_bus_interface delay_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] set cc [ipx::current_core]
ipx::infer_bus_interface adc_1_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface adc_2_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface dac_1_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface dac_2_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface adc_1_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface adc_2_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface dac_1_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interface dac_2_rst xilinx.com:signal:reset_rtl:1.0 [ipx::current_core]
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_1_rst -of_objects [ipx::current_core]] ipx::infer_bus_interface delay_clk xilinx.com:signal:clock_rtl:1.0 $cc
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_2_rst -of_objects [ipx::current_core]] ipx::infer_bus_interface adc_1_clk xilinx.com:signal:clock_rtl:1.0 $cc
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_1_rst -of_objects [ipx::current_core]] ipx::infer_bus_interface adc_2_clk xilinx.com:signal:clock_rtl:1.0 $cc
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_2_rst -of_objects [ipx::current_core]] ipx::infer_bus_interface dac_1_clk xilinx.com:signal:clock_rtl:1.0 $cc
ipx::infer_bus_interface dac_2_clk xilinx.com:signal:clock_rtl:1.0 $cc
ipx::infer_bus_interface adc_1_rst xilinx.com:signal:reset_rtl:1.0 $cc
ipx::infer_bus_interface adc_2_rst xilinx.com:signal:reset_rtl:1.0 $cc
ipx::infer_bus_interface dac_1_rst xilinx.com:signal:reset_rtl:1.0 $cc
ipx::infer_bus_interface dac_2_rst xilinx.com:signal:reset_rtl:1.0 $cc
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_1_rst -of_objects $cc]
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_2_rst -of_objects $cc]
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_1_rst -of_objects $cc]
ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_2_rst -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INDEPENDENT_1R1T_SUPPORT')) == 1 && spirit:decode(id('MODELPARAM_VALUE.DISABLE_TX2_SSI')) == 0} \ set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INDEPENDENT_1R1T_SUPPORT')) == 1 && spirit:decode(id('MODELPARAM_VALUE.DISABLE_TX2_SSI')) == 0} \
[ipx::get_ports dac_2* -of_objects [ipx::current_core]] [ipx::get_ports dac_2* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INDEPENDENT_1R1T_SUPPORT')) == 1 && spirit:decode(id('MODELPARAM_VALUE.DISABLE_RX2_SSI')) == 0} \ set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.INDEPENDENT_1R1T_SUPPORT')) == 1 && spirit:decode(id('MODELPARAM_VALUE.DISABLE_RX2_SSI')) == 0} \
[ipx::get_ports adc_2* -of_objects [ipx::current_core]] [ipx::get_ports adc_2* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.DISABLE_TX2_SSI')) == 0} \ set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.DISABLE_TX2_SSI')) == 0} \
[ipx::get_ports *tx2_* -of_objects [ipx::current_core]] [ipx::get_ports *tx2_* -of_objects $cc]
set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.DISABLE_RX2_SSI')) == 0} \ set_property enablement_dependency {spirit:decode(id('MODELPARAM_VALUE.DISABLE_RX2_SSI')) == 0} \
[ipx::get_ports *rx2_* -of_objects [ipx::current_core]] [ipx::get_ports *rx2_* -of_objects $cc]
set_property driver_value 0 [ipx::get_ports *_sync_in* -of_objects $cc]
## Customize XGUI layout
set page0 [ipgui::get_pagespec -name "Page 0" -component $cc]
ipgui::add_param -name "EXT_SYNC" -component $cc -parent $page0
set_property -dict [list \
"display_name" "External sync" \
"tooltip" "NOTE: If active enables the external synchronization features for Rx and Tx. The external sync signals must be synchronous with to ref_clk" \
"widget" "checkBox" \
] [ipgui::get_guiparamspec -name "EXT_SYNC" -component $cc]
adi_set_ports_dependency "adc_sync_in" \
"(spirit:decode(id('MODELPARAM_VALUE.EXT_SYNC')) == 1)"
adi_set_ports_dependency "dac_sync_in" \
"(spirit:decode(id('MODELPARAM_VALUE.EXT_SYNC')) == 1)"
adi_add_auto_fpga_spec_params adi_add_auto_fpga_spec_params
ipx::create_xgui_files [ipx::current_core] ipx::create_xgui_files $cc
ipx::save_core [ipx::current_core] ipx::save_core $cc

View File

@ -93,6 +93,8 @@ module axi_adrv9001_rx #(
input adc_dovf, input adc_dovf,
output adc_sync,
// processor interface // processor interface
input up_rstn, input up_rstn,
input up_clk, input up_clk,
@ -362,7 +364,7 @@ end else begin : core_enabled
.adc_clk_ratio (adc_clk_ratio), .adc_clk_ratio (adc_clk_ratio),
.adc_start_code (), .adc_start_code (),
.adc_sref_sync (), .adc_sref_sync (),
.adc_sync (), .adc_sync (adc_sync),
.adc_num_lanes (adc_num_lanes), .adc_num_lanes (adc_num_lanes),
.adc_sdr_ddr_n (adc_sdr_ddr_n), .adc_sdr_ddr_n (adc_sdr_ddr_n),
.adc_symb_op (adc_symb_op), .adc_symb_op (adc_symb_op),

View File

@ -47,6 +47,7 @@ module axi_adrv9001_tx #(
parameter FPGA_FAMILY = 0, parameter FPGA_FAMILY = 0,
parameter SPEED_GRADE = 0, parameter SPEED_GRADE = 0,
parameter DEV_PACKAGE = 0, parameter DEV_PACKAGE = 0,
parameter EXT_SYNC = 0,
parameter DISABLE = 0, parameter DISABLE = 0,
parameter DDS_DISABLE = 0, parameter DDS_DISABLE = 0,
parameter IQCORRECTION_DISABLE = 0, parameter IQCORRECTION_DISABLE = 0,
@ -78,6 +79,7 @@ module axi_adrv9001_tx #(
// master/slave // master/slave
input dac_sync_in, input dac_sync_in,
output dac_sync_out, output dac_sync_out,
output dac_ext_sync_arm,
// dma interface // dma interface
output dac_valid, output dac_valid,
@ -166,7 +168,7 @@ end else begin : core_enabled
// master/slave // master/slave
assign dac_data_sync_s = (ID == 0) ? dac_sync_out : dac_sync_in; assign dac_data_sync_s = (EXT_SYNC == 0) ? dac_sync_out : dac_sync_in;
always @(posedge dac_clk) begin always @(posedge dac_clk) begin
dac_data_sync <= dac_data_sync_s; dac_data_sync <= dac_data_sync_s;
@ -377,6 +379,7 @@ end else begin : core_enabled
.dac_symb_op (dac_symb_op), .dac_symb_op (dac_symb_op),
.dac_symb_8_16b (dac_symb_8_16b), .dac_symb_8_16b (dac_symb_8_16b),
.dac_sync (dac_sync_out), .dac_sync (dac_sync_out),
.dac_ext_sync_arm (dac_ext_sync_arm),
.dac_frame (), .dac_frame (),
.dac_clksel (), .dac_clksel (),
.dac_par_type (), .dac_par_type (),