Skip to content

Commit 130fe9a

Browse files
committed
m2k:axi_ad9963, axi_dac_interpolate fixes
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>
1 parent 4c613e2 commit 130fe9a

File tree

2 files changed

+39
-24
lines changed

2 files changed

+39
-24
lines changed

library/axi_ad9963/axi_ad9963_tx_channel.v

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// ***************************************************************************
22
// ***************************************************************************
3-
// Copyright (C) 2017-2023 Analog Devices, Inc. All rights reserved.
3+
// Copyright (C) 2017-2024 Analog Devices, Inc. All rights reserved.
44
//
55
// In this HDL repository, there are many different and unique modules, consisting
66
// of various HDL (Verilog or VHDL) components. The individual modules are
@@ -88,7 +88,6 @@ module axi_ad9963_tx_channel #(
8888
// internal registers
8989

9090
reg dac_valid_sel = 'd0;
91-
reg data_source_valid = 'd0;
9291
reg [23:0] dac_test_data = 'd0;
9392
reg [15:0] dac_test_counter = 'd0;
9493
reg [15:0] dac_pat_data = 'd0;
@@ -111,27 +110,29 @@ module axi_ad9963_tx_channel #(
111110
wire dac_iqcor_enb_s;
112111
wire [15:0] dac_iqcor_coeff_1_s;
113112
wire [15:0] dac_iqcor_coeff_2_s;
113+
wire data_source_valid_s;
114114

115115
// dac iq correction
116116

