From 48d2c9d36f7d7a252bb776e95b9347d7f5c59276 Mon Sep 17 00:00:00 2001 From: Istvan Csomortani Date: Wed, 5 Jun 2019 19:02:45 +0300 Subject: [PATCH] axi_ad9361: Define a MIMO enabled parameter Define a MIMO_ENABLE parameter for the core, which will insert and additional de-skew logic to prevent timing issues coming from the clock skew differences of two or multiple AD9361. --- library/axi_ad9361/axi_ad9361.v | 9 +- library/axi_ad9361/axi_ad9361_hw.tcl | 1 + .../axi_ad9361/xilinx/axi_ad9361_cmos_if.v | 141 +++++++++++----- .../axi_ad9361/xilinx/axi_ad9361_lvds_if.v | 151 ++++++++++++------ projects/fmcomms5/common/fmcomms5_bd.tcl | 2 + 5 files changed, 219 insertions(+), 85 deletions(-) diff --git a/library/axi_ad9361/axi_ad9361.v b/library/axi_ad9361/axi_ad9361.v index 240e53542..b311b89f6 100644 --- a/library/axi_ad9361/axi_ad9361.v +++ b/library/axi_ad9361/axi_ad9361.v @@ -64,7 +64,8 @@ module axi_ad9361 #( parameter DAC_DDS_CORDIC_PHASE_DW = 13, parameter DAC_USERPORTS_DISABLE = 0, parameter DAC_IQCORRECTION_DISABLE = 0, - parameter IO_DELAY_GROUP = "dev_if_delay_group") ( + parameter IO_DELAY_GROUP = "dev_if_delay_group", + parameter MIMO_ENABLE = 0) ( // physical interface (receive-lvds) @@ -329,7 +330,8 @@ module axi_ad9361 #( axi_ad9361_cmos_if #( .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), .DAC_IODELAY_ENABLE (DAC_IODELAY_ENABLE), - .IO_DELAY_GROUP (IO_DELAY_GROUP)) + .IO_DELAY_GROUP (IO_DELAY_GROUP), + .CLK_DESKEW (MIMO_ENABLE)) i_dev_if ( .rx_clk_in (rx_clk_in), .rx_frame_in (rx_frame_in), @@ -390,7 +392,8 @@ module axi_ad9361 #( axi_ad9361_lvds_if #( .FPGA_TECHNOLOGY (FPGA_TECHNOLOGY), .DAC_IODELAY_ENABLE (DAC_IODELAY_ENABLE), - .IO_DELAY_GROUP (IO_DELAY_GROUP)) + .IO_DELAY_GROUP (IO_DELAY_GROUP), + .CLK_DESKEW (MIMO_ENABLE)) i_dev_if ( .rx_clk_in_p (rx_clk_in_p), .rx_clk_in_n (rx_clk_in_n), diff --git a/library/axi_ad9361/axi_ad9361_hw.tcl b/library/axi_ad9361/axi_ad9361_hw.tcl index c0ec7a893..28acabd36 100644 --- a/library/axi_ad9361/axi_ad9361_hw.tcl +++ b/library/axi_ad9361/axi_ad9361_hw.tcl @@ -69,6 +69,7 @@ ad_ip_parameter DAC_DDS_DISABLE INTEGER 0 ad_ip_parameter DAC_USERPORTS_DISABLE INTEGER 0 ad_ip_parameter DAC_IQCORRECTION_DISABLE INTEGER 0 ad_ip_parameter IO_DELAY_GROUP STRING {dev_if_delay_group} +ad_ip_parameter MIMO_EN INTEGER 0 adi_add_auto_fpga_spec_params diff --git a/library/axi_ad9361/xilinx/axi_ad9361_cmos_if.v b/library/axi_ad9361/xilinx/axi_ad9361_cmos_if.v index c84bf358c..8fc3745fc 100644 --- a/library/axi_ad9361/xilinx/axi_ad9361_cmos_if.v +++ b/library/axi_ad9361/xilinx/axi_ad9361_cmos_if.v @@ -39,7 +39,8 @@ module axi_ad9361_cmos_if #( parameter FPGA_TECHNOLOGY = 0, parameter DAC_IODELAY_ENABLE = 0, - parameter IO_DELAY_GROUP = "dev_if_delay_group") ( + parameter IO_DELAY_GROUP = "dev_if_delay_group", + parameter CLK_DESKEW = 0) ( // physical interface (receive) @@ -169,13 +170,26 @@ module axi_ad9361_cmos_if #( // r1mode - always @(negedge clk) begin - adc_r1_mode_n <= adc_r1_mode; - end + generate if (CLK_DESKEW) begin + + reg adc_r1_mode_n = 'd0; + + always @(negedge clk) begin + adc_r1_mode_n <= adc_r1_mode; + end + + always @(posedge l_clk) begin + rx_r1_mode <= adc_r1_mode_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + rx_r1_mode <= adc_r1_mode; + end - always @(posedge l_clk) begin - rx_r1_mode <= adc_r1_mode_n; end + endgenerate // adc-status @@ -255,21 +269,42 @@ module axi_ad9361_cmos_if #( // transfer to common clock - always @(negedge l_clk) begin - adc_valid_n <= adc_valid_p; - adc_data_n <= adc_data_p; - adc_status_n <= adc_status_p; - end + generate if (CLK_DESKEW) begin - assign adc_valid = adc_valid_int; - assign adc_data = adc_data_int; - assign adc_status = adc_status_int; + reg adc_valid_n = 'd0; + reg [47:0] adc_data_n = 'd0; + reg adc_status_n = 'd0; + + always @(negedge l_clk) begin + adc_valid_n <= adc_valid_p; + adc_data_n <= adc_data_p; + adc_status_n <= adc_status_p; + end + + always @(posedge clk) begin + adc_valid_int <= adc_valid_n; + adc_data_int <= adc_data_n; + adc_status_int <= adc_status_n; + end + + assign adc_valid = adc_valid_int; + assign adc_data = adc_data_int; + assign adc_status = adc_status_int; + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge clk) begin + adc_valid_int <= adc_valid_p; + adc_data_int <= adc_data_p; + adc_status_int <= adc_status_p; + end + + assign adc_valid = adc_valid_int; + assign adc_data = adc_data_int; + assign adc_status = adc_status_int; - always @(posedge clk) begin - adc_valid_int <= adc_valid_n; - adc_data_int <= adc_data_n; - adc_status_int <= adc_status_n; end + endgenerate // dac-tx interface @@ -304,19 +339,38 @@ module axi_ad9361_cmos_if #( // transfer to local clock - always @(negedge clk) begin - tx_clk_n <= tx_clk_p; - tx_frame_n <= tx_frame_p; - tx_data_0_n <= tx_data_0_p; - tx_data_1_n <= tx_data_1_p; - end + generate if (CLK_DESKEW) begin + + reg [ 1:0] tx_clk_n = 'd0; + reg tx_frame_n = 'd0; + reg [ 5:0] tx_data_0_n = 'd0; + reg [ 5:0] tx_data_1_n = 'd0; + + always @(negedge clk) begin + tx_clk_n <= tx_clk_p; + tx_frame_n <= tx_frame_p; + tx_data_0_n <= tx_data_0_p; + tx_data_1_n <= tx_data_1_p; + end + + always @(posedge l_clk) begin + tx_clk <= tx_clk_n; + tx_frame <= tx_frame_n; + tx_data_0 <= tx_data_0_n; + tx_data_1 <= tx_data_1_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + tx_clk <= tx_clk_p; + tx_frame <= tx_frame_p; + tx_data_0 <= tx_data_0_p; + tx_data_1 <= tx_data_1_p; + end - always @(posedge l_clk) begin - tx_clk <= tx_clk_n; - tx_frame <= tx_frame_n; - tx_data_0 <= tx_data_0_n; - tx_data_1 <= tx_data_1_n; end + endgenerate // tdd/ensm control @@ -349,15 +403,30 @@ module axi_ad9361_cmos_if #( end end - always @(negedge clk) begin - enable_int_n <= enable_int; - txnrx_int_n <= txnrx_int; - end + generate if (CLK_DESKEW) begin + + reg enable_int_n = 'd0; + reg txnrx_int_n = 'd0; + + always @(negedge clk) begin + enable_int_n <= enable_int; + txnrx_int_n <= txnrx_int; + end + + always @(posedge l_clk) begin + enable_int_p <= enable_int_n; + txnrx_int_p <= txnrx_int_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + enable_int_p <= enable_int_p; + txnrx_int_p <= txnrx_int_p; + end - always @(posedge l_clk) begin - enable_int_p <= enable_int_n; - txnrx_int_p <= txnrx_int_n; end + endgenerate // receive data interface, ibuf -> idelay -> iddr diff --git a/library/axi_ad9361/xilinx/axi_ad9361_lvds_if.v b/library/axi_ad9361/xilinx/axi_ad9361_lvds_if.v index 8dd95f751..914b1f14e 100644 --- a/library/axi_ad9361/xilinx/axi_ad9361_lvds_if.v +++ b/library/axi_ad9361/xilinx/axi_ad9361_lvds_if.v @@ -39,7 +39,8 @@ module axi_ad9361_lvds_if #( parameter FPGA_TECHNOLOGY = 0, parameter DAC_IODELAY_ENABLE = 0, - parameter IO_DELAY_GROUP = "dev_if_delay_group") ( + parameter IO_DELAY_GROUP = "dev_if_delay_group", + parameter CLK_DESKEW = 0) ( // physical interface (receive) @@ -120,7 +121,6 @@ module axi_ad9361_lvds_if #( // internal registers - reg adc_r1_mode_n = 'd0; reg rx_r1_mode = 'd0; reg rx_locked_m1 = 'd0; reg rx_locked = 'd0; @@ -135,9 +135,6 @@ module axi_ad9361_lvds_if #( reg adc_valid_p = 'd0; reg [47:0] adc_data_p = 'd0; reg adc_status_p = 'd0; - reg adc_valid_n = 'd0; - reg [47:0] adc_data_n = 'd0; - reg adc_status_n = 'd0; reg adc_valid_int = 'd0; reg [47:0] adc_data_int = 'd0; reg adc_status_int = 'd0; @@ -147,10 +144,6 @@ module axi_ad9361_lvds_if #( reg tx_frame_p = 'd0; reg [ 5:0] tx_data_0_p = 'd0; reg [ 5:0] tx_data_1_p = 'd0; - reg [ 1:0] tx_clk_n = 'd0; - reg tx_frame_n = 'd0; - reg [ 5:0] tx_data_0_n = 'd0; - reg [ 5:0] tx_data_1_n = 'd0; reg [ 1:0] tx_clk = 'd0; reg tx_frame = 'd0; reg [ 5:0] tx_data_0 = 'd0; @@ -163,8 +156,6 @@ module axi_ad9361_lvds_if #( reg txnrx_up = 'd0; reg enable_int = 'd0; reg txnrx_int = 'd0; - reg enable_int_n = 'd0; - reg txnrx_int_n = 'd0; reg enable_int_p = 'd0; reg txnrx_int_p = 'd0; @@ -184,13 +175,26 @@ module axi_ad9361_lvds_if #( // r1mode - always @(negedge clk) begin - adc_r1_mode_n <= adc_r1_mode; - end + generate if (CLK_DESKEW) begin + + reg adc_r1_mode_n = 'd0; + + always @(negedge clk) begin + adc_r1_mode_n <= adc_r1_mode; + end + + always @(posedge l_clk) begin + rx_r1_mode <= adc_r1_mode_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + rx_r1_mode <= adc_r1_mode; + end - always @(posedge l_clk) begin - rx_r1_mode <= adc_r1_mode_n; end + endgenerate // adc-status @@ -336,21 +340,42 @@ module axi_ad9361_lvds_if #( // transfer to common clock - always @(negedge l_clk) begin - adc_valid_n <= adc_valid_p; - adc_data_n <= adc_data_p; - adc_status_n <= adc_status_p; - end + generate if (CLK_DESKEW) begin - assign adc_valid = adc_valid_int; - assign adc_data = adc_data_int; - assign adc_status = adc_status_int; + reg adc_valid_n = 'd0; + reg [47:0] adc_data_n = 'd0; + reg adc_status_n = 'd0; + + always @(negedge l_clk) begin + adc_valid_n <= adc_valid_p; + adc_data_n <= adc_data_p; + adc_status_n <= adc_status_p; + end + + always @(posedge clk) begin + adc_valid_int <= adc_valid_n; + adc_data_int <= adc_data_n; + adc_status_int <= adc_status_n; + end + + assign adc_valid = adc_valid_int; + assign adc_data = adc_data_int; + assign adc_status = adc_status_int; + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge clk) begin + adc_valid_int <= adc_valid_p; + adc_data_int <= adc_data_p; + adc_status_int <= adc_status_p; + end + + assign adc_valid = adc_valid_int; + assign adc_data = adc_data_int; + assign adc_status = adc_status_int; - always @(posedge clk) begin - adc_valid_int <= adc_valid_n; - adc_data_int <= adc_data_n; - adc_status_int <= adc_status_n; end + endgenerate // dac-tx interface @@ -411,19 +436,38 @@ module axi_ad9361_lvds_if #( // transfer to local clock - always @(negedge clk) begin - tx_clk_n <= tx_clk_p; - tx_frame_n <= tx_frame_p; - tx_data_0_n <= tx_data_0_p; - tx_data_1_n <= tx_data_1_p; - end + generate if (CLK_DESKEW) begin + + reg [ 1:0] tx_clk_n = 'd0; + reg tx_frame_n = 'd0; + reg [ 5:0] tx_data_0_n = 'd0; + reg [ 5:0] tx_data_1_n = 'd0; + + always @(negedge clk) begin + tx_clk_n <= tx_clk_p; + tx_frame_n <= tx_frame_p; + tx_data_0_n <= tx_data_0_p; + tx_data_1_n <= tx_data_1_p; + end + + always @(posedge l_clk) begin + tx_clk <= tx_clk_n; + tx_frame <= tx_frame_n; + tx_data_0 <= tx_data_0_n; + tx_data_1 <= tx_data_1_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + tx_clk <= tx_clk_p; + tx_frame <= tx_frame_p; + tx_data_0 <= tx_data_0_p; + tx_data_1 <= tx_data_1_p; + end - always @(posedge l_clk) begin - tx_clk <= tx_clk_n; - tx_frame <= tx_frame_n; - tx_data_0 <= tx_data_0_n; - tx_data_1 <= tx_data_1_n; end + endgenerate // tdd/ensm control @@ -456,15 +500,30 @@ module axi_ad9361_lvds_if #( end end - always @(negedge clk) begin - enable_int_n <= enable_int; - txnrx_int_n <= txnrx_int; - end + generate if (CLK_DESKEW) begin + + reg enable_int_n = 'd0; + reg txnrx_int_n = 'd0; + + always @(negedge clk) begin + enable_int_n <= enable_int; + txnrx_int_n <= txnrx_int; + end + + always @(posedge l_clk) begin + enable_int_p <= enable_int_n; + txnrx_int_p <= txnrx_int_n; + end + + end else begin /* CLK_DESKEW == 0 */ + + always @(posedge l_clk) begin + enable_int_p <= enable_int_p; + txnrx_int_p <= txnrx_int_p; + end - always @(posedge l_clk) begin - enable_int_p <= enable_int_n; - txnrx_int_p <= txnrx_int_n; end + endgenerate // receive data interface, ibuf -> idelay -> iddr diff --git a/projects/fmcomms5/common/fmcomms5_bd.tcl b/projects/fmcomms5/common/fmcomms5_bd.tcl index e4c486e15..3188e2662 100644 --- a/projects/fmcomms5/common/fmcomms5_bd.tcl +++ b/projects/fmcomms5/common/fmcomms5_bd.tcl @@ -49,6 +49,7 @@ ad_connect sys_cpu_resetn sys_100m_resetn ad_ip_instance axi_ad9361 axi_ad9361_0 ad_ip_parameter axi_ad9361_0 CONFIG.ID 0 ad_ip_parameter axi_ad9361_0 CONFIG.IO_DELAY_GROUP dev_0_if_delay_group +ad_ip_parameter axi_ad9361_0 CONFIG.MIMO_ENABLE 1 ad_connect sys_200m_clk axi_ad9361_0/delay_clk ad_connect axi_ad9361_0/l_clk axi_ad9361_0/clk ad_connect axi_ad9361_0/dac_sync_out axi_ad9361_0/dac_sync_in @@ -74,6 +75,7 @@ ad_connect up_txnrx_0 axi_ad9361_0/up_txnrx ad_ip_instance axi_ad9361 axi_ad9361_1 ad_ip_parameter axi_ad9361_1 CONFIG.ID 1 ad_ip_parameter axi_ad9361_1 CONFIG.IO_DELAY_GROUP dev_1_if_delay_group +ad_ip_parameter axi_ad9361_1 CONFIG.MIMO_ENABLE 1 ad_connect sys_200m_clk axi_ad9361_1/delay_clk ad_connect axi_ad9361_0/l_clk axi_ad9361_1/clk ad_connect axi_ad9361_0/dac_sync_out axi_ad9361_1/dac_sync_in