rtl: sampler synchronization work, not totally ready
This commit is contained in:
@ -1,7 +1,5 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module sampler
|
module sampler
|
||||||
#(
|
#(
|
||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
@ -14,16 +12,16 @@ module sampler
|
|||||||
input [DATA_WIDTH-1:0] data_in,
|
input [DATA_WIDTH-1:0] data_in,
|
||||||
input out_of_range,
|
input out_of_range,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input sample_req,
|
input done,
|
||||||
|
|
||||||
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||||
output logic m_axis_tvalid,
|
output logic m_axis_tvalid,
|
||||||
output logic sample_done
|
output logic request
|
||||||
);
|
);
|
||||||
(* MARK_DEBUG="true" *) logic [DATA_WIDTH-1:0] data_converted;
|
(* MARK_DEBUG="true" *) logic [DATA_WIDTH-1:0] data_converted;
|
||||||
(* MARK_DEBUG="true" *) logic out_of_range_reg;
|
(* MARK_DEBUG="true" *) logic out_of_range_reg;
|
||||||
(* MARK_DEBUG="true" *) logic [31:0] smp_num_reg, cnt_smp_num;
|
(* MARK_DEBUG="true" *) logic [31:0] smp_num_reg, cnt_smp_num;
|
||||||
(* MARK_DEBUG="true" *) logic enable;
|
(* MARK_DEBUG="true" *) logic enable, enable_d;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (PROCESS_MODE) begin
|
if (PROCESS_MODE) begin
|
||||||
@ -68,20 +66,22 @@ module sampler
|
|||||||
buffer_ready <= 0;
|
buffer_ready <= 0;
|
||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
smp_num_reg <= '0;
|
smp_num_reg <= '0;
|
||||||
enable <= '0;
|
enable <= 0;
|
||||||
sample_done <= 0;
|
request <= 0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
buffer_ready <= 0;
|
buffer_ready <= 0;
|
||||||
if (sample_done && !sample_req) begin
|
enable_d <= enable;
|
||||||
sample_done <= 1'b0;
|
if (!enable) begin
|
||||||
end
|
if (request && done) begin
|
||||||
if (!enable && sample_req && !sample_done) begin
|
|
||||||
enable <= 1;
|
enable <= 1;
|
||||||
|
request <= 0;
|
||||||
cnt_smp_num <= 0;
|
cnt_smp_num <= 0;
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
|
end else begin
|
||||||
|
request <= 1;
|
||||||
end
|
end
|
||||||
if (enable) begin
|
end else begin
|
||||||
if (!out_of_range_reg) begin
|
if (!out_of_range_reg) begin
|
||||||
if (cnt_smp_num != smp_num_reg) begin
|
if (cnt_smp_num != smp_num_reg) begin
|
||||||
buffer <= data_converted;
|
buffer <= data_converted;
|
||||||
@ -90,8 +90,6 @@ module sampler
|
|||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
sample_done <= 1'b1;
|
|
||||||
buffer_ready <= 0;
|
|
||||||
buffer <= '0;
|
buffer <= '0;
|
||||||
enable <= 0;
|
enable <= 0;
|
||||||
end
|
end
|
||||||
@ -108,21 +106,21 @@ module sampler
|
|||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
smp_num_reg <= '0;
|
smp_num_reg <= '0;
|
||||||
enable <= 0;
|
enable <= 0;
|
||||||
sample_done <= 0;
|
request <= 0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
buffer_ready <= 0;
|
buffer_ready <= 0;
|
||||||
if (sample_done && !sample_req) begin
|
if (!enable) begin
|
||||||
sample_done <= 1'b0;
|
if (!request) request <= 1;
|
||||||
end
|
if (request && done) begin
|
||||||
if (!enable && sample_req && !sample_done) begin
|
|
||||||
enable <= 1;
|
enable <= 1;
|
||||||
|
request <= 0;
|
||||||
cnt_smp_num <= 0;
|
cnt_smp_num <= 0;
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
end
|
end
|
||||||
if (enable) begin
|
end else begin
|
||||||
if (!out_of_range_reg) begin
|
if (!out_of_range_reg) begin
|
||||||
if (cnt_smp_num != smp_num_reg) begin
|
if (cnt_smp_num < smp_num_reg) begin
|
||||||
cnt_smp_num <= cnt_smp_num +1;
|
cnt_smp_num <= cnt_smp_num +1;
|
||||||
buffer <= {buffer[DATA_WIDTH*(PACK_FACTOR-1)-1:0], data_converted};
|
buffer <= {buffer[DATA_WIDTH*(PACK_FACTOR-1)-1:0], data_converted};
|
||||||
if (cnt == PACK_FACTOR-1) begin
|
if (cnt == PACK_FACTOR-1) begin
|
||||||
@ -135,7 +133,6 @@ module sampler
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
sample_done <= 1'b1;
|
|
||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
buffer_ready <= 0;
|
buffer_ready <= 0;
|
||||||
buffer <= '0;
|
buffer <= '0;
|
||||||
|
|||||||
@ -2,130 +2,209 @@
|
|||||||
|
|
||||||
module sampler_tb;
|
module sampler_tb;
|
||||||
|
|
||||||
parameter DATA_WIDTH = 12;
|
// =========================================================
|
||||||
parameter PROCESS_MODE = 0;
|
// PARAMETERS
|
||||||
parameter CLK_PERIOD = 15.3846;
|
// =========================================================
|
||||||
parameter TEST_NUM = 1000;
|
localparam DATA_WIDTH = 12;
|
||||||
|
localparam PACK_FACTOR = 1;
|
||||||
|
localparam PROCESS_MODE = 0;
|
||||||
|
localparam CLK_PERIOD = 15.3846;
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// SIGNALS
|
||||||
|
// =========================================================
|
||||||
logic clk;
|
logic clk;
|
||||||
logic rst;
|
logic rst;
|
||||||
|
|
||||||
logic [DATA_WIDTH-1:0] data_in;
|
logic [DATA_WIDTH-1:0] data_in;
|
||||||
logic out_of_range;
|
logic out_of_range;
|
||||||
|
|
||||||
logic [DATA_WIDTH-1:0] m_axis_tdata;
|
logic [31:0] smp_num;
|
||||||
|
|
||||||
|
logic done;
|
||||||
|
logic request;
|
||||||
|
|
||||||
|
logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||||
logic m_axis_tvalid;
|
logic m_axis_tvalid;
|
||||||
|
|
||||||
integer errors = 0;
|
// =========================================================
|
||||||
|
// DUT
|
||||||
|
// =========================================================
|
||||||
sampler #(
|
sampler #(
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.PACK_FACTOR(PACK_FACTOR),
|
||||||
.PROCESS_MODE(PROCESS_MODE)
|
.PROCESS_MODE(PROCESS_MODE)
|
||||||
) dut (
|
) dut (
|
||||||
.clk_in(clk),
|
.clk_in(clk),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
|
|
||||||
.data_in(data_in),
|
.data_in(data_in),
|
||||||
.out_of_range(out_of_range),
|
.out_of_range(out_of_range),
|
||||||
|
|
||||||
|
.smp_num(smp_num),
|
||||||
|
.done(done),
|
||||||
|
|
||||||
.m_axis_tdata(m_axis_tdata),
|
.m_axis_tdata(m_axis_tdata),
|
||||||
.m_axis_tvalid(m_axis_tvalid)
|
.m_axis_tvalid(m_axis_tvalid),
|
||||||
|
|
||||||
|
.request(request)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// CLOCK
|
||||||
|
// =========================================================
|
||||||
initial begin
|
initial begin
|
||||||
clk = 0;
|
clk = 0;
|
||||||
forever #(CLK_PERIOD/2) clk = ~clk;
|
forever #(CLK_PERIOD/2) clk = ~clk;
|
||||||
end
|
end
|
||||||
|
|
||||||
function automatic [DATA_WIDTH-1:0] ref_convert(input [DATA_WIDTH-1:0] din);
|
// =========================================================
|
||||||
if (PROCESS_MODE == 0)
|
// RESET (ONLY ONCE)
|
||||||
return din;
|
// =========================================================
|
||||||
else if (din == {1'b1, {(DATA_WIDTH-1){1'b0}}})
|
|
||||||
return din;
|
|
||||||
else
|
|
||||||
return din[DATA_WIDTH-1] ?
|
|
||||||
{1'b1, (~din[DATA_WIDTH-2:0] + 1'b1)} :
|
|
||||||
din;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
task send(input [DATA_WIDTH-1:0] word, input bit oor);
|
|
||||||
@(posedge clk);
|
|
||||||
data_in <= word;
|
|
||||||
out_of_range <= oor;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
logic [DATA_WIDTH-1:0] exp_d0, exp_d1, exp_d2;
|
|
||||||
logic oor_d0, oor_d1, oor_d2;
|
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
$display("\n=== RANDOM SAMPLER TEST===\n");
|
|
||||||
|
|
||||||
rst = 1;
|
rst = 1;
|
||||||
|
done = 0;
|
||||||
data_in = 0;
|
data_in = 0;
|
||||||
out_of_range = 0;
|
out_of_range = 0;
|
||||||
|
smp_num = 0;
|
||||||
exp_d0 = 0;
|
|
||||||
exp_d1 = 0;
|
|
||||||
exp_d2 = 0;
|
|
||||||
|
|
||||||
oor_d0 = 1;
|
|
||||||
oor_d1 = 1;
|
|
||||||
oor_d2 = 1;
|
|
||||||
|
|
||||||
repeat(5) @(posedge clk);
|
repeat(5) @(posedge clk);
|
||||||
rst = 0;
|
rst = 0;
|
||||||
repeat(2) @(posedge clk);
|
|
||||||
|
|
||||||
repeat (TEST_NUM) begin
|
|
||||||
logic [DATA_WIDTH-1:0] rand_data;
|
|
||||||
bit rand_oor;
|
|
||||||
|
|
||||||
rand_data = $urandom_range(0, (1 << DATA_WIDTH) - 1);
|
|
||||||
rand_oor = ($urandom_range(0, 99) < 20);
|
|
||||||
|
|
||||||
@(negedge clk);
|
|
||||||
|
|
||||||
if (!oor_d2) begin
|
|
||||||
if (m_axis_tvalid !== 1) begin
|
|
||||||
$display("ERROR: valid=0");
|
|
||||||
errors++;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (m_axis_tdata !== exp_d2) begin
|
// =========================================================
|
||||||
$display("ERROR: data mismatch");
|
// CONFIG
|
||||||
$display(" expected = %h", exp_d2);
|
// =========================================================
|
||||||
$display(" got = %h", m_axis_tdata);
|
task automatic set_config(
|
||||||
errors++;
|
input int n,
|
||||||
|
input int init_delay
|
||||||
|
);
|
||||||
|
smp_num = n;
|
||||||
|
repeat(init_delay) @(posedge clk);
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// HANDSHAKE (DONE/REQUEST)
|
||||||
|
// =========================================================
|
||||||
|
task automatic synchronize_sampler(
|
||||||
|
input bit sampler_first,
|
||||||
|
input int delay_before_ack,
|
||||||
|
input int ack_duration
|
||||||
|
);
|
||||||
|
if (sampler_first) begin
|
||||||
|
repeat(delay_before_ack) @(posedge clk);
|
||||||
|
|
||||||
|
done <= 1'b1;
|
||||||
|
wait(request == 1'b1);
|
||||||
|
|
||||||
|
repeat(ack_duration) @(posedge clk);
|
||||||
|
|
||||||
|
done <= 1'b0;
|
||||||
end
|
end
|
||||||
|
else begin
|
||||||
|
wait(request == 1'b1);
|
||||||
|
|
||||||
|
repeat(delay_before_ack) @(posedge clk);
|
||||||
|
|
||||||
|
done <= 1'b1;
|
||||||
|
|
||||||
|
repeat(ack_duration) @(posedge clk);
|
||||||
|
|
||||||
|
done <= 1'b0;
|
||||||
end
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
send(rand_data, rand_oor);
|
// =========================================================
|
||||||
|
// DATA STREAM (STARTS AFTER SYNC)
|
||||||
exp_d2 = exp_d1;
|
// =========================================================
|
||||||
exp_d1 = exp_d0;
|
task automatic feed_data_stream(
|
||||||
exp_d0 = ref_convert(rand_data);
|
input int num_words,
|
||||||
|
input bit random_mode
|
||||||
oor_d2 = oor_d1;
|
);
|
||||||
oor_d1 = oor_d0;
|
logic [DATA_WIDTH-1:0] val;
|
||||||
oor_d0 = rand_oor;
|
val = 1;
|
||||||
end
|
|
||||||
|
|
||||||
|
for (int i = 0; i < num_words; i++) begin
|
||||||
@(posedge clk);
|
@(posedge clk);
|
||||||
|
|
||||||
|
if (random_mode)
|
||||||
if (!oor_d2) begin
|
val = $urandom_range(1, 2**DATA_WIDTH-1);
|
||||||
|
|
||||||
if (m_axis_tdata !== exp_d2) begin
|
|
||||||
$display("ERROR: final mismatch");
|
|
||||||
$display(" expected = %h", exp_d2);
|
|
||||||
$display(" got = %h", m_axis_tdata);
|
|
||||||
errors++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (errors == 0)
|
|
||||||
$display("\n========== ALL PASSED ==========\n");
|
|
||||||
else
|
else
|
||||||
$display("\n========== FAILED: %0d errors ==========\n", errors);
|
val = val + 1;
|
||||||
|
|
||||||
|
data_in <= val;
|
||||||
|
out_of_range <= 0;
|
||||||
|
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// COUNTER
|
||||||
|
// =========================================================
|
||||||
|
int received_count;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (m_axis_tvalid)
|
||||||
|
received_count++;
|
||||||
|
end
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// TEST CASE
|
||||||
|
// =========================================================
|
||||||
|
task automatic run_test_case(
|
||||||
|
input int n,
|
||||||
|
input int delay,
|
||||||
|
input int ack,
|
||||||
|
input bit sampler_first,
|
||||||
|
input bit random_stream
|
||||||
|
);
|
||||||
|
received_count = 0;
|
||||||
|
|
||||||
|
set_config(n, 2);
|
||||||
|
|
||||||
|
// 1) сначала синхронизация
|
||||||
|
synchronize_sampler(sampler_first, delay, ack);
|
||||||
|
|
||||||
|
// 2) СРАЗУ после sync - поток данных
|
||||||
|
feed_data_stream(n, random_stream);
|
||||||
|
|
||||||
|
repeat(20) @(posedge clk);
|
||||||
|
|
||||||
|
if (received_count == n)
|
||||||
|
$display("[OK] received %0d / %0d", received_count, n);
|
||||||
|
else
|
||||||
|
$display("[ERROR] received %0d / %0d", received_count, n);
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// RANDOM STRESS TEST
|
||||||
|
// =========================================================
|
||||||
|
task automatic check_random;
|
||||||
|
int n, d, a;
|
||||||
|
bit sf;
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++) begin
|
||||||
|
n = $urandom_range(3, 10);
|
||||||
|
d = $urandom_range(0, 5);
|
||||||
|
a = $urandom_range(1, 5);
|
||||||
|
sf = $urandom_range(0, 1);
|
||||||
|
|
||||||
|
$display("\n--- TEST %0d --- n=%0d delay=%0d ack=%0d sf=%0b",
|
||||||
|
i, n, d, a, sf);
|
||||||
|
|
||||||
|
run_test_case(n, d, a, sf, 1);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// MAIN
|
||||||
|
// =========================================================
|
||||||
|
initial begin
|
||||||
|
$display("\n=== SAMPLER TEST (FIXED FLOW: NO MULTI RESET) ===\n");
|
||||||
|
|
||||||
|
check_random();
|
||||||
|
|
||||||
|
$display("\n=== TEST FINISHED ===");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user