From 77050396724432d0cef5baa098522b5a080203d6 Mon Sep 17 00:00:00 2001 From: Reed Foster Date: Mon, 4 Dec 2023 11:40:27 -0500 Subject: [PATCH] The timetagging discriminating buffer simulation seems to be working. Seems like I'm better at writing RTL than tests, which is slightly concerning --- banked_sample_buffer_test_behav.wcfg | 80 +-- .../timetagging_discriminating_buffer_test.sv | 245 +++++-- .../sources_1/new/banked_sample_buffer.sv | 2 +- .../new/timetagging_discriminating_buffer.sv | 4 +- ...ging_discriminating_buffer_test_behav.wcfg | 620 ++++++++++++++++++ 5 files changed, 837 insertions(+), 114 deletions(-) create mode 100644 timetagging_discriminating_buffer_test_behav.wcfg diff --git a/banked_sample_buffer_test_behav.wcfg b/banked_sample_buffer_test_behav.wcfg index 71f9173..18631b0 100644 --- a/banked_sample_buffer_test_behav.wcfg +++ b/banked_sample_buffer_test_behav.wcfg @@ -11,13 +11,13 @@ - - - + + + - + @@ -51,7 +51,6 @@ dut_i label - clk clk @@ -197,6 +196,7 @@ valid[7:0] valid[7:0] + last[7:0] @@ -272,10 +272,44 @@ DWIDTH[31:0] + + dut_i_all_banks_out + label + + + data[7:0][15:0] + data[7:0][15:0] + + + + ready[7:0] + ready[7:0] + + + valid[7:0] + valid[7:0] + + + last[7:0] + last[7:0] + + + ok[7:0] + ok[7:0] + + + + DWIDTH[31:0] + DWIDTH[31:0] + + + PARALLEL_CHANNELS[31:0] + PARALLEL_CHANNELS[31:0] + + bank_0 label - clk clk @@ -543,40 +577,6 @@ DWIDTH[31:0] - - dut_i_all_banks_out - label - - data[7:0][15:0] - data[7:0][15:0] - - - - ready[7:0] - ready[7:0] - - - valid[7:0] - valid[7:0] - - - last[7:0] - last[7:0] - - - ok[7:0] - ok[7:0] - - - - DWIDTH[31:0] - DWIDTH[31:0] - - - PARALLEL_CHANNELS[31:0] - PARALLEL_CHANNELS[31:0] - - bank_2 label diff --git a/dds_test.srcs/sim_1/new/timetagging_discriminating_buffer_test.sv b/dds_test.srcs/sim_1/new/timetagging_discriminating_buffer_test.sv index c656152..b53461b 100644 --- a/dds_test.srcs/sim_1/new/timetagging_discriminating_buffer_test.sv +++ b/dds_test.srcs/sim_1/new/timetagging_discriminating_buffer_test.sv @@ -27,6 +27,9 @@ localparam int TIMESTAMP_WIDTH = SAMPLE_WIDTH * ((SAMPLE_INDEX_WIDTH + APPROX_CL localparam int DMA_WORD_PARSE_WIDTH = util.max(2*TIMESTAMP_WIDTH, 2*PARALLEL_SAMPLES*SAMPLE_WIDTH); +// util for functions any_above_high and all_below_low for comparing data to thresholds +sim_util_pkg::sample_discriminator_util #(.SAMPLE_WIDTH(SAMPLE_WIDTH), .PARALLEL_SAMPLES(PARALLEL_SAMPLES)) disc_util; + 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 (); @@ -59,13 +62,14 @@ timetagging_discriminating_buffer #( .data_in, .data_out, .discriminator_config_in, - .buffer_cfg_in + .buffer_config_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 [$]; +logic [N_CHANNELS-1:0][TIMESTAMP_WIDTH-SAMPLE_INDEX_WIDTH-1:0] timer; // send data to DUT and save sent/received data always @(posedge clk) begin @@ -74,16 +78,13 @@ always @(posedge clk) begin data_in.data[i] <= '0; end else begin if (data_in.ok[i]) 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 // save data that was sent data_sent[i].push_front(data_in.data[i]); - end else if (update_input_data) begin + end + if (data_in.ok[i] || 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}}); + data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH] <= $urandom_range(data_range_low[i], data_range_high[i]); end end end @@ -97,10 +98,10 @@ end 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 + input logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_low, + inout logic [N_CHANNELS-1:0][TIMESTAMP_WIDTH-SAMPLE_INDEX_WIDTH-1:0] timer ); // 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 @@ -114,17 +115,24 @@ task check_results( int parsed_bank_count; int word_width; bit need_channel_id, need_word_count; + bit done_parsing; enum {TIMESTAMP, DATA} parse_mode; logic [TIMESTAMP_WIDTH-1:0] timestamps [N_CHANNELS][$]; logic [SAMPLE_WIDTH*PARALLEL_SAMPLES-1:0] samples [N_CHANNELS][$]; + // signals for checking correct operation of the DUT + logic is_high; + logic [SAMPLE_INDEX_WIDTH-1:0] sample_index; + // 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()); + /////////////////////////////////////////////////////////////////// // organize DMA output into data structures for easier analysis + /////////////////////////////////////////////////////////////////// dma_word_leftover_bits = 0; word_width = TIMESTAMP_WIDTH; parse_mode = TIMESTAMP; @@ -132,6 +140,7 @@ task check_results( need_channel_id = 1'b1; need_word_count = 1'b1; parsed_bank_count = 0; + done_parsing = 0; while (!done_parsing) begin // combine remaining bits with new word dma_word = (data_received.pop_back() << dma_word_leftover_bits) | dma_word; @@ -161,6 +170,7 @@ task check_results( // mask lower bits based on data width samples[current_channel].push_front(dma_word & ((1'b1 << word_width) - 1)); end + endcase words_remaining = words_remaining - 1; end // check if we have read all the timestamps or data @@ -177,7 +187,7 @@ task check_results( word_width = SAMPLE_WIDTH*PARALLEL_SAMPLES; parse_mode = DATA; end else begin - done = 1; + done_parsing = 1; end // reset DMA word, the rest of the word is garbage; the data // information will come on the next word @@ -191,64 +201,145 @@ task check_results( end end - // 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()); + ///////////////////////////// + // process data + ///////////////////////////// + // first check that we didn't get any extra samples or timestamps + for (int channel = 1 << banking_mode; channel < N_CHANNELS; channel++) begin + if (timestamps[channel].size() > 0) begin + $warning( + "received too many timestamps for channel %0d with banking mode %0d (got %0d, expected 0)", + channel, + banking_mode, + timestamps[channel].size() + ); + error_count = error_count + 1; + end + while (timestamps[channel].size() > 0) timestamps[channel].pop_back(); + if (samples[channel].size() > 0) begin + $warning( + "received too many samples for channel %0d with banking mode %0d (got %0d, expected 0)", + channel, + banking_mode, + samples[channel].size() + ); + error_count = error_count + 1; + end + while (samples[channel].size() > 0) samples[channel].pop_back(); + // clean up data sent + $display("removing %0d samples from data_sent[%0d]", data_sent[channel].size(), channel); + while (data_sent[channel].size() > 0) begin + data_sent[channel].pop_back(); + timer[channel] = timer[channel] + 1'b1; + end end -endtask - - + for (int channel = 0; channel < (1 << banking_mode); channel++) begin + // report timestamp/sample queue sizes + $display("timestamps[%0d].size() = %0d", channel, timestamps[channel].size()); + $display("samples[%0d].size() = %0d", channel, samples[channel].size()); + if (samples[channel].size() > data_sent[channel].size()) begin + $warning( + "too many samples for channel %0d with banking mode %0d: got %0d, expected at most %0d", + channel, + banking_mode, + samples[channel].size(), + data_sent[channel].size() + ); + error_count = error_count + 1; + end + ///////////////////////////// + // check all the samples + ///////////////////////////// + // The sample counter and hysteresis tracking of the sample discriminator + // are reset before each trial. Therefore is_high is reset. + is_high = 0; + sample_index = 0; // index of sample in received samples buffer + while (data_sent[channel].size() > 0) begin + $display( + "processing sample %0d from channel %0d: samp = %0x, timer = %0x", + data_sent[channel].size(), + channel, + data_sent[channel][$], + timer[channel] + ); + if (disc_util.any_above_high(data_sent[channel][$], threshold_high[channel])) begin + $display( + "%x contains a sample greater than %x", + data_sent[channel][$], + threshold_high[channel] + ); + if (!is_high) begin + // new sample, should get a timestamp + if (timestamps[channel].size() > 0) begin + if (timestamps[channel][$] !== {timer[channel], sample_index}) begin + $warning( + "mismatched timestamp: got %x, expected %x", + timestamps[channel][$], + {timer[channel], sample_index} + ); + error_count = error_count + 1; + end + timestamps[channel].pop_back(); + end else begin + $warning( + "expected a timestamp (with value %x), but no more timestamps left", + {timer[channel], sample_index} + ); + error_count = error_count + 1; + end + end + is_high = 1'b1; + end else if (disc_util.all_below_low(data_sent[channel][$], threshold_low[channel])) begin + is_high = 1'b0; + end + if (is_high) begin + if (data_sent[channel][$] !== samples[channel][$]) begin + $warning( + "mismatched data: got %x, expected %x", + samples[channel][$], + data_sent[channel][$] + ); + error_count = error_count + 1; + end + samples[channel].pop_back(); + sample_index = sample_index + 1'b1; + end + data_sent[channel].pop_back(); + timer[channel] = timer[channel] + 1'b1; + end + // check to make sure we didn't miss any data + if (timestamps[channel].size() > 0) begin + $warning( + "too many timestamps leftover for channel %0d with banking mode %0d (got %0d, expected 0)", + channel, + banking_mode, + timestamps[channel].size() + ); + error_count = error_count + 1; + end + // flush out remaining timestamps + while (timestamps[channel].size() > 0) timestamps[channel].pop_back(); + if (samples[channel].size() > 0) begin + $warning( + "too many samples leftover for channel %0d with banking mode %0d (got %0d, expected 0)", + channel, + banking_mode, + samples[channel].size() + ); + error_count = error_count + 1; + end + // flush out remaining samples + while (samples[channel].size() > 0) samples[channel].pop_back(); + // should not be any leftover data_sent samples, since the while loop + // won't terminate until data_sent[channel] is empty. therefore don't + // bother checking + end + for (int channel = 0; channel < N_CHANNELS; channel++) begin + $display("timer[%0d] = %0d (0x%x)", channel, timer[channel], timer[channel]); + end -// 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 +endtask task start_acq_with_banking_mode(input int mode); start <= 1'b1; @@ -273,7 +364,9 @@ initial begin reset <= 1'b1; start <= 1'b0; stop <= 1'b0; - banking_mode <= '0; // only enable channel 0 + timer <= '0; // reset timer for all channels + banking_mode <= '0; // only enable channel 0 to start + data_out.ready <= '0; data_in.valid <= '0; repeat (100) @(posedge clk); reset <= 1'b0; @@ -281,16 +374,16 @@ initial begin for (int in_valid_rand = 0; in_valid_rand < 2; in_valid_rand++) begin for (int bank_mode = 0; bank_mode < 4; bank_mode++) begin - for (int amplitude_mode = 0; amplitude_mode < 4; amplitude_mode++) begin + for (int amplitude_mode = 0; amplitude_mode < 5; amplitude_mode++) begin repeat (10) @(posedge clk); unique case (amplitude_mode) 0: begin // save everything for (int i = 0; i < N_CHANNELS; i++) begin - data_range_low[i] <= 16'h0000; + data_range_low[i] <= 16'h03c0; data_range_high[i] <= 16'h04ff; - threshold_low[i] <= 16'h03c0; - threshold_high[i] <= 16'h0400; + threshold_low[i] <= 16'h0000; + threshold_high[i] <= 16'h0100; end end 1: begin @@ -320,6 +413,15 @@ initial begin threshold_high[i] <= 16'h0400; end end + 5: begin + // send stuff that mostly gets filtered out + for (int i = 0; i < N_CHANNELS; i++) begin + data_range_low[i] <= 16'h0000; + data_range_high[i] <= 16'h04ff; + threshold_low[i] <= 16'h03c0; + threshold_high[i] <= 16'h0400; + end + end endcase // write the new threshold to the discriminator and update the input data discriminator_config_in.valid <= 1'b1; @@ -330,6 +432,7 @@ initial begin repeat (10) @(posedge clk); start_acq_with_banking_mode(bank_mode); + repeat (10) @(posedge clk); data_in.send_samples(clk, $urandom_range(50,500), in_valid_rand & 1'b1, 1'b1); repeat (10) @(posedge clk); @@ -340,7 +443,7 @@ initial begin $display("# banking mode = %d", bank_mode); $display("# samples sent with rand_valid = %d", in_valid_rand); $display("######################################################"); - check_results(bank_mode, threshold_low, threshold_high); + check_results(bank_mode, threshold_high, threshold_low, timer); end end end diff --git a/dds_test.srcs/sources_1/new/banked_sample_buffer.sv b/dds_test.srcs/sources_1/new/banked_sample_buffer.sv index 66206b9..23f996f 100644 --- a/dds_test.srcs/sources_1/new/banked_sample_buffer.sv +++ b/dds_test.srcs/sources_1/new/banked_sample_buffer.sv @@ -32,7 +32,7 @@ always_ff @(posedge clk) begin banking_mode <= '0; end else begin if (config_in.ok) begin - banking_mode <= config_in.data[2+:N_BANKING_MODES]; + banking_mode <= config_in.data[2+:$clog2(N_BANKING_MODES)]; start <= config_in.data[1]; stop <= config_in.data[0]; end else begin diff --git a/dds_test.srcs/sources_1/new/timetagging_discriminating_buffer.sv b/dds_test.srcs/sources_1/new/timetagging_discriminating_buffer.sv index bb7be8e..589c2ef 100644 --- a/dds_test.srcs/sources_1/new/timetagging_discriminating_buffer.sv +++ b/dds_test.srcs/sources_1/new/timetagging_discriminating_buffer.sv @@ -10,7 +10,7 @@ module timetagging_discriminating_buffer #( parameter int APPROX_CLOCK_WIDTH = 48 // requested width of timestamp ) ( input wire clk, reset, - output logic [31:0] timestamp_width, + output logic [31:0] timestamp_width, // output so that PS can correctly parse output data Axis_Parallel_If.Slave_Simple data_in, // all channels in parallel Axis_If.Master_Full data_out, Axis_If.Slave_Simple discriminator_config_in, // {threshold_high, threshold_low} for each channel @@ -67,7 +67,7 @@ sample_discriminator #( .data_out(disc_data), .timestamps_out(disc_timestamps), .config_in(discriminator_config_in), - .sample_index_reset(start & ~start_d) // reset sample_index count whenever a new capture is started + .reset_state(start & ~start_d) // reset sample_index count and is_high whenever a new capture is started ); banked_sample_buffer #( diff --git a/timetagging_discriminating_buffer_test_behav.wcfg b/timetagging_discriminating_buffer_test_behav.wcfg new file mode 100644 index 0000000..a299d0c --- /dev/null +++ b/timetagging_discriminating_buffer_test_behav.wcfg @@ -0,0 +1,620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + test + label + + clk + clk + + + reset + reset + + + error_count[31:0] + error_count[31:0] + + + start + start + + + stop + stop + + + banking_mode[1:0] + banking_mode[1:0] + + + threshold_high[7:0][15:0] + threshold_high[7:0][15:0] + + + threshold_low[7:0][15:0] + threshold_low[7:0][15:0] + + + update_input_data + update_input_data + + + data_range_low[7:0][15:0] + data_range_low[7:0][15:0] + + + data_range_high[7:0][15:0] + data_range_high[7:0][15:0] + + + CLK_RATE_HZ[31:0] + CLK_RATE_HZ[31:0] + + + N_CHANNELS[31:0] + N_CHANNELS[31:0] + + + TSTAMP_BUFFER_DEPTH[31:0] + TSTAMP_BUFFER_DEPTH[31:0] + + + DATA_BUFFER_DEPTH[31:0] + DATA_BUFFER_DEPTH[31:0] + + + AXI_MM_WIDTH[31:0] + AXI_MM_WIDTH[31:0] + + + PARALLEL_SAMPLES[31:0] + PARALLEL_SAMPLES[31:0] + + + SAMPLE_WIDTH[31:0] + SAMPLE_WIDTH[31:0] + + + APPROX_CLOCK_WIDTH[31:0] + APPROX_CLOCK_WIDTH[31:0] + + + SAMPLE_INDEX_WIDTH[31:0] + SAMPLE_INDEX_WIDTH[31:0] + + + TIMESTAMP_WIDTH[31:0] + TIMESTAMP_WIDTH[31:0] + + + DMA_WORD_PARSE_WIDTH[31:0] + DMA_WORD_PARSE_WIDTH[31:0] + + + + data_in + label + + + data[7:0][15:0] + data[7:0][15:0] + + + ready[7:0] + ready[7:0] + + + valid[7:0] + valid[7:0] + + + last[7:0] + last[7:0] + + + ok[7:0] + ok[7:0] + + + DWIDTH[31:0] + DWIDTH[31:0] + + + PARALLEL_CHANNELS[31:0] + PARALLEL_CHANNELS[31:0] + + + + data_out + label + + + data[127:0] + data[127:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + buffer_config_in + label + + data[3:0] + data[3:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + discriminator_config_in + label + + data[255:0] + data[255:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + dut_i + label + + + clk + clk + + + reset + reset + + + timestamp_width[31:0] + timestamp_width[31:0] + + + buffer_full[1:0] + buffer_full[1:0] + + + start + start + + + start_d + start_d + + + buffer_select[31:0] + buffer_select[31:0] + + + timestamps_width + timestamps_width + + + params + label + + N_CHANNELS[31:0] + N_CHANNELS[31:0] + + + TSTAMP_BUFFER_DEPTH[31:0] + TSTAMP_BUFFER_DEPTH[31:0] + + + DATA_BUFFER_DEPTH[31:0] + DATA_BUFFER_DEPTH[31:0] + + + AXI_MM_WIDTH[31:0] + AXI_MM_WIDTH[31:0] + + + PARALLEL_SAMPLES[31:0] + PARALLEL_SAMPLES[31:0] + + + SAMPLE_WIDTH[31:0] + SAMPLE_WIDTH[31:0] + + + APPROX_CLOCK_WIDTH[31:0] + APPROX_CLOCK_WIDTH[31:0] + + + SAMPLE_INDEX_WIDTH[31:0] + SAMPLE_INDEX_WIDTH[31:0] + + + TIMESTAMP_WIDTH[31:0] + TIMESTAMP_WIDTH[31:0] + + + DATA_AXI_MM_GCD[31:0] + DATA_AXI_MM_GCD[31:0] + + + TIMESTAMP_AXI_MM_GCD[31:0] + TIMESTAMP_AXI_MM_GCD[31:0] + + + DATA_RESIZER_UP[31:0] + DATA_RESIZER_UP[31:0] + + + DATA_RESIZER_DOWN[31:0] + DATA_RESIZER_DOWN[31:0] + + + TIMESTAMP_RESIZER_UP[31:0] + TIMESTAMP_RESIZER_UP[31:0] + + + TIMESTAMP_RESIZER_DOWN[31:0] + TIMESTAMP_RESIZER_DOWN[31:0] + + + + timestamps_out + label + + + data[63:0] + data[63:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + timestamps_out_resized + label + + data[127:0] + data[127:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + data_out + label + + data[15:0] + data[15:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + data_out_resized + label + + data[127:0] + data[127:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + + + + discriminator + label + + + clk + clk + + + reset + reset + + + reset_state + reset_state + + + threshold_low[7:0][15:0] + threshold_low[7:0][15:0] + + + threshold_high[7:0][15:0] + threshold_high[7:0][15:0] + + + data_in_reg[7:0][15:0] + data_in_reg[7:0][15:0] + + + + data_in_valid[7:0] + data_in_valid[7:0] + + + timer[7:0][50:0] + timer[7:0][50:0] + + + + timer_d[7:0][50:0] + timer_d[7:0][50:0] + + + + sample_index[7:0][12:0] + sample_index[7:0][12:0] + + + + is_high[7:0] + is_high[7:0] + + + + is_high_d[7:0] + is_high_d[7:0] + + + + new_is_high[7:0] + new_is_high[7:0] + + + + any_above_high[7:0] + any_above_high[7:0] + + + all_below_low[7:0] + all_below_low[7:0] + + + SAMPLE_WIDTH[31:0] + SAMPLE_WIDTH[31:0] + UNSIGNEDDECRADIX + + + PARALLEL_SAMPLES[31:0] + PARALLEL_SAMPLES[31:0] + UNSIGNEDDECRADIX + + + N_CHANNELS[31:0] + N_CHANNELS[31:0] + UNSIGNEDDECRADIX + + + SAMPLE_INDEX_WIDTH[31:0] + SAMPLE_INDEX_WIDTH[31:0] + UNSIGNEDDECRADIX + + + CLOCK_WIDTH[31:0] + CLOCK_WIDTH[31:0] + UNSIGNEDDECRADIX + + + TIMESTAMP_WIDTH[31:0] + TIMESTAMP_WIDTH[31:0] + UNSIGNEDDECRADIX + + + data_out + label + + + data[7:0][15:0] + data[7:0][15:0] + + + + ready[7:0] + ready[7:0] + + + valid[7:0] + valid[7:0] + + + last[7:0] + last[7:0] + + + ok[7:0] + ok[7:0] + + + + DWIDTH[31:0] + DWIDTH[31:0] + + + PARALLEL_CHANNELS[31:0] + PARALLEL_CHANNELS[31:0] + + + + timestamps + label + + + data[7:0][63:0] + data[7:0][63:0] + + + + ready[7:0] + ready[7:0] + + + valid[7:0] + valid[7:0] + + + last[7:0] + last[7:0] + + + ok[7:0] + ok[7:0] + + + + DWIDTH[31:0] + DWIDTH[31:0] + + + PARALLEL_CHANNELS[31:0] + PARALLEL_CHANNELS[31:0] + + + + +