Skip to content

Commit

Permalink
m2k:axi_ad9963, axi_dac_interpolate fixes
Browse files Browse the repository at this point in the history
This commit fixes the last sample hold and spike before buffers
at low samplerates by compensating for the interpolation filter delays.

Signed-off-by: AndreiGrozav <andrei.grozav@analog.com>
  • Loading branch information
AndreiGrozav committed Sep 9, 2024
1 parent 4c613e2 commit 130fe9a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 24 deletions.
11 changes: 6 additions & 5 deletions library/axi_ad9963/axi_ad9963_tx_channel.v
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ***************************************************************************
// ***************************************************************************
// Copyright (C) 2017-2023 Analog Devices, Inc. All rights reserved.
// Copyright (C) 2017-2024 Analog Devices, Inc. All rights reserved.
//
// In this HDL repository, there are many different and unique modules, consisting
// of various HDL (Verilog or VHDL) components. The individual modules are
Expand Down Expand Up @@ -88,7 +88,6 @@ module axi_ad9963_tx_channel #(
// internal registers

reg dac_valid_sel = 'd0;
reg data_source_valid = 'd0;
reg [23:0] dac_test_data = 'd0;
reg [15:0] dac_test_counter = 'd0;
reg [15:0] dac_pat_data = 'd0;
Expand All @@ -111,27 +110,29 @@ module axi_ad9963_tx_channel #(
wire dac_iqcor_enb_s;
wire [15:0] dac_iqcor_coeff_1_s;
wire [15:0] dac_iqcor_coeff_2_s;
wire data_source_valid_s;

// dac iq correction

always @(posedge dac_clk) begin
data_source_valid <= dac_data_sel_s == 4'h2 ? dma_valid_m : dac_valid;
dac_enable <= (dac_data_sel_s == 4'h2) ? 1'b1 : 1'b0;
if (dac_iqcor_valid_s == 1'b1) begin
dac_data <= dac_iqcor_data_s[15:4];
end
end

assign data_source_valid_s = dac_data_sel_s == 4'h2 ? dma_valid_m : dac_valid;

generate
if (DATAPATH_DISABLE == 1) begin
assign dac_iqcor_valid_s = data_source_valid;
assign dac_iqcor_valid_s = data_source_valid_s;
assign dac_iqcor_data_s = {dac_data_out, 4'd0};
end else begin
ad_iqcor #(
.Q_OR_I_N (Q_OR_I_N)
) i_ad_iqcor (
.clk (dac_clk),
.valid (data_source_valid),
.valid (data_source_valid_s),
.data_in ({dac_data_out, 4'd0}),
.data_iq ({dac_data_in, 4'd0}),
.valid_out (dac_iqcor_valid_s),
Expand Down
52 changes: 33 additions & 19 deletions library/axi_dac_interpolate/axi_dac_interpolate_filter.v
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,17 @@ module axi_dac_interpolate_filter #(
reg cic_change_rate;
reg [31:0] interpolation_counter;

reg filter_enable = 1'b0;
reg [15:0] dma_valid_m = 16'd0;
reg [15:0] reset_filt_m = 16'd0;
reg stop_transfer = 1'd0;
reg clear_stop_flag = 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;
reg last_m = 1'd0;
reg dac_int_ready_residual;

// internal signals

Expand Down Expand Up @@ -128,8 +130,6 @@ module axi_dac_interpolate_filter #(
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;

Expand Down Expand Up @@ -175,10 +175,6 @@ module axi_dac_interpolate_filter #(
end
end

// - for start synchronized, wait until the DMA has valid data on both channels
// - for non synchronized channels the start of transmission gets the 2 data
// paths randomly ready, only when using data buffers

always @(posedge dac_clk) begin
if (dac_filt_int_valid & transfer_ready) begin
if (interpolation_counter == interpolation_ratio) begin
Expand All @@ -194,13 +190,22 @@ module axi_dac_interpolate_filter #(
end
end

always @(posedge dac_clk) begin
last_m <= last;
end

// - for start synchronized, wait until the DMA has valid data on both channels
// - for non synchronized channels the start of transmission gets the 2 data
// paths randomly ready, only when using data buffers

assign transfer_ready = start_sync_channels ?
dma_valid & dma_valid_adjacent :
dma_valid;
assign transfer_start = !(en_start_trigger ^ trigger) &
transfer_ready & !dma_transfer_suspend;

assign rearm_channel = last & rearm_on_last;
assign rearm_channel = ~last_m & last & rearm_on_last; // re-arm on last rise

always @(posedge dac_clk) begin
stop_transfer <= transfer_sm == IDLE ? 1'b0 :
(stop_transfer & !clear_stop_flag) |
Expand Down Expand Up @@ -258,29 +263,38 @@ module axi_dac_interpolate_filter #(

always @(posedge dac_clk) begin
if (dac_rst == 1'b1) begin
dma_valid_m <= 'd0;
dma_valid_m <= 16'h0;
end else begin
dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch};
if (dac_filt_int_valid == 1'b1) begin
dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch};
end
end
end

assign dac_valid_out = dma_valid_m[2];

always @(posedge dac_clk) begin
case (filter_mask)
3'b000: filter_enable <= 1'b0;
default: filter_enable <= 1'b1;
endcase
if (dac_rst == 1'b1) begin
reset_filt_m <= 16'hffff;
end else begin
if (dac_filt_int_valid == 1'b1) begin
reset_filt_m <= {reset_filt_m[14:0], dma_transfer_suspend};
end else if (dma_transfer_suspend == 1'b0) begin
reset_filt_m <= 16'h0;
end
end
end

// compensate fir cic filter
assign dac_valid_out = |filter_mask ? dma_valid_m[13] : dma_valid_m[2];
assign reset_filt = !raw_dma_n & reset_filt_m[13];

always @(*) begin
case (filter_enable)
1'b0: dac_int_data = dac_data_corrected;
case (filter_mask)
3'b000: dac_int_data = dac_data_corrected;
default: dac_int_data = dac_cic_data[31:16];
endcase

case (filter_mask)
1'b0: dac_filt_int_valid = dac_valid_corrected & !dma_transfer_suspend;
1'b0: dac_filt_int_valid = dac_valid_corrected;
default: dac_filt_int_valid = dac_fir_valid;
endcase

Expand Down

0 comments on commit 130fe9a

Please sign in to comment.