axi_dac_interpolate: Fix channel sync mechanism

The previous channel sync mechanism was simply holding the transmission by
pulling down the dma_rd_en of the two DMAs for each channel(set reg 0x50). After a
period of time (that will take the two DMAs to have the data ready to move)
the dma_rd_en was set for both channels, resulting in a synchronized start.
  This mechanism is valid when the two channels are streaming the same
type of data (constant, waveform, buffer or math) at close frequencies.
Streaming 10MHz on a channel and 100KHz on the second one will result
in different interpolation factors being used for the two channels.
  The interpolation counter runs only when the dma_transfer_suspended(reg 0x50)
is cleared. Because of this, different delays are added by the interpolation
counter one DMA with continuous dma_rd_en will have data earlier than the
one with dma_rd_en controlled by the interpolation counter. Furthermore,
because the interpolation counter value is not reset at each
dma_transfer_suspended, the phase shift between the 2 channels will
differ at each start of transmission.

  To make the transfer start synced immune to the above irregularities a
sync_transfer_start register was added (bit 1 of the 0x50 reg).
When this bit is set and the bit 0(dma_transfer_suspended) is toggled,
the interpolation counters are reset. Each channel enables it's DMA until
valid data is received, then it waits for the adjacent channel to get valid data.
This mechanism will be simplified in a future update by using a streaming
interface between the axi_dac_interpolate and the DMAs that does not require
the probing of the DMA.
main
AndreiGrozav 2019-08-05 10:44:21 +03:00 committed by AndreiGrozav
parent 53f466a93e
commit 245f3f9704
3 changed files with 68 additions and 16 deletions

View File

@ -47,6 +47,9 @@ module axi_dac_interpolate #(
input dac_valid_a,
input dac_valid_b,
input dma_valid_a,
input dma_valid_b,
output [15:0] dac_int_data_a,
output [15:0] dac_int_data_b,
output dac_int_valid_a,
@ -95,6 +98,7 @@ module axi_dac_interpolate #(
wire [ 2:0] filter_mask_b;
wire dma_transfer_suspend;
wire start_sync_channels;
wire dac_correction_enable_a;
wire dac_correction_enable_b;
@ -121,6 +125,9 @@ module axi_dac_interpolate #(
.filter_mask (filter_mask_a),
.interpolation_ratio (interpolation_ratio_a),
.dma_transfer_suspend (dma_transfer_suspend),
.start_sync_channels (start_sync_channels),
.dma_valid (dma_valid_a),
.dma_valid_adjacent (dma_valid_b),
.dac_correction_enable(dac_correction_enable_a),
.dac_correction_coefficient(dac_correction_coefficient_a)
);
@ -140,6 +147,9 @@ module axi_dac_interpolate #(
.filter_mask (filter_mask_b),
.interpolation_ratio (interpolation_ratio_b),
.dma_transfer_suspend (dma_transfer_suspend),
.start_sync_channels (start_sync_channels),
.dma_valid (dma_valid_b),
.dma_valid_adjacent (dma_valid_a),
.dac_correction_enable(dac_correction_enable_b),
.dac_correction_coefficient(dac_correction_coefficient_b)
);
@ -154,6 +164,7 @@ module axi_dac_interpolate #(
.dac_filter_mask_b (filter_mask_b),
.dma_transfer_suspend (dma_transfer_suspend),
.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),

View File

