From c2d960e029ea4081b6093284dff9730490ac40b6 Mon Sep 17 00:00:00 2001 From: AndreiGrozav Date: Fri, 3 Dec 2021 16:40:48 +0200 Subject: [PATCH] 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. --- library/axi_adrv9001/axi_adrv9001.v | 12 ++- library/axi_adrv9001/axi_adrv9001_constr.xdc | 21 +++++ library/axi_adrv9001/axi_adrv9001_core.v | 91 ++++++++++++++++++-- library/axi_adrv9001/axi_adrv9001_ip.tcl | 58 +++++++++---- library/axi_adrv9001/axi_adrv9001_rx.v | 4 +- library/axi_adrv9001/axi_adrv9001_tx.v | 5 +- 6 files changed, 161 insertions(+), 30 deletions(-) diff --git a/library/axi_adrv9001/axi_adrv9001.v b/library/axi_adrv9001/axi_adrv9001.v index d28ab3ada..5d3d2423b 100644 --- a/library/axi_adrv9001/axi_adrv9001.v +++ b/library/axi_adrv9001/axi_adrv9001.v @@ -51,12 +51,17 @@ module axi_adrv9001 #( parameter FPGA_FAMILY = 0, parameter SPEED_GRADE = 0, parameter DEV_PACKAGE = 0, + parameter EXT_SYNC = 0, parameter USE_RX_CLK_FOR_TX = 0 ) ( input ref_clk, input mssi_sync, input tx_output_enable, + // external synchronization signals + input adc_sync_in, + input dac_sync_in, + // physical interface input rx1_dclk_in_n_NC, input rx1_dclk_in_p_dclk_in, @@ -416,7 +421,8 @@ module axi_adrv9001 #( .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), .FPGA_FAMILY (FPGA_FAMILY), .SPEED_GRADE (SPEED_GRADE), - .DEV_PACKAGE (DEV_PACKAGE) + .DEV_PACKAGE (DEV_PACKAGE), + .EXT_SYNC (EXT_SYNC) ) i_core ( // ADC interface .rx1_clk (adc_1_clk), @@ -530,6 +536,10 @@ module axi_adrv9001 #( .tdd_tx2_rf_en (tdd_tx2_rf_en), .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_clk (up_clk), .up_wreq (up_wreq_s), diff --git a/library/axi_adrv9001/axi_adrv9001_constr.xdc b/library/axi_adrv9001/axi_adrv9001_constr.xdc index 8350c805c..35670994d 100644 --- a/library/axi_adrv9001/axi_adrv9001_constr.xdc +++ b/library/axi_adrv9001/axi_adrv9001_constr.xdc @@ -13,3 +13,24 @@ set_false_path \ set_false_path \ -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ -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}] diff --git a/library/axi_adrv9001/axi_adrv9001_core.v b/library/axi_adrv9001/axi_adrv9001_core.v index 407da8ee3..c403b7755 100644 --- a/library/axi_adrv9001/axi_adrv9001_core.v +++ b/library/axi_adrv9001/axi_adrv9001_core.v @@ -51,6 +51,7 @@ module axi_ad9001_core #( parameter FPGA_FAMILY = 0, parameter SPEED_GRADE = 0, parameter DEV_PACKAGE = 0, + parameter EXT_SYNC = 0, parameter DAC_DDS_TYPE = 1, parameter DAC_DDS_CORDIC_DW = 20, @@ -90,7 +91,7 @@ module axi_ad9001_core #( output tx1_sdr_ddr_n, output tx1_symb_op, output tx1_symb_8_16b, - + input tx2_clk, output tx2_rst, output tx2_data_valid, @@ -101,7 +102,7 @@ module axi_ad9001_core #( output tx2_sdr_ddr_n, output tx2_symb_op, output tx2_symb_8_16b, - + input [ 31:0] adc_clk_ratio, input [ 31:0] dac_clk_ratio, @@ -169,6 +170,11 @@ module axi_ad9001_core #( output tdd_tx2_rf_en, output tdd_if2_mode, + // external syncronization signals + input adc_sync_in, + input dac_sync_in, + input ref_clk, + // processor interface input up_rstn, @@ -210,6 +216,10 @@ module axi_ad9001_core #( wire tx2_sdr_ddr_n_loc; wire tx2_symb_op_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 [15:0] tx1_data_i_A_d; @@ -220,6 +230,14 @@ module axi_ad9001_core #( reg tx2_data_valid_A_d; reg [15:0] tx2_data_i_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 should be 0 only when rx1_clk and rx2_clk have the same frequency @@ -304,6 +322,59 @@ module axi_ad9001_core #( 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 #( .ID (ID), .ENABLED (1), @@ -321,11 +392,11 @@ module axi_ad9001_core #( i_rx1 ( .adc_rst (rx1_rst), .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_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_q_B (rx2_data_q), @@ -357,6 +428,7 @@ module axi_ad9001_core #( .adc_data_q1 (adc_1_data_q1[15:0]), .adc_dovf (adc_1_dovf), + .adc_sync (adc_sync), .up_rstn (up_rstn), .up_clk (up_clk), .up_wreq (up_wreq), @@ -385,7 +457,7 @@ module axi_ad9001_core #( i_rx2 ( .adc_rst (rx2_rst_loc), .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_q_A (rx2_data_q), @@ -438,6 +510,7 @@ module axi_ad9001_core #( .FPGA_FAMILY (FPGA_FAMILY), .SPEED_GRADE (SPEED_GRADE), .DEV_PACKAGE (DEV_PACKAGE), + .EXT_SYNC (EXT_SYNC), .DDS_DISABLE (DDS_DISABLE), .IQCORRECTION_DISABLE (1), .DAC_DDS_TYPE (DAC_DDS_TYPE), @@ -459,8 +532,9 @@ module axi_ad9001_core #( .up_dac_r1_mode (up_tx1_r1_mode), .tdd_tx_valid (tdd_tx1_valid), .dac_clk_ratio (dac_clk_ratio), - .dac_sync_in (1'b0), - .dac_sync_out (), + .dac_sync_in (external_dac_sync | dac_sync_out_1), + .dac_sync_out (dac_sync_out_1), + .dac_ext_sync_arm (dac_ext_sync_arm), .dac_enable_i0 (dac_1_enable_i0), .dac_valid (dac_1_valid), .dac_data_i0 (dac_1_data_i0[15:0]), @@ -494,6 +568,7 @@ module axi_ad9001_core #( .FPGA_FAMILY (FPGA_FAMILY), .SPEED_GRADE (SPEED_GRADE), .DEV_PACKAGE (DEV_PACKAGE), + .EXT_SYNC (EXT_SYNC), .DDS_DISABLE (DDS_DISABLE), .IQCORRECTION_DISABLE (1), .DAC_DDS_TYPE (DAC_DDS_TYPE), @@ -512,7 +587,7 @@ module axi_ad9001_core #( .dac_sdr_ddr_n (tx2_sdr_ddr_n_loc), .dac_symb_op (tx2_symb_op_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_valid (dac_2_valid), .dac_enable_i0 (dac_2_enable_i0), diff --git a/library/axi_adrv9001/axi_adrv9001_ip.tcl b/library/axi_adrv9001/axi_adrv9001_ip.tcl index 75d9f2a7e..d258d30fc 100644 --- a/library/axi_adrv9001/axi_adrv9001_ip.tcl +++ b/library/axi_adrv9001/axi_adrv9001_ip.tcl @@ -62,35 +62,55 @@ adi_ip_add_core_dependencies { \ analog.com:user:util_cdc:1.0 \ } -ipx::infer_bus_interface delay_clk xilinx.com:signal:clock_rtl:1.0 [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] +set cc [ipx::current_core] -ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_1_rst -of_objects [ipx::current_core]] -ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces adc_2_rst -of_objects [ipx::current_core]] -ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_1_rst -of_objects [ipx::current_core]] -ipx::add_bus_parameter POLARITY [ipx::get_bus_interfaces dac_2_rst -of_objects [ipx::current_core]] +ipx::infer_bus_interface delay_clk xilinx.com:signal:clock_rtl:1.0 $cc +ipx::infer_bus_interface adc_1_clk xilinx.com:signal:clock_rtl:1.0 $cc +ipx::infer_bus_interface adc_2_clk xilinx.com:signal:clock_rtl:1.0 $cc +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} \ - [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} \ - [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} \ - [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} \ - [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 -ipx::create_xgui_files [ipx::current_core] +ipx::create_xgui_files $cc -ipx::save_core [ipx::current_core] +ipx::save_core $cc diff --git a/library/axi_adrv9001/axi_adrv9001_rx.v b/library/axi_adrv9001/axi_adrv9001_rx.v index 85ee8ed39..ce832abe8 100644 --- a/library/axi_adrv9001/axi_adrv9001_rx.v +++ b/library/axi_adrv9001/axi_adrv9001_rx.v @@ -93,6 +93,8 @@ module axi_adrv9001_rx #( input adc_dovf, + output adc_sync, + // processor interface input up_rstn, input up_clk, @@ -362,7 +364,7 @@ end else begin : core_enabled .adc_clk_ratio (adc_clk_ratio), .adc_start_code (), .adc_sref_sync (), - .adc_sync (), + .adc_sync (adc_sync), .adc_num_lanes (adc_num_lanes), .adc_sdr_ddr_n (adc_sdr_ddr_n), .adc_symb_op (adc_symb_op), diff --git a/library/axi_adrv9001/axi_adrv9001_tx.v b/library/axi_adrv9001/axi_adrv9001_tx.v index ef3680b1f..0cc367f03 100644 --- a/library/axi_adrv9001/axi_adrv9001_tx.v +++ b/library/axi_adrv9001/axi_adrv9001_tx.v @@ -47,6 +47,7 @@ module axi_adrv9001_tx #( parameter FPGA_FAMILY = 0, parameter SPEED_GRADE = 0, parameter DEV_PACKAGE = 0, + parameter EXT_SYNC = 0, parameter DISABLE = 0, parameter DDS_DISABLE = 0, parameter IQCORRECTION_DISABLE = 0, @@ -78,6 +79,7 @@ module axi_adrv9001_tx #( // master/slave input dac_sync_in, output dac_sync_out, + output dac_ext_sync_arm, // dma interface output dac_valid, @@ -166,7 +168,7 @@ end else begin : core_enabled // 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 dac_data_sync <= dac_data_sync_s; @@ -377,6 +379,7 @@ end else begin : core_enabled .dac_symb_op (dac_symb_op), .dac_symb_8_16b (dac_symb_8_16b), .dac_sync (dac_sync_out), + .dac_ext_sync_arm (dac_ext_sync_arm), .dac_frame (), .dac_clksel (), .dac_par_type (),