diff --git a/library/axi_ad9963/axi_ad9963.v b/library/axi_ad9963/axi_ad9963.v index 0ed6b77e0c..c1b8455123 100644 --- a/library/axi_ad9963/axi_ad9963.v +++ b/library/axi_ad9963/axi_ad9963.v @@ -107,8 +107,6 @@ module axi_ad9963 #( input dma_valid_q, input dac_dunf, - input hold_last_sample, - // axi interface input s_axi_aclk, @@ -169,8 +167,6 @@ module axi_ad9963 #( wire up_rack_tx_s; wire up_adc_ce; wire up_dac_ce; - wire valid_out_q_s; - wire valid_out_i_s; // signal name changes @@ -208,10 +204,7 @@ module axi_ad9963 #( .adc_status (adc_status_s), .up_adc_ce(up_adc_ce), .dac_data (dac_data_s), - .out_valid_q (valid_out_q_s), - .out_valid_i (valid_out_i_s), .up_dac_ce(up_dac_ce), - .tx_sample_hold (hold_last_sample), .up_clk (up_clk), .up_adc_dld (up_adc_dld_s), .up_adc_dwdata (up_adc_dwdata_s), @@ -288,12 +281,10 @@ module axi_ad9963 #( .dac_valid_i (dac_valid_i), .dac_data_i (dac_data_i), .dma_valid_i (dma_valid_i), - .out_valid_i (valid_out_i_s), .dac_enable_q (dac_enable_q), .dac_valid_q (dac_valid_q), .dac_data_q (dac_data_q), .dma_valid_q (dma_valid_q), - .out_valid_q (valid_out_q_s), .dac_dunf(dac_dunf), .up_dac_ce(up_dac_ce), .up_rstn (up_rstn), diff --git a/library/axi_ad9963/axi_ad9963_if.v b/library/axi_ad9963/axi_ad9963_if.v index 145f2aa2ed..de4e4f137e 100644 --- a/library/axi_ad9963/axi_ad9963_if.v +++ b/library/axi_ad9963/axi_ad9963_if.v @@ -73,11 +73,8 @@ module axi_ad9963_if #( // transmit data path interface - input out_valid_q, - input out_valid_i, input [23:0] dac_data, input up_dac_ce, - input tx_sample_hold, // delay interface @@ -93,9 +90,6 @@ module axi_ad9963_if #( // internal registers reg [11:0] rx_data_p = 0; - reg [11:0] tx_data_p = 'd0; - reg [11:0] tx_data_n = 'd0; - reg [23:0] constant_sample = 'd0; // internal signals @@ -103,6 +97,8 @@ module axi_ad9963_if #( wire [11:0] rx_data_n_s; wire rx_iq_p_s; wire rx_iq_n_s; + wire [11:0] tx_data_p; + wire [11:0] tx_data_n; wire div_clk; @@ -119,26 +115,8 @@ module axi_ad9963_if #( end end - always @(posedge dac_clk) begin - if (dac_rst == 1'b1) begin - tx_data_p <= 24'd0; - tx_data_n <= 24'd0; - constant_sample <= 24'd0; - end else begin - if(out_valid_i == 1'b1) begin - tx_data_p <= dac_data[11: 0]; - constant_sample[11: 0] <= tx_sample_hold ? dac_data[11: 0] : 12'd0; - end else begin - tx_data_p <= constant_sample[11:0] ; - end - if(out_valid_q == 1'b1) begin - tx_data_n <= dac_data[23:12]; - constant_sample[23:12] <= tx_sample_hold ? dac_data[23:12] : 12'd0; - end else begin - tx_data_n <= constant_sample[23:12]; - end - end - end + assign tx_data_p = dac_data[11: 0]; + assign tx_data_n = dac_data[23:12]; always @(posedge adc_clk) begin if (adc_rst == 1'b1) begin diff --git a/library/axi_ad9963/axi_ad9963_tx.v b/library/axi_ad9963/axi_ad9963_tx.v index a428345e9b..0fe50071ba 100644 --- a/library/axi_ad9963/axi_ad9963_tx.v +++ b/library/axi_ad9963/axi_ad9963_tx.v @@ -68,12 +68,10 @@ module axi_ad9963_tx #( output reg dac_valid_i, input [15:0] dac_data_i, input dma_valid_i, - output out_valid_i, output dac_enable_q, output reg dac_valid_q, input [15:0] dac_data_q, input dma_valid_q, - output out_valid_q, input dac_dunf, output up_dac_ce, @@ -147,7 +145,6 @@ module axi_ad9963_tx #( .dac_data_sync (dac_data_sync_s), .dac_dds_format (dac_dds_format_s), .dma_valid (dma_valid_i), - .out_data_valid (out_valid_i), .up_rstn (up_rstn), .up_clk (up_clk), .up_wreq (up_wreq), @@ -181,7 +178,6 @@ module axi_ad9963_tx #( .dac_data_sync (dac_data_sync_s), .dac_dds_format (dac_dds_format_s), .dma_valid (dma_valid_q), - .out_data_valid (out_valid_q), .up_rstn (up_rstn), .up_clk (up_clk), .up_wreq (up_wreq), diff --git a/library/axi_ad9963/axi_ad9963_tx_channel.v b/library/axi_ad9963/axi_ad9963_tx_channel.v index 0db035e376..4eb549d816 100644 --- a/library/axi_ad9963/axi_ad9963_tx_channel.v +++ b/library/axi_ad9963/axi_ad9963_tx_channel.v @@ -58,7 +58,6 @@ module axi_ad9963_tx_channel #( output reg [11:0] dac_data_out, input [11:0] dac_data_in, input dma_valid, - output out_data_valid, // processor interface @@ -113,8 +112,6 @@ module axi_ad9963_tx_channel #( wire [15:0] dac_iqcor_coeff_1_s; wire [15:0] dac_iqcor_coeff_2_s; - assign out_data_valid = dac_iqcor_valid_s; - // dac iq correction always @(posedge dac_clk) begin diff --git a/library/axi_dac_interpolate/axi_dac_interpolate.v b/library/axi_dac_interpolate/axi_dac_interpolate.v index 2077b10177..238d0e01f0 100644 --- a/library/axi_dac_interpolate/axi_dac_interpolate.v +++ b/library/axi_dac_interpolate/axi_dac_interpolate.v @@ -58,7 +58,6 @@ module axi_dac_interpolate #( output [15:0] dac_int_data_b, output dac_valid_out_a, output dac_valid_out_b, - output hold_last_sample, output underflow, input [ 1:0] trigger_i, @@ -125,6 +124,7 @@ module axi_dac_interpolate #( wire [ 2:0] filter_mask_b; wire dma_transfer_suspend; + wire flush_dma_s; wire start_sync_channels; wire dac_correction_enable_a; @@ -152,8 +152,10 @@ module axi_dac_interpolate #( wire underflow_a; wire underflow_b; - wire [ 1:0] lsample_hold_config; - wire sync_stop_channels; + wire stop_sync_channels; + wire [ 1:0] raw_transfer_en; + wire [15:0] dac_raw_ch_a_data; + wire [15:0] dac_raw_ch_b_data; // signal name changes @@ -206,9 +208,6 @@ module axi_dac_interpolate #( low_level_trigger <= ~trigger_i_m3 & low_level; end - assign hold_last_sample = lsample_hold_config[0]; - assign sync_stop_channels = lsample_hold_config[1]; - assign underflow = underflow_a | underflow_b; axi_dac_interpolate_filter #( @@ -220,7 +219,6 @@ module axi_dac_interpolate #( .dac_data (dac_data_a), .dac_valid (dac_valid_a), .dac_valid_out (dac_valid_out_a), - .sync_stop_channels (sync_stop_channels), .dac_enable (dac_enable_a), .dac_int_data (dac_int_data_a), @@ -231,6 +229,10 @@ module axi_dac_interpolate #( .interpolation_ratio (interpolation_ratio_a), .dma_transfer_suspend (dma_transfer_suspend), .start_sync_channels (start_sync_channels), + .sync_stop_channels (stop_sync_channels), + .flush_dma_in (flush_dma_s), + .raw_transfer_en (raw_transfer_en[0]), + .dac_raw_ch_data (dac_raw_ch_a_data), .trigger (trigger), .trigger_active (trigger_active), .en_start_trigger (en_start_trigger), @@ -249,7 +251,6 @@ module axi_dac_interpolate #( .dac_data (dac_data_b), .dac_valid (dac_valid_b), .dac_valid_out (dac_valid_out_b), - .sync_stop_channels (sync_stop_channels), .underflow (underflow_b), .dac_enable (dac_enable_b), @@ -260,6 +261,10 @@ module axi_dac_interpolate #( .interpolation_ratio (interpolation_ratio_b), .dma_transfer_suspend (dma_transfer_suspend), .start_sync_channels (start_sync_channels), + .sync_stop_channels (stop_sync_channels), + .flush_dma_in (flush_dma_s), + .raw_transfer_en (raw_transfer_en[1]), + .dac_raw_ch_data (dac_raw_ch_b_data), .trigger (trigger), .trigger_active (trigger_active), .en_start_trigger (en_start_trigger), @@ -279,13 +284,17 @@ module axi_dac_interpolate #( .dac_filter_mask_b (filter_mask_b), .dma_transfer_suspend (dma_transfer_suspend), + .flush_dma_out (flush_dma_s), + .raw_transfer_en (raw_transfer_en), + .dac_raw_ch_a_data (dac_raw_ch_a_data), + .dac_raw_ch_b_data (dac_raw_ch_b_data), .start_sync_channels (start_sync_channels), .dac_correction_enable_a(dac_correction_enable_a), .dac_correction_enable_b(dac_correction_enable_b), .dac_correction_coefficient_a(dac_correction_coefficient_a), .dac_correction_coefficient_b(dac_correction_coefficient_b), .trigger_config (trigger_config), - .lsample_hold_config (lsample_hold_config), + .stop_sync_channels (stop_sync_channels), .up_rstn (up_rstn), .up_clk (up_clk), diff --git a/library/axi_dac_interpolate/axi_dac_interpolate_filter.v b/library/axi_dac_interpolate/axi_dac_interpolate_filter.v index 0f746959bd..de4148bdf7 100644 --- a/library/axi_dac_interpolate/axi_dac_interpolate_filter.v +++ b/library/axi_dac_interpolate/axi_dac_interpolate_filter.v @@ -49,7 +49,6 @@ module axi_dac_interpolate_filter #( output reg [15:0] dac_int_data, output dma_ready, output dac_valid_out, - input sync_stop_channels, output underflow, input [ 2:0] filter_mask, @@ -58,6 +57,10 @@ module axi_dac_interpolate_filter #( input dac_correction_enable, input dma_transfer_suspend, input start_sync_channels, + input sync_stop_channels, + input flush_dma_in, + input raw_transfer_en, + input [15:0] dac_raw_ch_data, input trigger, input trigger_active, input en_start_trigger, @@ -66,7 +69,14 @@ module axi_dac_interpolate_filter #( input dma_valid_adjacent ); - // internal signals + // local parameters + + localparam [1:0] IDLE = 0; + localparam [1:0] WAIT = 1; + localparam [1:0] TRANSFER = 2; + localparam [1:0] FLUSHING = 3; + + // internal registers reg dac_int_ready; reg dac_filt_int_valid; @@ -75,15 +85,20 @@ module axi_dac_interpolate_filter #( reg cic_change_rate; reg [31:0] interpolation_counter; - reg transmit_ready = 1'b0; reg dma_data_valid = 1'b0; reg dma_data_valid_adjacent = 1'b0; reg filter_enable = 1'b0; - reg transfer = 1'b0; reg [15:0] dma_valid_m = 16'd0; reg stop_transfer = 1'd0; + reg transfer = 1'd0; + reg [ 1:0] transfer_sm = 2'd0; + reg [ 1:0] transfer_sm_next = 2'd0; + reg raw_dma_n = 1'd0; + + // internal signals + wire dac_valid_corrected; wire [15:0] dac_data_corrected; wire dac_fir_valid; @@ -94,6 +109,28 @@ module axi_dac_interpolate_filter #( wire dma_valid_ch_sync; wire dma_valid_ch; + wire flush_dma; + + wire [15:0] iqcor_data_in; + wire iqcor_valid_in; + + wire transfer_start; + wire transfer_ready; + + // Once enabled the raw value will be selected until the DMA has valid data. + // This is a workaround for when DAC channels are start/stopped independent + // of each other and working in cyclic mode at a lower samplerate. It is + // used to solve a system limitation(delay) between the application and + // Linux kernel, which resulted in a pulse at the beginning of a new buffer + // consisting in the last sample on the DMA bus. + always @(posedge dac_clk) begin + raw_dma_n <= raw_transfer_en | flush_dma ? 1'b1 : raw_dma_n & !dma_valid; + end + + assign reset_filt = !raw_dma_n & dma_transfer_suspend; + + assign iqcor_data_in = raw_dma_n ? dac_raw_ch_data : dac_data; + assign iqcor_valid_in = raw_dma_n ? 1'b1 : dac_valid; ad_iqcor #( .Q_OR_I_N (0), @@ -101,8 +138,8 @@ module axi_dac_interpolate_filter #( .SCALE_ONLY(1) ) i_ad_iqcor ( .clk (dac_clk), - .valid (dac_valid), - .data_in (dac_data), + .valid (iqcor_valid_in), + .data_in (iqcor_data_in), .data_iq (16'h0), .valid_out (dac_valid_corrected), .data_out (dac_data_corrected), @@ -113,7 +150,7 @@ module axi_dac_interpolate_filter #( fir_interp fir_interpolation ( .clk (dac_clk), .clk_enable (dac_cic_valid), - .reset (dac_rst | dma_transfer_suspend), + .reset (dac_rst | reset_filt), .filter_in (dac_data_corrected), .filter_out (dac_fir_data), .ce_out (dac_fir_valid)); @@ -121,28 +158,13 @@ module axi_dac_interpolate_filter #( cic_interp cic_interpolation ( .clk (dac_clk), .clk_enable (dac_valid_corrected), - .reset (dac_rst | cic_change_rate | dma_transfer_suspend), + .reset (dac_rst | cic_change_rate | reset_filt), .rate (interp_rate_cic), .load_rate (1'b0), .filter_in (dac_fir_data[30:0]), .filter_out (dac_cic_data), .ce_out (dac_cic_valid)); - assign dma_valid_ch_sync = sync_stop_channels ? - dma_valid & dma_valid_adjacent & !dma_transfer_suspend : - dma_valid & !dma_transfer_suspend; - - assign dma_valid_ch = dma_valid_ch_sync & !stop_transfer; - always @(posedge dac_clk) begin - if (dac_rst == 1'b1) begin - dma_valid_m <= 'd0; - end else begin - dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch}; - end - end - - assign dac_valid_out = dma_valid_m[4'h5]; - always @(posedge dac_clk) begin filter_mask_d1 <= filter_mask; if (filter_mask_d1 != filter_mask) begin @@ -157,9 +179,7 @@ module axi_dac_interpolate_filter #( // paths randomly ready, only when using data buffers always @(posedge dac_clk) begin - if (dac_filt_int_valid & - (!start_sync_channels & dma_valid | - (dma_valid & dma_valid_adjacent))) begin + if (dac_filt_int_valid & transfer_ready) begin if (interpolation_counter == interpolation_ratio) begin interpolation_counter <= 0; dac_int_ready <= 1'b1; @@ -173,26 +193,71 @@ module axi_dac_interpolate_filter #( end end + assign transfer_ready = start_sync_channels ? + dma_valid & dma_valid_adjacent : + dma_valid; + assign transfer_start = !(en_start_trigger ^ trigger) & transfer_ready; + always @(posedge dac_clk) begin - if (dma_transfer_suspend == 1'b0) begin - transfer <= trigger ? 1'b1 : transfer | !(trigger_active & en_start_trigger); - end else begin - transfer <= 1'b0; - end - if (start_sync_channels == 1'b0) begin - transmit_ready <= dma_valid & transfer; - end else begin - transmit_ready <= dma_valid & dma_valid_adjacent & transfer; - end + stop_transfer <= transfer_sm == IDLE ? 1'b0 : + stop_transfer | + dma_transfer_suspend | + (en_stop_trigger & trigger) | + (sync_stop_channels & dma_valid & dma_valid_adjacent); + end + + // transfer state machine + always @(posedge dac_clk) begin + case (transfer_sm) + IDLE: begin + transfer <= 1'b0; + if (dac_int_ready) begin + transfer_sm_next <= WAIT; + end + end + WAIT: begin + transfer <= 1'b0; + if (transfer_start) begin + transfer_sm_next <= TRANSFER; + end + end + TRANSFER: begin + transfer <= 1'b1; + if (stop_transfer) begin + if (flush_dma_in) begin + transfer_sm_next <= FLUSHING; + end else begin + transfer_sm_next <= WAIT; + end + end else if (dma_valid == 1'b0) begin + transfer_sm_next <= IDLE; + end + end + FLUSHING: begin + transfer <= 1'b1; + if (dma_valid == 1'b0) begin + transfer_sm_next <= IDLE; + end + end + endcase + transfer_sm <= transfer_sm_next; end + assign flush_dma = transfer_sm_next == FLUSHING ? 1'b1 : raw_transfer_en & flush_dma_in; + assign dma_ready = transfer_sm_next == TRANSFER ? dac_int_ready : flush_dma; + assign underflow = dac_enable & dma_ready & ~dma_valid & !flush_dma; + + assign dma_valid_ch = transfer | raw_transfer_en; + always @(posedge dac_clk) begin - stop_transfer <= !en_stop_trigger | dma_transfer_suspend ? 1'b0 : - stop_transfer | (trigger_active & trigger & transfer); + if (dac_rst == 1'b1) begin + dma_valid_m <= 'd0; + end else begin + dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch}; + end end - assign dma_ready = transmit_ready ? dac_int_ready : 1'b0; - assign underflow = dac_enable & dma_ready & ~dma_valid; + assign dac_valid_out = dma_valid_m[2]; always @(posedge dac_clk) begin case (filter_mask) diff --git a/library/axi_dac_interpolate/axi_dac_interpolate_reg.v b/library/axi_dac_interpolate/axi_dac_interpolate_reg.v index 01fecec1e8..512f9b0099 100644 --- a/library/axi_dac_interpolate/axi_dac_interpolate_reg.v +++ b/library/axi_dac_interpolate/axi_dac_interpolate_reg.v @@ -44,13 +44,17 @@ module axi_dac_interpolate_reg( output [31:0] dac_interpolation_ratio_b, output [ 2:0] dac_filter_mask_b, output dma_transfer_suspend, + output flush_dma_out, + output [ 1:0] raw_transfer_en, + output [15:0] dac_raw_ch_a_data, + output [15:0] dac_raw_ch_b_data, output start_sync_channels, + output stop_sync_channels, output dac_correction_enable_a, output dac_correction_enable_b, output [15:0] dac_correction_coefficient_a, output [15:0] dac_correction_coefficient_b, output [19:0] trigger_config, - output [ 1:0] lsample_hold_config, // bus interface input up_rstn, @@ -67,24 +71,30 @@ module axi_dac_interpolate_reg( // internal registers - reg [31:0] up_version = 32'h00020100; + reg [31:0] up_version = {16'h0002, /* MAJOR */ + 8'h03, /* MINOR */ + 8'h00}; /* PATCH */ reg [31:0] up_scratch = 32'h0; reg [31:0] up_interpolation_ratio_a = 32'h0; reg [ 2:0] up_filter_mask_a = 3'h0; reg [31:0] up_interpolation_ratio_b = 32'h0; reg [ 2:0] up_filter_mask_b = 3'h0; - reg [1:0] up_flags = 2'h2; - reg [1:0] up_config = 2'h0; + reg [ 5:0] up_flags = 6'ha; + reg [ 1:0] up_config = 2'h0; reg [15:0] up_correction_coefficient_a = 16'h0; reg [15:0] up_correction_coefficient_b = 16'h0; reg [19:0] up_trigger_config = 20'h0; - reg [ 1:0] up_lsample_hold_config = 2'h0; + reg [15:0] up_dac_raw_ch_a_data; + reg [15:0] up_dac_raw_ch_b_data; - wire [ 1:0] flags; + wire [ 5:0] flags; assign dma_transfer_suspend = flags[0]; assign start_sync_channels = flags[1]; + assign stop_sync_channels = flags[2]; + assign flush_dma_out = flags[3]; + assign raw_transfer_en = flags[5:4]; //5-b; 4-a always @(negedge up_rstn or posedge up_clk) begin if (up_rstn == 0) begin @@ -94,12 +104,13 @@ module axi_dac_interpolate_reg( up_filter_mask_a <= 'd0; up_interpolation_ratio_b <= 'd0; up_filter_mask_b <= 'd0; - up_flags <= 'd2; + up_flags <= 'ha; up_config <= 'd0; up_correction_coefficient_a <= 'd0; up_correction_coefficient_b <= 'd0; up_trigger_config <= 'd0; - up_lsample_hold_config <= 'h0; + up_dac_raw_ch_a_data <= 16'd0; + up_dac_raw_ch_b_data <= 16'd0; end else begin up_wack <= up_wreq; if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h1)) begin @@ -118,7 +129,7 @@ module axi_dac_interpolate_reg( up_filter_mask_b <= up_wdata[2:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h14)) begin - up_flags <= {30'h0,up_wdata[1:0]}; + up_flags <= up_wdata[5:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h15)) begin up_config <= up_wdata[1:0]; @@ -133,7 +144,8 @@ module axi_dac_interpolate_reg( up_trigger_config <= up_wdata[19:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h19)) begin - up_lsample_hold_config <= up_wdata[1:0]; + up_dac_raw_ch_a_data <= up_wdata[15:0]; + up_dac_raw_ch_b_data <= up_wdata[31:16]; end end end @@ -154,12 +166,12 @@ module axi_dac_interpolate_reg( 5'h11: up_rdata <= {29'h0,up_filter_mask_a}; 5'h12: up_rdata <= up_interpolation_ratio_b; 5'h13: up_rdata <= {29'h0,up_filter_mask_b}; - 5'h14: up_rdata <= {30'h0,up_flags}; + 5'h14: up_rdata <= {26'h0,up_flags}; 5'h15: up_rdata <= {30'h0,up_config}; 5'h16: up_rdata <= {16'h0,up_correction_coefficient_a}; 5'h17: up_rdata <= {16'h0,up_correction_coefficient_b}; 5'h18: up_rdata <= {12'h0,up_trigger_config}; - 5'h19: up_rdata <= {30'h0,up_lsample_hold_config}; + 5'h19: up_rdata <= {up_dac_raw_ch_b_data, up_dac_raw_ch_a_data}; default: up_rdata <= 0; endcase end else begin @@ -169,7 +181,7 @@ module axi_dac_interpolate_reg( end up_xfer_cntrl #( - .DATA_WIDTH(128) + .DATA_WIDTH(162) ) i_xfer_cntrl ( .up_rstn (up_rstn), .up_clk (up_clk), @@ -178,8 +190,9 @@ module axi_dac_interpolate_reg( up_correction_coefficient_b,// 16 up_correction_coefficient_a,// 16 up_trigger_config, // 20 - up_lsample_hold_config, // 2 - up_flags, // 2 + up_flags, // 6 + up_dac_raw_ch_a_data, // 16 + up_dac_raw_ch_b_data, // 16 up_interpolation_ratio_b, // 32 up_interpolation_ratio_a, // 32 up_filter_mask_b, // 3 @@ -193,8 +206,9 @@ module axi_dac_interpolate_reg( dac_correction_coefficient_b, // 16 dac_correction_coefficient_a, // 16 trigger_config, // 20 - lsample_hold_config, // 2 - flags, // 2 + flags, // 6 + dac_raw_ch_a_data, // 16 + dac_raw_ch_b_data, // 16 dac_interpolation_ratio_b, // 32 dac_interpolation_ratio_a, // 32 dac_filter_mask_b, // 3 diff --git a/projects/m2k/common/m2k_bd.tcl b/projects/m2k/common/m2k_bd.tcl index dcc15a5deb..5a5c68e2a7 100644 --- a/projects/m2k/common/m2k_bd.tcl +++ b/projects/m2k/common/m2k_bd.tcl @@ -265,7 +265,6 @@ ad_connect axi_dac_interpolate/trigger_la logic_analyzer/trigger_out_adc ad_connect axi_dac_interpolate/dac_valid_out_a axi_ad9963/dma_valid_i ad_connect axi_dac_interpolate/dac_valid_out_b axi_ad9963/dma_valid_q -ad_connect axi_dac_interpolate/hold_last_sample axi_ad9963/hold_last_sample ad_connect /axi_ad9963/tx_data txd ad_connect /axi_ad9963/tx_iq txiq