Skip to content

Commit

Permalink
new sample discriminator seems to work okay, found a couple small bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
reed-foster committed Oct 12, 2023
1 parent caa6aa1 commit 4deed91
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 62 deletions.
190 changes: 161 additions & 29 deletions dds_test.srcs/sim_1/new/sample_discriminator_test.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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]);
Expand All @@ -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<<N_CHANNELS) - 1) & (~done);
for (int i = 0; i < N_CHANNELS; i++) begin
if (data_in.valid[i]) begin
samples_sent[i] <= samples_sent[i] + 1'b1;
if (samples_sent[i] == n_samples - 1) begin
done[i] = 1'b1;
end else begin
samples_sent[i] <= samples_sent[i] + 1'b1;
samples_sent[i] = samples_sent[i] + 1'b1;
end
end
end
data_in.valid <= $urandom_range((1<<N_CHANNELS) - 1) & (~done);
@(posedge clk);
end
data_in.valid <= '0;
Expand All @@ -97,59 +107,181 @@ task send_samples(input int n_samples, input bit rand_arrivals);
end
endtask

task check_results();
function logic any_above_high (
input logic [SAMPLE_WIDTH*PARALLEL_SAMPLES-1:0] samples_in,
input logic [SAMPLE_WIDTH-1:0] threshold_high
);
for (int j = 0; j < PARALLEL_SAMPLES; j++) begin
if (signed_sample_t'(samples_in[j*SAMPLE_WIDTH+:SAMPLE_WIDTH]) > 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

Expand Down
31 changes: 15 additions & 16 deletions dds_test.srcs/sources_1/new/sample_discriminator.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Loading

0 comments on commit 4deed91

Please sign in to comment.