mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
fpga: Ensure constant initial phase of dds phase accumulator
between bursts Reload the phase accumulator (with registered phase increment) in dds_ms at EoB to maintain constant initial phase between bursts
This commit is contained in:
parent
76ddd382f9
commit
e90b0b4643
@ -118,6 +118,7 @@ module dds_ms
|
||||
logic [SPC:0] din_tuser;
|
||||
logic din_tvalid;
|
||||
logic din_transfer_complete;
|
||||
logic eob_transfer;
|
||||
|
||||
// Phase increment
|
||||
logic [PHASE_WIDTH-1:0] phase_inc_tdata = '0;
|
||||
@ -199,6 +200,14 @@ module dds_ms
|
||||
current_state <= WAIT_FOR_TAG;
|
||||
phase_update_pending <= '1;
|
||||
end
|
||||
end else if (eob_transfer) begin
|
||||
// Reuse the phase-update path to reload the accumulator at EoB while
|
||||
// retaining the configured phase increment. The following burst
|
||||
// remains stalled until the LUT has flushed stale values following the
|
||||
// reload event.
|
||||
timed_update_pending <= 1'b0;
|
||||
phase_update_pending <= 1'b1;
|
||||
current_state <= UPDATE_ACCUMULATOR;
|
||||
end
|
||||
end
|
||||
// Wait for data transfer to start blocking
|
||||
@ -268,7 +277,9 @@ module dds_ms
|
||||
// available.
|
||||
|
||||
assign din_transfer_complete = (din_tvalid && din_tready[0]) || !din_tvalid;
|
||||
assign data_lock = (!timed_update_pending || (din_tvalid && din_tuser[SPC:1] != '0)) && phase_update_pending;
|
||||
assign eob_transfer = din_tvalid && din_tready[0] && din_tlast && din_tuser[0];
|
||||
assign data_lock = (!timed_update_pending || (din_tvalid && din_tuser[SPC:1] != '0))
|
||||
&& phase_update_pending;
|
||||
assign flush_enabled = current_state == FLUSH || current_state == UPDATE_ACCUMULATOR;
|
||||
|
||||
|
||||
|
||||
@ -901,17 +901,15 @@ module dds_ms_tb #(
|
||||
test.end_test();
|
||||
endtask : randomize_test
|
||||
|
||||
// Test to verify freq shift once set is applied consistently
|
||||
// across multiple bursts of samples unless changed.
|
||||
// Test to verify that freq shift once set is applied consistently
|
||||
// across multiple bursts of samples unless changed. It also checks that
|
||||
// initial phase of dds-internal phase accumulator is constant (0.0) between bursts.
|
||||
task automatic continuous_run (int repeat_count, stall_config_t stall_cfg);
|
||||
axis_burst_queue_t input_bursts, received_bursts, expected_bursts;
|
||||
axis_pkt_queue_t pkts_in, pkts_out, expected_pkts_out;
|
||||
tone_config_t input_tone_cfg, dut_tone_cfg;
|
||||
logic [PHASE_WIDTH-1:0] phase_in_tdata;
|
||||
logic [CTRLPORT_DATA_W-1:0] write_phase;
|
||||
// Tracks the NCO phase continuously across bursts to match DUT accumulator state
|
||||
real expected_phase = 0.0;
|
||||
|
||||
test.start_test("Continuous Run");
|
||||
write_phase = $urandom_range(MAX_PHASE);
|
||||
phase_in_tdata = write_phase[CTRLPORT_DATA_W-1 -: PHASE_WIDTH];
|
||||
@ -941,11 +939,8 @@ module dds_ms_tb #(
|
||||
pkts_in = generate_burst(.num_pkts(3), .pkt_length(PKT_LENGTH),
|
||||
.tone_cfg(input_tone_cfg), .gen_mode(TONE));
|
||||
expected_pkts_out = generate_expected_output(.num_pkts(3), .pkt_length(PKT_LENGTH),
|
||||
.initial_phase(expected_phase), .tone_cfg(dut_tone_cfg),
|
||||
.initial_phase(0.0), .tone_cfg(dut_tone_cfg),
|
||||
.input_pkt_queue(pkts_in));
|
||||
// Advance expected_phase by the number of words consumed in this burst
|
||||
// (num_pkts * pkt_length words, each advancing phase by freq_norm)
|
||||
expected_phase += 3 * PKT_LENGTH * dut_tone_cfg.freq_norm;
|
||||
input_bursts.push_back(pkts_in);
|
||||
expected_bursts.push_back(expected_pkts_out);
|
||||
|
||||
@ -976,12 +971,6 @@ module dds_ms_tb #(
|
||||
|
||||
int num_pkts = 2;
|
||||
int pkt_length = PKT_LENGTH;
|
||||
// Phase accumulated by the post-tag NCO by the end of the first burst,
|
||||
// used as initial phase for the follow-up burst verification
|
||||
int words_pre_tag = 0;
|
||||
int words_post_tag = 0;
|
||||
real timed_initial_phase = 0.0;
|
||||
|
||||
|
||||
test.start_test($sformatf("Simulated timed DDS test, master stall: %0d, slave stall: %0d",
|
||||
stall_cfg.master_stall_prob, stall_cfg.slave_stall_prob));
|
||||
@ -1069,17 +1058,13 @@ module dds_ms_tb #(
|
||||
// Ensure that the DUT applies the last written frequency shift value if
|
||||
// new phase increment is sent but not valid
|
||||
phase_to_dut.tdata = '0;
|
||||
// Derive the post-tag NCO phase at the end of the previous burst:
|
||||
// the post-tag config becomes active at data_in_tag and runs for the
|
||||
// remaining words in the burst.
|
||||
words_pre_tag = data_in_tag.packet * pkt_length + data_in_tag.word;
|
||||
words_post_tag = num_pkts * pkt_length - words_pre_tag;
|
||||
timed_initial_phase = words_post_tag * timed_dut_tone_cfg.freq_norm;
|
||||
// EOB reloads the accumulator after the preceding burst, so the follow-up
|
||||
// burst starts at phase zero using the post-tag frequency increment.
|
||||
pkts_in = generate_burst(.num_pkts(num_pkts), .pkt_length(pkt_length),
|
||||
.tone_cfg(input_tone_cfg),
|
||||
.gen_mode(RAMP));
|
||||
expected_pkts_out = generate_expected_output(.num_pkts(num_pkts), .pkt_length(pkt_length),
|
||||
.initial_phase(timed_initial_phase), .tone_cfg(timed_dut_tone_cfg),
|
||||
.initial_phase(0.0), .tone_cfg(timed_dut_tone_cfg),
|
||||
.input_pkt_queue(pkts_in));
|
||||
input_bursts.push_back(pkts_in);
|
||||
expected_bursts.push_back(expected_pkts_out);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user