@ -47,23 +47,31 @@ module axi_dac_interpolate_filter #(
input dac_valid,
output reg [15:0] dac_int_data,
output reg dac_int_valid,
output dac_int_valid,
input [ 2:0] filter_mask,
input [31:0] interpolation_ratio,
input [15:0] dac_correction_coefficient,
input dac_correction_enable,
input dma_transfer_suspend
input dma_transfer_suspend,
input start_sync_channels,
input dma_valid,
input dma_valid_adjacent
);
// internal signals
reg dac_int_valid_d;
reg dac_filt_int_valid;
reg [15:0] interp_rate_cic;
reg [ 2:0] filter_mask_d1;
reg cic_change_rate;
reg [31:0] interpolation_counter;
reg transmit_valid = 1'b1;
reg dma_data_valid = 1'b0;
reg dma_data_valid_adjacent = 1'b0;
reg filter_enable = 1'b0;
wire dac_valid_corrected;
@ -71,6 +79,7 @@ module axi_dac_interpolate_filter #(
wire dac_fir_valid;
wire [35:0] dac_fir_data;
wire dac_cic_valid;
wire [109:0] dac_cic_data;
@ -115,24 +124,50 @@ module axi_dac_interpolate_filter #(
end
end
// - for start synchronized, if the channels run until the DMA has data valid
// then if the case wait for second channel DMA to have valid data
// - for non synchronized channels the start of transmission gets the 2 data
// paths randomly ready. Only valid for the case of loading data buffers
always @(posedge dac_clk) begin
if (interpolation_ratio == 0 || interpolation_ratio == 1) begin
dac_int_valid <= dac_filt_int_valid;
dac_int_valid_d <= dac_filt_int_valid;
end else begin
if (dac_filt_int_valid == 1'b1) begin
if (interpolation_counter < interpolation_ratio) begin
if (dac_filt_int_valid &
(!start_sync_channels | !dma_data_valid |
(dma_data_valid & dma_data_valid_adjacent))) begin
if (interpolation_counter < interpolation_ratio) begin
interpolation_counter <= interpolation_counter + 1;
dac_int_valid <= 1'b0;
dac_int_valid_d <= 1'b0;
end else begin
interpolation_counter <= 0;
dac_int_valid <= 1'b1;
dac_int_valid_d <= 1'b1;
end
end else begin
dac_int_valid <= 1'b0;
dac_int_valid_d <= 1'b0;
interpolation_counter <= 0;
end
end
end
always @(posedge dac_clk) begin
if (dma_transfer_suspend) begin
dma_data_valid <= 1'b0;
dma_data_valid_adjacent <= 1'b0;
end else begin
dma_data_valid <= dma_valid ? 1'b1 : dma_data_valid;
dma_data_valid_adjacent <= dma_valid_adjacent ? 1'b1 : dma_data_valid_adjacent;
end
if (start_sync_channels == 1'b0) begin
transmit_valid <= 1'b1;
end else begin
transmit_valid <= (dma_data_valid & dma_data_valid_adjacent) ? 1'b1 : ~dma_data_valid;
end
end
assign dac_int_valid = transmit_valid ? dac_int_valid_d : 1'b0;
always @(posedge dac_clk) begin
case (filter_mask)
3'b000: filter_enable <= 1'b0;

View File

@ -44,6 +44,7 @@ module axi_dac_interpolate_reg(
output [31:0] dac_interpolation_ratio_b,
output [ 2:0] dac_filter_mask_b,
output dma_transfer_suspend,
output start_sync_channels,
output dac_correction_enable_a,
output dac_correction_enable_b,
output [15:0] dac_correction_coefficient_a,
@ -64,18 +65,23 @@ module axi_dac_interpolate_reg(
// internal registers
reg [31:0] up_version = 32'h00020000;
reg [31:0] up_version = 32'h00020100;
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 up_flags = 32'h0;
reg [1:0] up_flags = 2'h2;
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;
wire [ 1:0] flags;
assign dma_transfer_suspend = flags[0];
assign start_sync_channels = flags[1];
always @(negedge up_rstn or posedge up_clk) begin
if (up_rstn == 0) begin
up_wack <= 'd0;
@ -84,7 +90,7 @@ module axi_dac_interpolate_reg(
up_filter_mask_a <= 'd0;
up_interpolation_ratio_b <= 'd0;
up_filter_mask_b <= 'd0;
up_flags <= 'd0;
up_flags <= 'd2;
up_config <= 'd0;
up_correction_coefficient_a <= 'd0;
up_correction_coefficient_b <= 'd0;
@ -106,7 +112,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 <= {31'h0,up_wdata[0]};
up_flags <= {30'h0,up_wdata[1:0]};
end
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h15)) begin
up_config <= up_wdata[1:0];
@ -136,7 +142,7 @@ 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 <= {31'h0,up_flags};
5'h14: up_rdata <= {30'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};
@ -148,14 +154,14 @@ module axi_dac_interpolate_reg(
end
end
up_xfer_cntrl #(.DATA_WIDTH(105)) i_xfer_cntrl (
up_xfer_cntrl #(.DATA_WIDTH(106)) i_xfer_cntrl (
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_data_cntrl ({ up_config[1], // 1
up_config[0], // 1
up_correction_coefficient_b,// 16
up_correction_coefficient_a,// 16
up_flags, // 1
up_flags, // 2
up_interpolation_ratio_b, // 32
up_interpolation_ratio_a, // 32
up_filter_mask_b, // 3
@ -168,7 +174,7 @@ module axi_dac_interpolate_reg(
dac_correction_enable_a, // 1
dac_correction_coefficient_b, // 16
dac_correction_coefficient_a, // 16
dma_transfer_suspend, // 1
flags, // 2
dac_interpolation_ratio_b, // 32
dac_interpolation_ratio_a, // 32
dac_filter_mask_b, // 3