Skip to content

Commit

Permalink
working on timetagging discriminating buffer test. have a pretty good…
Browse files Browse the repository at this point in the history
… idea of how the test is gonna go
  • Loading branch information
reed-foster committed Dec 1, 2023
1 parent 8642f99 commit bbc15dc
Showing 1 changed file with 176 additions and 50 deletions.
226 changes: 176 additions & 50 deletions dds_test.srcs/sim_1/new/timetagging_discriminating_buffer_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import sim_util_pkg::*;
`timescale 1ns / 1ps
module timetagging_discriminating_buffer_test ();

sim_util_pkg::generic #(int) util;

logic clk = 0;
localparam CLK_RATE_HZ = 100_000_000;
always #(0.5s/CLK_RATE_HZ) clk = ~clk;
Expand All @@ -19,11 +21,16 @@ localparam int PARALLEL_SAMPLES = 1;
localparam int SAMPLE_WIDTH = 16;
localparam int APPROX_CLOCK_WIDTH = 48;

// derived parameters
localparam int SAMPLE_INDEX_WIDTH = $clog2(DATA_BUFFER_DEPTH*N_CHANNELS);
localparam int TIMESTAMP_WIDTH = SAMPLE_WIDTH * ((SAMPLE_INDEX_WIDTH + APPROX_CLOCK_WIDTH + (SAMPLE_WIDTH - 1)) / SAMPLE_WIDTH);

localparam int DMA_WORD_PARSE_WIDTH = util.max(2*TIMESTAMP_WIDTH, 2*PARALLEL_SAMPLES*SAMPLE_WIDTH);

Axis_Parallel_If #(.DWIDTH(PARALLEL_SAMPLES*SAMPLE_WIDTH), .PARALLEL_CHANNELS(N_CHANNELS)) data_in ();
Axis_If #(.DWIDTH(AXI_MM_WIDTH)) data_out ();
Axis_If #(.DWIDTH(2+$clog2($clog2(N_CHANNELS)+1))) buffer_config_in ();
Axis_If #(.DWIDTH(N_CHANNELS*SAMPLE_WIDTH*2)) discriminator_config_in();
logic [31:0] timestamp_width;

logic start, stop;
logic [$clog2($clog2(N_CHANNELS)+1)-1:0] banking_mode;
Expand All @@ -48,13 +55,15 @@ timetagging_discriminating_buffer #(
) dut_i (
.clk,
.reset,
.timestamp_width,
.timestamp_width(),
.data_in,
.data_out,
.discriminator_config_in,
.buffer_cfg_in,
.buffer_cfg_in
);

logic update_input_data;
logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] data_range_low, data_range_high;
logic [PARALLEL_SAMPLES*SAMPLE_WIDTH-1:0] data_sent [N_CHANNELS][$];
logic [AXI_MM_WIDTH-1:0] data_received [$];

Expand All @@ -71,6 +80,11 @@ always @(posedge clk) begin
end
// save data that was sent
data_sent[i].push_front(data_in.data[i]);
end else if (update_input_data) begin
// send new data
for (int j = 0; j < PARALLEL_SAMPLES; j++) begin
data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH] <= $urandom_range({SAMPLE_WIDTH{1'b1}});
end
end
end
end
Expand All @@ -80,59 +94,177 @@ always @(posedge clk) begin
end
end

task check_results(input int banking_mode, input bit missing_ok);
logic [SAMPLE_WIDTH*PARALLEL_SAMPLES:0] temp_sample;
int current_channel, n_samples;
task check_results(
input int banking_mode,
input logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_high,
input logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_low
);
// checks that:
// - all data received belongs to the proper channels
// - timestamps line up with when samples were sent
// - all inputs > threshold_high were saved and all inputs < threshold_low
// were not
// - all samples < threshold_high that were saved arrived in sequence after
// a sample > threshold_high

// data structures for organizing DMA output
logic [AXI_MM_WIDTH-1:0] dma_word;
int dma_word_leftover_bits;
int current_channel, words_remaining;
int parsed_bank_count;
int word_width;
bit need_channel_id, need_word_count;
enum {TIMESTAMP, DATA} parse_mode;
logic [TIMESTAMP_WIDTH-1:0] timestamps [N_CHANNELS][$];
logic [SAMPLE_WIDTH*PARALLEL_SAMPLES-1:0] samples [N_CHANNELS][$];

// first report the size of the buffers
for (int i = 0; i < N_CHANNELS; i++) begin
$display("data_sent[%0d].size() = %0d", i, data_sent[i].size());
end
$display("data_received.size() = %0d", data_received.size());
while (data_received.size() > 0) begin
current_channel = data_received.pop_back();
n_samples = data_received.pop_back();
$display("processing new bank with %0d samples from channel %0d", n_samples, current_channel);
for (int i = 0; i < n_samples; i++) begin
if (data_sent[current_channel][$] != data_received[$]) begin
$display("data mismatch error (channel = %0d, sample = %0d, received %x, sent %x)", current_channel, i, data_received[$], data_sent[current_channel][$]);
error_count = error_count + 1;

// organize DMA output into data structures for easier analysis
dma_word_leftover_bits = 0;
word_width = TIMESTAMP_WIDTH;
parse_mode = TIMESTAMP;
dma_word = '0;
need_channel_id = 1'b1;
need_word_count = 1'b1;
parsed_bank_count = 0;
while (!done_parsing) begin
// combine remaining bits with new word
dma_word = (data_received.pop_back() << dma_word_leftover_bits) | dma_word;
dma_word_leftover_bits = dma_word_leftover_bits + AXI_MM_WIDTH;
while (dma_word_leftover_bits >= word_width) begin
// data is always organized as so:
// [channel_id, tstamp_count, tstamp_0, ..., channel_id, tstamp_count, ...]
// so first update the channel ID, then update the number of timestamps
// to add to that channel, then finally collect those timestamps
if (need_channel_id) begin
// mask lower bits depending on whether we're parsing timestamps or data
current_channel = dma_word & ((1'b1 << word_width) - 1);
need_channel_id = 1'b0;
need_word_count = 1'b1;
end else begin
if (need_word_count) begin
// mask lower bits depending on whether we're parsing timestamps or data
words_remaining = dma_word & ((1'b1 << word_width) - 1);
need_word_count = 1'b0;
end else begin
unique case (parse_mode)
TIMESTAMP: begin
// mask lower bits based on timestamp width
timestamps[current_channel].push_front(dma_word & ((1'b1 << word_width) - 1));
end
DATA: begin
// mask lower bits based on data width
samples[current_channel].push_front(dma_word & ((1'b1 << word_width) - 1));
end
words_remaining = words_remaining - 1;
end
// check if we have read all the timestamps or data
if (words_remaining == 0) begin
need_channel_id = 1'b1;
parsed_bank_count = parsed_bank_count + 1;
end
end
// check if we're done with all channels
if (parsed_bank_count == N_CHANNELS) begin
// if we're done with all channels, but we were in the timestamp mode,
// then shift to data mode
if (parse_mode == TIMESTAMP) begin
word_width = SAMPLE_WIDTH*PARALLEL_SAMPLES;
parse_mode = DATA;
end else begin
done = 1;
end
// reset DMA word, the rest of the word is garbage; the data
// information will come on the next word
dma_word = '0;
dma_word_leftover_bits = 0;
parsed_bank_count = 0;
end else begin
dma_word = dma_word >> word_width;
dma_word_leftover_bits = dma_word_leftover_bits - word_width;
end
data_sent[current_channel].pop_back();
data_received.pop_back();
end
end
for (int i = 0; i < (1 << banking_mode); i++) begin
// make sure there are no remaining samples in data_sent queues
// corresponding to channels which are enabled as per banking_mode
// caveat: if one of the channels filled up, then it's okay for there to
// be missing samples in the other channels
if ((data_sent[i].size() > 0) & (!missing_ok)) begin
$warning("leftover samples in data_sent[%0d]: %0d", i, data_sent[i].size());
error_count = error_count + 1;
end
while (data_sent[i].size() > 0) data_sent[i].pop_back();
end
for (int i = (1 << banking_mode); i < N_CHANNELS; i++) begin
// flush out any remaining samples in data_sent queue
$display("removing %0d samples from data_sent[%0d]", data_sent[i].size(), i);
while (data_sent[i].size() > 0) data_sent[i].pop_back();

// report the number of timestamps and samples for each channel
for (int i = 0; i < N_CHANNELS; i++) begin
$display("timestamps[%0d].size() = %0d", i, timestamps[i].size());
$display("samples[%0d].size() = %0d", i, samples[i].size());
end

endtask



// current_channel = data_received.pop_back();
// // check if current_channel is valid for banking mode
// if (current_channel >= (1'b1 << banking_mode)) begin
// $warning(
// "invalid channel id (%d) for current banking mode (%d)",
// current_channel,
// banking_mode
// );
// error_count = error_count + 1;
// end
// n_samples = data_received.pop_back();
// $display(
// "processing new bank with %0d samples from channel %0d",
// n_samples,
// current_channel
// );
// for (int i = 0; i < n_samples; i++) begin
// if (data_sent[current_channel][$] != data_received[$]) begin
// $display(
// "data mismatch error (channel = %0d, sample = %0d, received %x, sent %x)",
// current_channel,
// i,
// data_received[$],
// data_sent[current_channel][$]
// );
// error_count = error_count + 1;
// end
// data_sent[current_channel].pop_back();
// data_received.pop_back();
// end
// end
// for (int i = 0; i < (1 << banking_mode); i++) begin
// // make sure there are no remaining samples in data_sent queues
// // corresponding to channels which are enabled as per banking_mode
// // caveat: if one of the channels filled up, then it's okay for there to
// // be missing samples in the other channels
// if (data_sent[i].size() > 0) begin
// $warning("leftover samples in data_sent[%0d]: %0d", i, data_sent[i].size());
// error_count = error_count + 1;
// end
// while (data_sent[i].size() > 0) data_sent[i].pop_back();
// end
// for (int i = (1 << banking_mode); i < N_CHANNELS; i++) begin
// // flush out any remaining samples in data_sent queue
// $display("removing %0d samples from data_sent[%0d]", data_sent[i].size(), i);
// while (data_sent[i].size() > 0) data_sent[i].pop_back();
// end
//endtask

task start_acq_with_banking_mode(input int mode);
start <= 1'b1;
banking_mode <= mode;
buffer_config_inconfig_in.valid <= 1'b1;
buffer_config_in.valid <= 1'b1;
@(posedge clk);
buffer_config_in.valid <= 1'b0;
start <= 1'b0;
config_in.valid <= 1'b0;
endtask

task stop_acq();
stop <= 1'b1;
start <= 1'b0;
config_in.valid <= 1'b1;
buffer_config_in.valid <= 1'b1;
@(posedge clk);
config_in.valid <= 1'b0;
buffer_config_in.valid <= 1'b0;
start <= 1'b0;
stop <= 1'b0;
endtask
Expand Down Expand Up @@ -189,9 +321,12 @@ initial begin
end
end
endcase
disc_config_in.valid <= 1'b1;
// write the new threshold to the discriminator and update the input data
discriminator_config_in.valid <= 1'b1;
update_input_data <= 1'b1;
@(posedge clk);
disc_config_in.valid <= 1'b0;
discriminator_config_in.valid <= 1'b0;
update_input_data <= 1'b0;

repeat (10) @(posedge clk);
start_acq_with_banking_mode(bank_mode);
Expand All @@ -201,18 +336,11 @@ initial begin
stop_acq();
data_out.do_readout(clk, 1'b1, 100000);
$display("######################################################");
$display("# checking results n_samples = %d", samples_to_send);
$display("# banking mode = %d", bank_mode);
$display("# samples sent with rand_valid = %d", in_valid_rand);
$display("# checking results amplitude_mode = %d", amplitude_mode);
$display("# banking mode = %d", bank_mode);
$display("# samples sent with rand_valid = %d", in_valid_rand);
$display("######################################################");
// The second argument of check_results is if it's okay for there to
// be missing samples that weren't stored.
// When data_in.valid is randomly toggled on and off and enough samples
// are sent to fill up all the banks, one of the banks will likely
// fill up before the others are done, triggering a stop condition for
// the other banks before they are full.
// This results in "missing" samples that aren't saved
check_results(bank_mode, (samp_count == 2) & (in_valid_rand == 1));
check_results(bank_mode, threshold_low, threshold_high);
end
end
end
Expand All @@ -229,5 +357,3 @@ initial begin
end

endmodule


0 comments on commit bbc15dc

Please sign in to comment.