-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rewriting noise buffer and modularizing it
- Loading branch information
1 parent
c725162
commit 415cc48
Showing
5 changed files
with
559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
`timescale 1ns / 1ps | ||
module sample_discriminator_test(); | ||
|
||
logic clk = 0; | ||
localparam CLK_RATE_HZ = 100_000_000; | ||
always #(0.5s/CLK_RATE_HZ) clk = ~clk; | ||
|
||
logic reset; | ||
logic [15:0] threshold_high, threshold_low; | ||
|
||
Axis_If #(.DWIDTH(32)) config_in_if(); | ||
Axis_If #(.DWIDTH(16)) data_in_if(); | ||
Axis_If #(.DWIDTH(16)) data_out_if(); | ||
|
||
assign config_in_if.data = {threshold_high, threshold_low}; | ||
|
||
sample_discriminator #( | ||
.SAMPLE_WIDTH(16), | ||
.CLOCK_WIDTH(56) | ||
) dut_i ( | ||
.clk, | ||
.reset, | ||
.data_in(data_in_if), | ||
.data_out(data_out_if), | ||
.config_in(config_in_if) | ||
); | ||
|
||
logic [15:0] data_sent [$]; | ||
logic [55:0] timestamps_sent [$]; | ||
logic [15:0] data_received [$]; | ||
logic [15:0] timestamps_received [$]; | ||
|
||
logic [55:0] sample_count; | ||
logic [15:0] data_in_d; | ||
logic data_in_valid_d; | ||
logic is_high, is_high_d; | ||
logic new_is_high; | ||
|
||
assign new_is_high = is_high & (!is_high_d); | ||
|
||
logic [15:0] data_range_low, data_range_high; | ||
|
||
always @(posedge clk) begin | ||
if (reset) begin | ||
sample_count <= '0; | ||
data_in_if.data <= '0; | ||
is_high_d <= '0; | ||
is_high <= '0; | ||
end else begin | ||
data_in_valid_d <= data_in_if.valid; | ||
if (data_in_if.valid && data_in_if.ready) begin | ||
data_in_d <= data_in_if.data; | ||
is_high_d <= is_high; | ||
if (data_in_if.data > threshold_high) begin | ||
is_high <= 1'b1; | ||
end | ||
sample_count <= sample_count + 1'b1; | ||
data_in_if.data <= $urandom_range(data_range_low, data_range_high); | ||
end | ||
if (data_in_valid_d) begin | ||
if (is_high) begin | ||
data_sent.push_front(data_in_d & 16'hfff8); | ||
end | ||
if (new_is_high) begin | ||
timestamps_sent.push_front(sample_count); | ||
end | ||
end | ||
if (data_out_if.valid && data_out_if.ready) begin | ||
if (data_out_if.data[1]) begin | ||
// timestamp | ||
timestamps_received.push_front(data_out_if.data & 16'hfffc); | ||
end else begin | ||
// data | ||
data_received.push_front(data_out_if.data & 16'hfff8); | ||
end | ||
end | ||
end | ||
end | ||
|
||
// not 100% activity on output | ||
always @(posedge clk) begin | ||
data_out_if.ready <= $urandom_range(0,1); | ||
end | ||
|
||
task send_samples(input int n_samples); | ||
repeat (n_samples) begin | ||
data_in_if.valid <= 1'b1; | ||
@(posedge clk); | ||
data_in_if.valid <= 1'b0; | ||
repeat (4) @(posedge clk); | ||
end | ||
endtask | ||
|
||
task check_results(); | ||
logic [55:0] tstamp_temp; | ||
if (data_sent.size() != data_received.size()) begin | ||
$display("mismatch in amount of sent/received data"); | ||
$display("data_sent.size() = %0d", data_sent.size()); | ||
$display("data_received.size() = %0d", data_received.size()); | ||
for (int i = 0; i < data_sent.size(); i++) begin | ||
$display("data_sent[%0d] = %x", i, data_sent[i]); | ||
end | ||
for (int i = 0; i < data_received.size(); i++) begin | ||
$display("data_received[%0d] = %x", i, data_received[i]); | ||
end | ||
end | ||
if (timestamps_sent.size()*4 != timestamps_received.size()) begin | ||
$display("mismatch in amount of sent/received timestamps"); | ||
$display("timestamps_sent.size() = %0d", timestamps_sent.size()); | ||
$display("timestamps_received.size() = %0d", timestamps_received.size()); | ||
for (int i = 0; i < timestamps_sent.size(); i++) begin | ||
$display("timestamps_sent[%0d] = %x", i, timestamps_sent[i]); | ||
end | ||
for (int i = 0; i < timestamps_received.size(); i++) begin | ||
$display("timestamps_received[%0d] = %x", i, timestamps_received[i]); | ||
end | ||
end | ||
while (data_sent.size() > 0 && data_received.size() > 0) begin | ||
if (data_sent[$] != data_received[$]) begin | ||
$display("data mismatch error (received %x, sent %x)", data_received[$], data_sent[$]); | ||
end | ||
data_sent.pop_back(); | ||
data_received.pop_back(); | ||
end | ||
while (timestamps_sent.size() > 0 && timestamps_received.size() > 0) begin | ||
for (int i = 0; i < 4; i++) begin | ||
tstamp_temp[i*14+:14] = timestamps_received.pop_back() >> 2; | ||
end | ||
if (timestamps_sent[$] != tstamp_temp) begin | ||
$display("timestamp mismatch error (received %x, sent %x)", tstamp_temp, timestamps_sent[$]); | ||
end | ||
timestamps_sent.pop_back(); | ||
end | ||
endtask | ||
|
||
initial begin | ||
reset <= 1'b1; | ||
data_range_low <= 16'h0000; | ||
data_range_high <= 16'hffff; | ||
threshold_low <= '0; | ||
threshold_high <= '0; | ||
data_in_if.valid <= '0; | ||
repeat (100) @(posedge clk); | ||
reset <= 1'b0; | ||
repeat (50) @(posedge clk); | ||
send_samples(50); | ||
repeat (50) @(posedge clk); | ||
check_results(); | ||
$finish; | ||
end | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// sample discriminator | ||
// If input sample is above high threshold (with hysteresis), it is passed through, | ||
// otherwise it is dropped. If the preceeding sample was below the low threshold, | ||
// then a timestamp is also sent out after the current sample (indicated by | ||
// setting some flag bits) | ||
// data format (LSB 1'bx is channel index) | ||
// sample: {sample[15:3], 1'bx, 1'b0, 1'bx} bit 2 1'bx is new_is_high | ||
// timestamp (4 successive transactions): {clock[i*14+:14], 1'b1, 1'bx} for i = 0..3 | ||
module sample_discriminator #( | ||
parameter int SAMPLE_WIDTH = 16, | ||
parameter int CLOCK_WIDTH = 56 // rolls over roughly every 10 years | ||
) ( | ||
input wire clk, reset, | ||
Axis_If.Slave_Simple data_in, | ||
Axis_If.Master_Simple data_out, | ||
Axis_If.Slave_Simple config_in // {threshold_high, threshold_low} | ||
); | ||
|
||
assign config_in.ready = 1'b1; | ||
assign data_in.ready = 1'b1; // always process new samples; we'll just throw them away later if we don't need them | ||
|
||
logic [SAMPLE_WIDTH-1:0] threshold_low, threshold_high; | ||
logic [SAMPLE_WIDTH-1:0] data_in_reg; | ||
logic data_in_valid; | ||
logic [CLOCK_WIDTH-1:0] sample_count; | ||
|
||
// 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 | ||
threshold_high <= config_in.data[2*SAMPLE_WIDTH-1:SAMPLE_WIDTH]; | ||
threshold_low <= config_in.data[SAMPLE_WIDTH-1:0]; | ||
end | ||
end | ||
end | ||
|
||
logic is_high, is_high_d; | ||
logic new_is_high; | ||
assign new_is_high = is_high & (!is_high_d); | ||
|
||
always_ff @(posedge clk) begin | ||
if (reset) begin | ||
is_high <= '0; | ||
is_high_d <= '0; | ||
sample_count <= '0; | ||
end else begin | ||
data_in_valid <= data_in.valid; | ||
if (data_in.valid) begin | ||
data_in_reg <= data_in.data; | ||
is_high_d <= is_high; | ||
sample_count <= sample_count + 1'b1; | ||
if (data_in.data > threshold_high) begin | ||
is_high <= 1'b1; | ||
end else if (data_in.data < threshold_low) begin | ||
is_high <= 1'b0; | ||
end | ||
end | ||
end | ||
end | ||
|
||
Axis_If #(.DWIDTH(SAMPLE_WIDTH+CLOCK_WIDTH)) input_fifo_in (); | ||
Axis_If #(.DWIDTH(SAMPLE_WIDTH+CLOCK_WIDTH)) input_fifo_out (); | ||
Axis_If #(.DWIDTH(SAMPLE_WIDTH)) output_fifo_in (); | ||
|
||
fifo #( | ||
.DATA_WIDTH(SAMPLE_WIDTH+CLOCK_WIDTH), | ||
.ADDR_WIDTH(4) // add some buffer in case we get several samples with alternating noise in a row | ||
) input_fifo_i ( | ||
.clk, | ||
.reset, | ||
.data_out(input_fifo_out), | ||
.data_in(input_fifo_in) | ||
); | ||
|
||
localparam int SPLIT_TIMESTAMP_COUNT = CLOCK_WIDTH / (SAMPLE_WIDTH - 2); | ||
logic [$clog2(SPLIT_TIMESTAMP_COUNT+1)-1:0] subword_sel; | ||
|
||
assign input_fifo_in.data = {sample_count, data_in_reg[SAMPLE_WIDTH-1:2], new_is_high, data_in_reg[0]}; | ||
assign input_fifo_in.valid = data_in_valid & is_high; | ||
assign input_fifo_out.ready = ((!input_fifo_out.data[1]) || (subword_sel == SPLIT_TIMESTAMP_COUNT)) | ||
&& input_fifo_out.valid; | ||
assign output_fifo_in.valid = input_fifo_out.valid; | ||
|
||
always_comb begin | ||
if (subword_sel == 0) begin | ||
// set bit 1 to 0 to indicate the word contains a sample | ||
// sample: {sample[15:3], 1'bx, 1'b0, 1'bx} bit 2 1'bx is new_is_high | ||
output_fifo_in.data = {input_fifo_out.data[SAMPLE_WIDTH-1:3], | ||
input_fifo_out.data[1], 1'b0, input_fifo_out.data[0]}; | ||
end else begin | ||
// set bit 1 to 1 to indicate the word contains a timestamp | ||
// timestamp (4 successive transactions): {clock[i*14+:14], 1'b1, 1'bx} for i = 0..3 | ||
output_fifo_in.data = {input_fifo_out.data[2+subword_sel*(SAMPLE_WIDTH-2)+:(SAMPLE_WIDTH-2)], | ||
1'b1, input_fifo_out.data[0]}; | ||
end | ||
end | ||
|
||
always_ff @(posedge clk) begin | ||
if (reset) begin | ||
subword_sel <= '0; | ||
end else begin | ||
if (input_fifo_out.valid && input_fifo_out.data[1]) begin | ||
if (subword_sel == SPLIT_TIMESTAMP_COUNT) begin | ||
subword_sel <= '0; | ||
end else begin | ||
subword_sel <= subword_sel + 1'b1; | ||
end | ||
end | ||
end | ||
end | ||
|
||
fifo #( | ||
.DATA_WIDTH(SAMPLE_WIDTH), | ||
.ADDR_WIDTH(4) | ||
) output_fifo_i ( | ||
.clk, | ||
.reset, | ||
.data_out(data_out), | ||
.data_in(output_fifo_in) | ||
); | ||
|
||
endmodule |
Oops, something went wrong.