117117
always @(posedge dac_clk) begin
118-
data_source_valid <= dac_data_sel_s == 4'h2 ? dma_valid_m : dac_valid;
119118
dac_enable <= (dac_data_sel_s == 4'h2) ? 1'b1 : 1'b0;
120119
if (dac_iqcor_valid_s == 1'b1) begin
121120
dac_data <= dac_iqcor_data_s[15:4];
122121
end
123122
end
124123

124+
assign data_source_valid_s = dac_data_sel_s == 4'h2 ? dma_valid_m : dac_valid;
125+
125126
generate
126127
if (DATAPATH_DISABLE == 1) begin
127-
assign dac_iqcor_valid_s = data_source_valid;
128+
assign dac_iqcor_valid_s = data_source_valid_s;
128129
assign dac_iqcor_data_s = {dac_data_out, 4'd0};
129130
end else begin
130131
ad_iqcor #(
131132
.Q_OR_I_N (Q_OR_I_N)
132133
) i_ad_iqcor (
133134
.clk (dac_clk),
134-
.valid (data_source_valid),
135+
.valid (data_source_valid_s),
135136
.data_in ({dac_data_out, 4'd0}),
136137
.data_iq ({dac_data_in, 4'd0}),
137138
.valid_out (dac_iqcor_valid_s),

library/axi_dac_interpolate/axi_dac_interpolate_filter.v

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,17 @@ module axi_dac_interpolate_filter #(
8888
reg cic_change_rate;
8989
reg [31:0] interpolation_counter;
9090

91-
reg filter_enable = 1'b0;
9291
reg [15:0] dma_valid_m = 16'd0;
92+
reg [15:0] reset_filt_m = 16'd0;
9393
reg stop_transfer = 1'd0;
9494
reg clear_stop_flag = 1'd0;
9595

9696
reg transfer = 1'd0;
9797
reg [ 1:0] transfer_sm = 2'd0;
9898
reg [ 1:0] transfer_sm_next = 2'd0;
9999
reg raw_dma_n = 1'd0;
100+
reg last_m = 1'd0;
101+
reg dac_int_ready_residual;
100102

101103
// internal signals
102104

@@ -128,8 +130,6 @@ module axi_dac_interpolate_filter #(
128130
raw_dma_n <= raw_transfer_en | flush_dma ? 1'b1 : raw_dma_n & !dma_valid;
129131
end
130132

131-
assign reset_filt = !raw_dma_n & dma_transfer_suspend;
132-
133133
assign iqcor_data_in = raw_dma_n ? dac_raw_ch_data : dac_data;
134134
assign iqcor_valid_in = raw_dma_n ? 1'b1 : dac_valid;
135135

@@ -175,10 +175,6 @@ module axi_dac_interpolate_filter #(
175175
end
176176
end
177177

178-
// - for start synchronized, wait until the DMA has valid data on both channels
179-
// - for non synchronized channels the start of transmission gets the 2 data
180-
// paths randomly ready, only when using data buffers
181-
182178
always @(posedge dac_clk) begin
183179
if (dac_filt_int_valid & transfer_ready) begin
184180
if (interpolation_counter == interpolation_ratio) begin
@@ -194,13 +190,22 @@ module axi_dac_interpolate_filter #(
194190
end
195191
end
196192

193+
always @(posedge dac_clk) begin
194+
last_m <= last;
195+
end
196+
197+
// - for start synchronized, wait until the DMA has valid data on both channels
198+
// - for non synchronized channels the start of transmission gets the 2 data
199+
// paths randomly ready, only when using data buffers
200+
197201
assign transfer_ready = start_sync_channels ?
198202
dma_valid & dma_valid_adjacent :
199203
dma_valid;
200204
assign transfer_start = !(en_start_trigger ^ trigger) &
201205
transfer_ready & !dma_transfer_suspend;
202206

203-
assign rearm_channel = last & rearm_on_last;
207+
assign rearm_channel = ~last_m & last & rearm_on_last; // re-arm on last rise
208+
204209
always @(posedge dac_clk) begin
205210
stop_transfer <= transfer_sm == IDLE ? 1'b0 :
206211
(stop_transfer & !clear_stop_flag) |
@@ -258,29 +263,38 @@ module axi_dac_interpolate_filter #(
258263

259264
always @(posedge dac_clk) begin
260265
if (dac_rst == 1'b1) begin
261-
dma_valid_m <= 'd0;
266+
dma_valid_m <= 16'h0;
262267
end else begin
263-
dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch};
268+
if (dac_filt_int_valid == 1'b1) begin
269+
dma_valid_m <= {dma_valid_m[14:0], dma_valid_ch};
270+
end
264271
end
265272
end
266273

267-
assign dac_valid_out = dma_valid_m[2];
268-
269274
always @(posedge dac_clk) begin
270-
case (filter_mask)
271-
3'b000: filter_enable <= 1'b0;
272-
default: filter_enable <= 1'b1;
273-
endcase
275+
if (dac_rst == 1'b1) begin
276+
reset_filt_m <= 16'hffff;
277+
end else begin
278+
if (dac_filt_int_valid == 1'b1) begin
279+
reset_filt_m <= {reset_filt_m[14:0], dma_transfer_suspend};
280+
end else if (dma_transfer_suspend == 1'b0) begin
281+
reset_filt_m <= 16'h0;
282+
end
283+
end
274284
end
275285

286+
// compensate fir cic filter
287+
assign dac_valid_out = |filter_mask ? dma_valid_m[13] : dma_valid_m[2];
288+
assign reset_filt = !raw_dma_n & reset_filt_m[13];
289+
276290
always @(*) begin
277-
case (filter_enable)
278-
1'b0: dac_int_data = dac_data_corrected;
291+
case (filter_mask)
292+
3'b000: dac_int_data = dac_data_corrected;
279293
default: dac_int_data = dac_cic_data[31:16];
280294
endcase
281295

282296
case (filter_mask)
283-
1'b0: dac_filt_int_valid = dac_valid_corrected & !dma_transfer_suspend;
297+
1'b0: dac_filt_int_valid = dac_valid_corrected;
284298
default: dac_filt_int_valid = dac_fir_valid;
285299
endcase
286300

0 commit comments

Comments
 (0)