ad_dds: Fix noise caused by dac_data_sync

For projects where the clock ratio between the sampling clock and core clock
is higher than 2, the ad_dds generates a number of samples equal with
the clock ratio. There is a phase offset between the samples, proportional
with the requested DDS frequency.
In scenarios where the DDS out frequency is closer to the upper
limit(Nyquist) and/or the clock ratio is also greater than 2 and the
dac_data_sync reminds low for an extended period of time, the DAC will
receive at each core clock period, a number of samples equal with the
clock ratio and with an amplitude influenced by the DDS out frequency.
In most cases similar with a sawtooth signal.

With this commit we ensures that samples received by the DAC are 0 for
the period where dac_data_sync signal is high. Only when the signal
transitions to low, the phase accumulator is initialized and the phase
information is passed to the phase to amplitude converter.

Another issue can appear when the sync signal is too short; less then
CLK_RATIO * clock cycles. Because the phase accumulator will not
synchronize at all stages, the final result will be a random combination of
sine-waves. Added a minimum sync pulse after the dac_data_sync is set
low.
main
AndreiGrozav 2020-07-24 21:18:29 +03:00 committed by AndreiGrozav
parent 6ca6257341
commit a7a131cb36
1 changed files with 38 additions and 11 deletions

View File

@ -70,6 +70,8 @@ module ad_dds #(
wire [DDS_DW*CLK_RATIO-1:0] dac_dds_data_s;
reg dac_data_sync_m = 1'd0;
always @(posedge clk) begin
dac_dds_data <= dac_dds_data_s;
end
@ -87,26 +89,51 @@ module ad_dds #(
reg [PHASE_DW-1:0] dac_dds_phase_1[1:CLK_RATIO];
reg [PHASE_DW-1:0] dac_dds_incr_0 = 'd0;
reg [PHASE_DW-1:0] dac_dds_incr_1 = 'd0;
reg sync_min_pulse_m[1:CLK_RATIO];
// For scenarios where the synchronization signal comes from an external
// source and it is high for a longer period of time, the phase
// accumulator stages must be reset, in order to avoid a noise like
// signal caused by sending all the summed outputs of each DDS stage.
// There is a minimum synchronization pulse width of n clock cycles,
// that is required to synchronize all phase accumulator stages.
// Where n is equal to the CLK_RATIO.
always @(posedge clk) begin
dac_data_sync_m <= dac_data_sync;
sync_min_pulse_m[1] <= dac_data_sync_m & !dac_data_sync |
sync_min_pulse_m[1] & !sync_min_pulse_m[CLK_RATIO];
end
for (i=1; i <= CLK_RATIO; i=i+1) begin: sync_delay
always @(posedge clk) begin
sync_min_pulse_m[i+1] <= sync_min_pulse_m[i];
end
end
always @(posedge clk) begin
dac_dds_incr_0 <= tone_1_freq_word * CLK_RATIO;
dac_dds_incr_1 <= tone_2_freq_word * CLK_RATIO;
end
// phase accumulator
// phase accumulator
for (i=1; i <= CLK_RATIO; i=i+1) begin: dds_phase
always @(posedge clk) begin
if (dac_data_sync == 1'b1) begin
if (i == 1) begin
dac_dds_phase_0[1] <= tone_1_init_offset;
dac_dds_phase_1[1] <= tone_2_init_offset;
end else if (CLK_RATIO > 1)begin
dac_dds_phase_0[i] <= dac_dds_phase_0[i-1] + tone_1_freq_word;
dac_dds_phase_1[i] <= dac_dds_phase_1[i-1] + tone_2_freq_word;
if (dac_valid == 1'b1) begin
if (dac_data_sync == 1'b1) begin
dac_dds_phase_0[i] <= 'd0;
dac_dds_phase_1[i] <= 'd0;
end else if (sync_min_pulse_m[1] == 1'b1) begin
if (i == 1) begin
dac_dds_phase_0[1] <= tone_1_init_offset;
dac_dds_phase_1[1] <= tone_2_init_offset;
end else if (CLK_RATIO > 1)begin
dac_dds_phase_0[i] <= dac_dds_phase_0[i-1] + tone_1_freq_word;
dac_dds_phase_1[i] <= dac_dds_phase_1[i-1] + tone_2_freq_word;
end
end else begin
dac_dds_phase_0[i] <= dac_dds_phase_0[i] + dac_dds_incr_0;
dac_dds_phase_1[i] <= dac_dds_phase_1[i] + dac_dds_incr_1;
end
end else if (dac_valid == 1'b1) begin
dac_dds_phase_0[i] <= dac_dds_phase_0[i] + dac_dds_incr_0;
dac_dds_phase_1[i] <= dac_dds_phase_1[i] + dac_dds_incr_1;
end
end