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
parent
53f466a93e
commit
245f3f9704
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue