Merge branch 'dev/design' into integration_new_controller
This commit is contained in:
@@ -27,6 +27,14 @@ module generator
|
||||
|
||||
logic enable, synced;
|
||||
|
||||
initial begin
|
||||
cnt_pulse_period = '0;
|
||||
cnt_pulse_num = '0;
|
||||
enable = 0;
|
||||
synced = 0;
|
||||
dac_out = ZERO_LEVEL;
|
||||
end
|
||||
|
||||
always @(posedge clk_dac) begin
|
||||
if (rst) begin
|
||||
pulse_height_reg <= ZERO_LEVEL;
|
||||
|
||||
+22
-25
@@ -13,38 +13,38 @@ module sampler
|
||||
input [31:0] smp_num,
|
||||
input request,
|
||||
|
||||
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||
output logic m_axis_tvalid,
|
||||
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||
output logic m_axis_tvalid,
|
||||
output logic done
|
||||
);
|
||||
|
||||
// WARNING: number of samples smp_num must be multiple of PACK_FACTOR
|
||||
// Last (smp_num % PACK_FACTOR) will be lost and not transmitted
|
||||
logic [DATA_WIDTH-1:0] data_converted;
|
||||
logic [31:0] smp_num_reg, cnt_smp_num;
|
||||
logic synced;
|
||||
logic synced;
|
||||
logic [$clog2(PACK_FACTOR):0] pack_cnt;
|
||||
|
||||
always_comb begin
|
||||
data_converted = '0;
|
||||
if (PROCESS_MODE) begin
|
||||
if (out_of_range) begin
|
||||
if (data_in[DATA_WIDTH-1]==1'b1) data_converted = {1'b1, {(DATA_WIDTH-2){1'b0}}};
|
||||
else if (data_in[DATA_WIDTH-1]==1'b0) data_converted = {1'b0, {(DATA_WIDTH-2){1'b1}}};
|
||||
data_converted = {~data_in[DATA_WIDTH-1], {(DATA_WIDTH-1){data_in[DATA_WIDTH-1]}}};
|
||||
end else begin
|
||||
if (data_in == {1'b1, {(DATA_WIDTH-1){1'b0}}})
|
||||
data_converted = data_in;
|
||||
else
|
||||
data_converted = data_in[DATA_WIDTH-1] ?{1'b1, (~data_in[DATA_WIDTH-2:0] + 1'b1)}:data_in;
|
||||
data_converted = {~data_in[DATA_WIDTH-1], data_in[DATA_WIDTH-2:0]};
|
||||
end
|
||||
end else begin
|
||||
if (out_of_range) begin
|
||||
if (data_in[DATA_WIDTH-1]==1'b1) data_converted = '1;
|
||||
else if (data_in[DATA_WIDTH-1]==1'b0) data_converted = '0;
|
||||
data_converted = {DATA_WIDTH{data_in[DATA_WIDTH-1]}};
|
||||
end else begin
|
||||
data_converted = data_in;
|
||||
data_converted = data_in;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
synced = 0;
|
||||
m_axis_tdata = '0;
|
||||
m_axis_tvalid = 0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_in) begin
|
||||
if (rst) begin
|
||||
@@ -56,10 +56,9 @@ module sampler
|
||||
synced <= 0;
|
||||
done <= 0;
|
||||
end else begin
|
||||
m_axis_tvalid <= 0;
|
||||
if (!synced) begin
|
||||
if (done && request) begin
|
||||
synced <= 1;
|
||||
synced <= 1;
|
||||
done <= 0;
|
||||
cnt_smp_num <= 0;
|
||||
smp_num_reg <= smp_num;
|
||||
@@ -68,23 +67,21 @@ module sampler
|
||||
end
|
||||
end else begin
|
||||
if (cnt_smp_num != smp_num_reg) begin
|
||||
cnt_smp_num <= cnt_smp_num +1;
|
||||
cnt_smp_num++;
|
||||
m_axis_tdata[pack_cnt*DATA_WIDTH +: DATA_WIDTH] <= data_converted;
|
||||
if (pack_cnt == PACK_FACTOR-1) begin
|
||||
pack_cnt <= 0;
|
||||
m_axis_tvalid <= 1;
|
||||
end else begin
|
||||
pack_cnt <= pack_cnt + 1;
|
||||
pack_cnt++;
|
||||
m_axis_tvalid <= 0;
|
||||
end
|
||||
end else begin
|
||||
cnt_smp_num <= '0;
|
||||
pack_cnt <= '0;
|
||||
pack_cnt <= '0;
|
||||
synced <= 0;
|
||||
done <= 1;
|
||||
m_axis_tdata <= '0;
|
||||
m_axis_tvalid <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
||||
+162
-115
@@ -1,17 +1,24 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module sampler_tb;
|
||||
|
||||
localparam DATA_WIDTH = 12;
|
||||
localparam PACK_FACTOR = 1;
|
||||
localparam PROCESS_MODE = 0;
|
||||
localparam CLK_PERIOD = 15.3846;
|
||||
module sampler_tb #(
|
||||
// Параметры тестбенча
|
||||
parameter int DATA_WIDTH = 12, // bitwidth of sampled data. Equal to ADC bitwidth
|
||||
parameter int PACK_FACTOR = 1, // packing of several numbers in one axi-stream tdata transaction
|
||||
parameter bit PROCESS_MODE = 0, // signed (1) / unsigned (0)
|
||||
parameter real CLK_PERIOD = 15.3846,
|
||||
parameter int OTR_OFFSET = 0 // Out of Range offset number clipping
|
||||
);
|
||||
// Вычислимые константы
|
||||
// Диапазон значений семплера
|
||||
localparam int MIN_VALUE = PROCESS_MODE ? -2**(DATA_WIDTH-1) : 0;
|
||||
localparam int MAX_VALUE = PROCESS_MODE ? 2**(DATA_WIDTH-1)-1 : (2**DATA_WIDTH)-1;
|
||||
|
||||
logic clk;
|
||||
logic rst;
|
||||
logic rst_dut;
|
||||
logic rst_gen;
|
||||
|
||||
logic [DATA_WIDTH-1:0] data_in;
|
||||
logic out_of_range;
|
||||
wire [DATA_WIDTH-1:0] data_in;
|
||||
wire out_of_range;
|
||||
|
||||
logic [31:0] smp_num;
|
||||
|
||||
@@ -21,15 +28,13 @@ module sampler_tb;
|
||||
logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||
logic m_axis_tvalid;
|
||||
|
||||
int received_count;
|
||||
|
||||
sampler #(
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.PACK_FACTOR (PACK_FACTOR),
|
||||
.PROCESS_MODE(PROCESS_MODE)
|
||||
) dut (
|
||||
.clk_in (clk),
|
||||
.rst (rst),
|
||||
.rst (rst_dut),
|
||||
|
||||
.data_in (data_in),
|
||||
.out_of_range (out_of_range),
|
||||
@@ -54,141 +59,183 @@ module sampler_tb;
|
||||
// =====================================================
|
||||
// RESET
|
||||
// =====================================================
|
||||
initial begin
|
||||
rst = 1;
|
||||
data_in = 0;
|
||||
out_of_range = 0;
|
||||
done = 0;
|
||||
smp_num = 0;
|
||||
|
||||
repeat(5) @(posedge clk);
|
||||
rst = 0;
|
||||
end
|
||||
|
||||
// =====================================================
|
||||
// OUTPUT COUNTER
|
||||
// =====================================================
|
||||
always @(posedge clk) begin
|
||||
if (m_axis_tvalid)
|
||||
received_count++;
|
||||
end
|
||||
task automatic reset_dut();
|
||||
@(posedge clk);
|
||||
rst_dut = 1;
|
||||
@(posedge clk);
|
||||
rst_dut = 0;
|
||||
endtask
|
||||
|
||||
// =====================================================
|
||||
// FEED DATA
|
||||
// =====================================================
|
||||
task automatic feed_data_stream(
|
||||
input int num_words,
|
||||
input bit random_data,
|
||||
input bit random_out_of_range
|
||||
triangle_wave_gen #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.OFFSET(OTR_OFFSET), // offset of bits from '0 and '1 for OTR
|
||||
.STEP(1) // LSB bit per clock
|
||||
) signal_gen (
|
||||
.clk(clk),
|
||||
.rst(rst_gen),
|
||||
.signal(data_in),
|
||||
.otr(out_of_range)
|
||||
);
|
||||
logic [DATA_WIDTH-1:0] value;
|
||||
bit oor;
|
||||
begin
|
||||
value = 1;
|
||||
|
||||
for (int i = 0; i < num_words; i++) begin
|
||||
|
||||
if (random_data)
|
||||
value = $urandom_range(1, (1<<DATA_WIDTH)-1);
|
||||
else
|
||||
value = value + 1;
|
||||
|
||||
if (random_out_of_range)
|
||||
oor = ($urandom_range(0,3) == 0);
|
||||
else
|
||||
oor = 0;
|
||||
|
||||
data_in = value;
|
||||
out_of_range = oor;
|
||||
|
||||
@(posedge clk);
|
||||
end
|
||||
|
||||
out_of_range = 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
// =====================================================
|
||||
// TEST CASE
|
||||
// TEST TASKS
|
||||
// =====================================================
|
||||
task automatic run_test_case(
|
||||
input int n,
|
||||
input bit random_data,
|
||||
input bit random_out_of_range
|
||||
input int sample_num
|
||||
);
|
||||
begin
|
||||
received_count = 0;
|
||||
logic [DATA_WIDTH-1:0] input_values[$];
|
||||
logic [DATA_WIDTH-1:0] output_values[$];
|
||||
bit flag;
|
||||
int tmp_input_val, tmp_output_val;
|
||||
|
||||
data_in = 0;
|
||||
out_of_range = 0;
|
||||
done = 0;
|
||||
|
||||
smp_num = n;
|
||||
|
||||
// handshake
|
||||
// Startup sequence
|
||||
rst_gen <= 1;
|
||||
smp_num <= sample_num;
|
||||
request <= 1;
|
||||
@(posedge clk);
|
||||
done <= 1'b1;
|
||||
wait(request == 1'b1);
|
||||
@(posedge clk);
|
||||
done <= 1'b0;
|
||||
|
||||
// syncronize
|
||||
while (!done)
|
||||
@(posedge clk);
|
||||
request <= 0;
|
||||
|
||||
// Wait for sync and start signal generator
|
||||
// while (!dut.synced)
|
||||
// @(posedge clk);
|
||||
wait(dut.synced === 1);
|
||||
rst_gen <= 0;
|
||||
|
||||
// wait enable
|
||||
wait(dut.enable == 1'b1);
|
||||
// Wait for valid data
|
||||
fork
|
||||
begin : stat_mon_proc
|
||||
forever begin
|
||||
@(posedge clk);
|
||||
input_values.push_back(data_in);
|
||||
if (m_axis_tvalid) begin
|
||||
for (int i = 0; i < PACK_FACTOR; i++)
|
||||
output_values.push_back(m_axis_tdata[DATA_WIDTH*i +: DATA_WIDTH]);
|
||||
end
|
||||
end
|
||||
end
|
||||
join_none
|
||||
|
||||
// feed data
|
||||
feed_data_stream(n + 10, random_data, random_out_of_range);
|
||||
// Wait until end
|
||||
// while (dut.synced)
|
||||
// @(posedge clk);
|
||||
wait(dut.synced === 0);
|
||||
|
||||
// wait completion
|
||||
wait(dut.enable == 1'b0);
|
||||
disable stat_mon_proc;
|
||||
// Pop last input value. Signal is ahead of tdata for 1 cycle
|
||||
input_values.pop_back();
|
||||
|
||||
$display("Expected smp_num=%0d Received=%0d", smp_num, received_count);
|
||||
// check data length correct
|
||||
if ((input_values.size() - (input_values.size() % PACK_FACTOR)) != output_values.size()) begin
|
||||
$display("[ERROR] -run_test_case- Input queue size don't equal to output queue size: %0d vs %0d", input_values.size(), output_values.size());
|
||||
$finish;
|
||||
end
|
||||
flag = 0;
|
||||
for (int i = 0; i < output_values.size(); i++) begin
|
||||
// clip value for OTR
|
||||
tmp_input_val = int'(input_values[i]) + MIN_VALUE;
|
||||
tmp_output_val = PROCESS_MODE ?
|
||||
int'($signed({output_values[i][DATA_WIDTH-1], output_values[i]})) :
|
||||
int'(output_values[i]);
|
||||
|
||||
if (received_count == smp_num)
|
||||
$display("[OK]");
|
||||
else
|
||||
$display("[ERROR]");
|
||||
if ((tmp_input_val < MIN_VALUE + OTR_OFFSET) ||
|
||||
(tmp_input_val > MAX_VALUE - OTR_OFFSET)) begin
|
||||
// need clipping
|
||||
tmp_input_val = ((tmp_input_val - MIN_VALUE) < 2**(DATA_WIDTH-1)) ?
|
||||
MIN_VALUE : MAX_VALUE;
|
||||
end
|
||||
|
||||
repeat(10) @(posedge clk);
|
||||
end
|
||||
endtask
|
||||
|
||||
// =====================================================
|
||||
// RANDOM TESTS
|
||||
// =====================================================
|
||||
task automatic random_stress_test;
|
||||
int n;
|
||||
begin
|
||||
for (int i = 0; i < 20; i++) begin
|
||||
n = $urandom_range(5,20);
|
||||
|
||||
$display("\n--- TEST %0d --- n=%0d", i, n);
|
||||
|
||||
run_test_case(
|
||||
n,
|
||||
1,
|
||||
1
|
||||
);
|
||||
if (tmp_input_val != tmp_output_val)
|
||||
flag = 1;
|
||||
end
|
||||
// $display("Total: %0d", output_values.size());
|
||||
if (flag) begin
|
||||
$display("[ERROR] -run_test_case- Sampled data not correct and not equal to generated signal.");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
// =====================================================
|
||||
// MAIN
|
||||
// =====================================================
|
||||
initial begin
|
||||
int random_number;
|
||||
|
||||
$display("\n=== BASIC TEST ===");
|
||||
run_test_case(10, 0, 0);
|
||||
|
||||
$display("\n=== OUT_OF_RANGE TEST ===");
|
||||
run_test_case(20, 1, 1);
|
||||
rst_dut = 1;
|
||||
rst_gen = 1;
|
||||
smp_num = 0;
|
||||
repeat(2) @(posedge clk);
|
||||
rst_dut = 0;
|
||||
repeat(2) @(posedge clk);
|
||||
|
||||
$display("basic test #1");
|
||||
run_test_case(10);
|
||||
run_test_case(100);
|
||||
run_test_case(10000);
|
||||
$display("basic test #2");
|
||||
run_test_case(0);
|
||||
|
||||
$display("\n=== RANDOM STRESS TEST ===");
|
||||
random_stress_test();
|
||||
|
||||
for (int i = 0; i < 10; i++) begin
|
||||
$display("Random test #%0d", i);
|
||||
random_number = $urandom_range(0, 3 * 2**(DATA_WIDTH)); // up to 1.5 triangle waves
|
||||
run_test_case(random_number);
|
||||
end
|
||||
|
||||
$display("\n=== TEST FINISHED ===");
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
module triangle_wave_gen #(
|
||||
parameter DATA_WIDTH = 12,
|
||||
parameter OFFSET = 100, // offset of bits from '0 and '1 for OTR
|
||||
parameter STEP = 1 // LSB bit per clock
|
||||
) (
|
||||
input clk,
|
||||
input rst,
|
||||
output logic [DATA_WIDTH-1:0] signal,
|
||||
output logic otr
|
||||
);
|
||||
logic [DATA_WIDTH:0] counter;
|
||||
logic direction;
|
||||
|
||||
initial begin
|
||||
counter = '0;
|
||||
direction = 1;
|
||||
end
|
||||
|
||||
assign signal = counter > (2**DATA_WIDTH-1) ? (2**DATA_WIDTH-1) : counter;
|
||||
|
||||
always_comb begin
|
||||
if (signal < OFFSET || (2**DATA_WIDTH - signal) <= OFFSET)
|
||||
otr <= 1;
|
||||
else
|
||||
otr <= 0;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
counter = 0;
|
||||
direction = 1;
|
||||
end else begin
|
||||
if (direction)
|
||||
counter += STEP;
|
||||
else
|
||||
counter -= STEP;
|
||||
|
||||
if (counter >= 2**DATA_WIDTH-1 || counter <= 0)
|
||||
direction <= ~direction;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user