From 4deed91fe280fdc807f8b54cf544405a741e8d09 Mon Sep 17 00:00:00 2001 From: Reed Foster Date: Thu, 12 Oct 2023 11:40:03 -0400 Subject: [PATCH] new sample discriminator seems to work okay, found a couple small bugs --- .../sim_1/new/sample_discriminator_test.sv | 190 +++++++++++++++--- .../sources_1/new/sample_discriminator.sv | 31 ++- sample_discriminator_test_behav.wcfg | 66 ++++-- 3 files changed, 225 insertions(+), 62 deletions(-) diff --git a/dds_test.srcs/sim_1/new/sample_discriminator_test.sv b/dds_test.srcs/sim_1/new/sample_discriminator_test.sv index 9632808..7276f5e 100644 --- a/dds_test.srcs/sim_1/new/sample_discriminator_test.sv +++ b/dds_test.srcs/sim_1/new/sample_discriminator_test.sv @@ -18,8 +18,13 @@ Axis_Parallel_If #(.DWIDTH(SAMPLE_WIDTH*PARALLEL_SAMPLES), .PARALLEL_CHANNELS(N_ Axis_Parallel_If #(.DWIDTH(SAMPLE_WIDTH*PARALLEL_SAMPLES), .PARALLEL_CHANNELS(N_CHANNELS)) data_out(); Axis_Parallel_If #(.DWIDTH(SAMPLE_INDEX_WIDTH+CLOCK_WIDTH), .PARALLEL_CHANNELS(N_CHANNELS)) timestamps_out(); -logic signed [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_high, threshold_low; -assign config_in.data = {threshold_high, threshold_low}; +typedef logic signed [SAMPLE_WIDTH-1:0] signed_sample_t; +logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_high, threshold_low; +always_comb begin + for (int i = 0; i < N_CHANNELS; i++) begin + config_in.data[2*SAMPLE_WIDTH*i+:2*SAMPLE_WIDTH] = {threshold_high[i], threshold_low[i]}; + end +end logic sample_index_reset; @@ -52,7 +57,9 @@ always @(posedge clk) begin for (int i = 0; i < N_CHANNELS; i++) begin if (data_in.ok[i]) begin data_sent[i].push_front(data_in.data[i]); - data_in.data[i] <= $urandom_range(data_range_low[i], data_range_high[i]); + for (int j = 0; j < PARALLEL_SAMPLES; j++) begin + data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH] <= $urandom_range(data_range_low[i], data_range_high[i]); + end end if (data_out.ok[i]) begin data_received[i].push_front(data_out.data[i]); @@ -71,19 +78,22 @@ task send_samples(input int n_samples, input bit rand_arrivals); int samples_sent [N_CHANNELS]; logic [N_CHANNELS-1:0] done; if (rand_arrivals) begin + // reset done = '0; + for (int i = 0; i < N_CHANNELS; i++) begin + samples_sent[i] = 0; + end while (~done) begin - data_in.valid <= $urandom_range((1< signed_sample_t'(threshold_high)) begin + return 1'b1; + end + end + return 1'b0; +endfunction + +function logic all_below_low ( + input logic [SAMPLE_WIDTH*PARALLEL_SAMPLES-1:0] samples_in, + input logic [SAMPLE_WIDTH-1:0] threshold_low +); + for (int j = 0; j < PARALLEL_SAMPLES; j++) begin + if (signed_sample_t'(samples_in[j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > signed_sample_t'(threshold_low)) begin + return 1'b0; + end + end + return 1'b1; +endfunction + +task check_results ( + input logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_low, + input logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_high, + inout logic [N_CHANNELS-1:0][CLOCK_WIDTH-1:0] timer, + inout logic [N_CHANNELS-1:0][SAMPLE_INDEX_WIDTH-1:0] sample_index, + inout logic [N_CHANNELS-1:0] is_high +); for (int i = 0; i < N_CHANNELS; i++) begin + // process each channel $display("data_sent[%0d].size() = %0d", i, data_sent[i].size()); $display("data_received[%0d].size() = %0d", i, data_received[i].size()); $display("timestamps_received[%0d].size() = %0d", i, timestamps_received[i].size()); - end - for (int i = 0; i < N_CHANNELS; i++) begin - for (int j = 0; j < data_sent[i].size(); j++) begin - $display("data_sent[%0d][%0d] = %x", i, data_sent[i].size() - j - 1, data_sent[i][$-j]); - end - for (int j = 0; j < data_received[i].size(); j++) begin - $display("data_received[%0d][%0d] = %x", i, data_received[i].size() - j - 1, data_received[i][$-j]); + + if (data_sent[i].size() < data_received[i].size()) begin + $error("more data received than sent. this is not possible"); end - for (int j = 0; j < timestamps_received[i].size(); j++) begin - $display("timestamps_received[%0d][%0d] = %x", i, timestamps_received[i].size() - j - 1, timestamps_received[i][$-j]); + + while (data_sent[i].size() > 0) begin + if (any_above_high(data_sent[i][$], threshold_high[i])) begin + if (!is_high[i]) begin + // new high, we should get a timestamp + if (timestamps_received[i].size() > 0) begin + if (timestamps_received[i][$] != {timer[i], sample_index[i]}) begin + $warning("mismatched timestamp: got %x, expected %x", timestamps_received[i][$], {timer[i], sample_index[i]}); + end + timestamps_received[i].pop_back(); + end else begin + $warning("expected a timestamp (with value %x), but no more timestamps left", {timer[i], sample_index[i]}); + end + end + is_high[i] = 1'b1; + end else if (all_below_low(data_sent[i][$], threshold_low[i])) begin + is_high[i] = 1'b0; + end + if (is_high[i]) begin + if (data_sent[i][$] != data_received[i][$]) begin + $warning("mismatched data: got %x, expected %x", data_received[i][$], data_sent[i][$]); + end + data_received[i].pop_back(); + sample_index[i] = sample_index[i] + 1'b1; + end + data_sent[i].pop_back(); + timer[i] = timer[i] + 1'b1; end + $display("after processing:"); + $display("data_sent[%0d].size() = %0d", i, data_sent[i].size()); + $display("data_received[%0d].size() = %0d", i, data_received[i].size()); + $display("timestamps_received[%0d].size() = %0d", i, timestamps_received[i].size()); end endtask +logic [N_CHANNELS-1:0][CLOCK_WIDTH-1:0] timer; +logic [N_CHANNELS-1:0][SAMPLE_INDEX_WIDTH-1:0] sample_index; +logic [N_CHANNELS-1:0] is_high; + initial begin reset <= 1'b1; - data_range_low <= '0; - data_range_high <= '1; + for (int i = 0; i < N_CHANNELS; i++) begin + data_range_low[i] <= '0; + data_range_high[i] <= 16'h7fff; + end threshold_low <= '0; threshold_high <= '0; data_in.valid <= '0; + config_in.valid <= '0; sample_index_reset <= '0; + is_high <= '0; + timer <= '0; + sample_index <= '0; repeat (100) @(posedge clk); reset <= 1'b0; sample_index_reset <= 1'b1; @(posedge clk); sample_index_reset <= '0; repeat (50) @(posedge clk); + config_in.valid <= 1'b1; + @(posedge clk); + config_in.valid <= 1'b0; + repeat (50) @(posedge clk); + + // send a bunch of data with discrimination disabled send_samples(10, 1); repeat (50) @(posedge clk); send_samples(10, 0); repeat (50) @(posedge clk); - check_results(); - $finish; - // change amplitudes and threshold to check sample-rejection - // first, try sending small signals that shouldn't make it through - data_range_low <= 16'h00ff; - data_range_high <= 16'h02ff; - threshold_low <= 16'h03ff; - threshold_high <= 16'h07ff; + $display("######################################################"); + $display("# testing run with all data above thresholds #"); + $display("######################################################"); + check_results(threshold_low, threshold_high, timer, sample_index, is_high); + + // send a bunch of data, some below and some above the threshold on channel 0 + // for channel 1, keep the same settings as before + data_range_low[0] <= 16'h0000; + data_range_high[0] <= 16'h04ff; + threshold_low[0] <= 16'h03c0; + threshold_high[0] <= 16'h0400; + config_in.valid <= 1'b1; + @(posedge clk); + config_in.valid <= 1'b0; + repeat (50) @(posedge clk); + send_samples(100, 1); + repeat (50) @(posedge clk); + send_samples(100, 0); + repeat (50) @(posedge clk); + $display("######################################################"); + $display("# testing run with channel 0 straddling thresholds #"); + $display("# and channel 1 above thresholds #"); + $display("######################################################"); + check_results(threshold_low, threshold_high, timer, sample_index, is_high); + + // send a bunch of data below the threshold + for (int i = 0; i < N_CHANNELS; i++) begin + data_range_low[i] <= 16'h0000; + data_range_high[i] <= 16'h00ff; + threshold_low[i] <= 16'h03ff; + threshold_high[i] <= 16'h0400; + end config_in.valid <= 1'b1; @(posedge clk); config_in.valid <= 1'b0; repeat (50) @(posedge clk); - send_samples(200, 0); + send_samples(400, 1); repeat (50) @(posedge clk); - // should have 200 samples - check_results(); + send_samples(400, 0); + repeat (50) @(posedge clk); + $display("######################################################"); + $display("# testing run with all data below thresholds #"); + $display("######################################################"); + check_results(threshold_low, threshold_high, timer, sample_index, is_high); + + // send a bunch of data close to the threshold + 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 + config_in.valid <= 1'b1; + @(posedge clk); + config_in.valid <= 1'b0; + repeat (50) @(posedge clk); + send_samples(400, 1); + repeat (50) @(posedge clk); + send_samples(400, 0); + repeat (50) @(posedge clk); + $display("######################################################"); + $display("# testing run with both channels straddling #"); + $display("# thresholds #"); + $display("######################################################"); + check_results(threshold_low, threshold_high, timer, sample_index, is_high); + $finish; end diff --git a/dds_test.srcs/sources_1/new/sample_discriminator.sv b/dds_test.srcs/sources_1/new/sample_discriminator.sv index 27d3ae2..3e42872 100644 --- a/dds_test.srcs/sources_1/new/sample_discriminator.sv +++ b/dds_test.srcs/sources_1/new/sample_discriminator.sv @@ -26,24 +26,28 @@ localparam int TIMESTAMP_WIDTH = SAMPLE_INDEX_WIDTH + CLOCK_WIDTH; assign config_in.ready = 1'b1; assign data_in.ready = '1; // don't apply backpressure -logic signed [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_low, threshold_high; -logic [N_CHANNELS-1:0][PARALLEL_SAMPLES*SAMPLE_WIDTH-1:0] data_in_reg, data_out_reg; -logic [N_CHANNELS-1:0] data_in_valid, data_out_valid; +typedef logic signed [SAMPLE_WIDTH-1:0] signed_sample_t; + +logic [N_CHANNELS-1:0][SAMPLE_WIDTH-1:0] threshold_low, threshold_high; +logic [N_CHANNELS-1:0][PARALLEL_SAMPLES*SAMPLE_WIDTH-1:0] data_in_reg; +logic [N_CHANNELS-1:0] data_in_valid; logic [N_CHANNELS-1:0][CLOCK_WIDTH-1:0] timer, timer_d; logic [N_CHANNELS-1:0][SAMPLE_INDEX_WIDTH-1:0] sample_index; logic [N_CHANNELS-1:0] is_high, is_high_d; logic [N_CHANNELS-1:0] new_is_high; +assign new_is_high = is_high & (~is_high_d); + // update thresholds from config interface always_ff @(posedge clk) begin if (reset) begin threshold_low <= '0; threshold_high <= '0; end else begin - if (config_in.valid) begin + if (config_in.ok) begin for (int i = 0; i < N_CHANNELS; i++) begin - threshold_high[i] <= config_in.data[2*SAMPLE_WIDTH*(i+1)+:SAMPLE_WIDTH]; + threshold_high[i] <= config_in.data[2*SAMPLE_WIDTH*i+SAMPLE_WIDTH+:SAMPLE_WIDTH]; threshold_low[i] <= config_in.data[2*SAMPLE_WIDTH*i+:SAMPLE_WIDTH]; end end @@ -59,10 +63,10 @@ always_comb begin any_above_high[i] = 1'b0; all_below_low[i] = 1'b1; for (int j = 0; j < PARALLEL_SAMPLES; j++) begin - if (signed'(data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > threshold_high[i]) begin + if (signed_sample_t'(data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > signed_sample_t'(threshold_high[i])) begin any_above_high[i] = 1'b1; end - if (signed'(data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > threshold_low[i]) begin + if (signed_sample_t'(data_in.data[i][j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > signed_sample_t'(threshold_low[i])) begin all_below_low[i] = 1'b0; end end @@ -71,9 +75,8 @@ end always_ff @(posedge clk) begin // pipeline stage for timer to match sample_index delay - new_is_high <= is_high & (~is_high_d); - timestamps_out.valid <= new_is_high; timer_d <= timer; + timestamps_out.valid <= new_is_high; for (int i = 0; i < N_CHANNELS; i++) begin timestamps_out.data[i] <= {timer_d[i], sample_index[i]}; end @@ -86,10 +89,8 @@ always_ff @(posedge clk) begin is_high_d <= is_high; // match delay of sample_index - data_out_reg <= data_in_reg; - data_out.data <= data_out_reg; - data_out_valid <= data_in_valid & is_high; - data_out.valid <= data_out_valid; + data_out.data <= data_in_reg; + data_out.valid <= data_in_valid & is_high; // is_high SR flipflop, sample_index, and timer if (reset) begin @@ -112,13 +113,11 @@ always_ff @(posedge clk) begin // update is_high if (any_above_high[i]) begin is_high[i] <= 1'b1; - end else if (all_below_low) begin + end else if (all_below_low[i]) begin is_high[i] <= 1'b0; end end end end - - endmodule diff --git a/sample_discriminator_test_behav.wcfg b/sample_discriminator_test_behav.wcfg index 1a0eb9d..0356148 100644 --- a/sample_discriminator_test_behav.wcfg +++ b/sample_discriminator_test_behav.wcfg @@ -11,15 +11,15 @@ - - - + + + - + - + clk clk @@ -51,9 +51,11 @@ data_in label + data[1:0][63:0] data[1:0][63:0] + ready[1:0] @@ -70,6 +72,7 @@ ok[1:0] ok[1:0] + DWIDTH[31:0] @@ -83,9 +86,11 @@ data_out label + data[1:0][63:0] data[1:0][63:0] + ready[1:0] @@ -102,6 +107,7 @@ ok[1:0] ok[1:0] + DWIDTH[31:0] @@ -115,6 +121,7 @@ timestamps_out label + data[1:0][63:0] data[1:0][63:0] @@ -149,6 +156,7 @@ dut_i label + clk clk @@ -164,42 +172,37 @@ threshold_low[1:0][15:0] threshold_low[1:0][15:0] + threshold_high[1:0][15:0] threshold_high[1:0][15:0] + data_in_reg[1:0][63:0] data_in_reg[1:0][63:0] - - - data_out_reg[1:0][63:0] - data_out_reg[1:0][63:0] + data_in_valid[1:0] data_in_valid[1:0] - - - data_out_valid[1:0] - data_out_valid[1:0] + timer[1:0][49:0] timer[1:0][49:0] - - - timer_d[1:0][49:0] - timer_d[1:0][49:0] + sample_index[1:0][13:0] sample_index[1:0][13:0] + is_high[1:0] is_high[1:0] + is_high_d[1:0] @@ -208,6 +211,7 @@ new_is_high[1:0] new_is_high[1:0] + any_above_high[1:0] @@ -242,4 +246,32 @@ TIMESTAMP_WIDTH[31:0] + + config_in + label + + data[63:0] + data[63:0] + + + ready + ready + + + valid + valid + + + last + last + + + ok + ok + + + DWIDTH[31:0] + DWIDTH[31:0] + +