rtl: sampler synchronization work, not totally ready

This commit is contained in:
otroubi
2026-06-09 21:07:09 +03:00
parent d90167984a
commit b0e886893b
2 changed files with 185 additions and 109 deletions

View File

@ -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 end else begin
if (enable) begin request <= 1;
end
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;

View File

@ -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); end
repeat (TEST_NUM) begin // =========================================================
logic [DATA_WIDTH-1:0] rand_data; // CONFIG
bit rand_oor; // =========================================================
task automatic set_config(
input int n,
input int init_delay
);
smp_num = n;
repeat(init_delay) @(posedge clk);
endtask
rand_data = $urandom_range(0, (1 << DATA_WIDTH) - 1); // =========================================================
rand_oor = ($urandom_range(0, 99) < 20); // 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);
@(negedge clk); done <= 1'b1;
wait(request == 1'b1);
if (!oor_d2) begin repeat(ack_duration) @(posedge clk);
if (m_axis_tvalid !== 1) begin
$display("ERROR: valid=0");
errors++;
end
if (m_axis_tdata !== exp_d2) begin done <= 1'b0;
$display("ERROR: data mismatch");
$display(" expected = %h", exp_d2);
$display(" got = %h", m_axis_tdata);
errors++;
end
end
send(rand_data, rand_oor);
exp_d2 = exp_d1;
exp_d1 = exp_d0;
exp_d0 = ref_convert(rand_data);
oor_d2 = oor_d1;
oor_d1 = oor_d0;
oor_d0 = rand_oor;
end end
else begin
wait(request == 1'b1);
@(posedge clk); repeat(delay_before_ack) @(posedge clk);
done <= 1'b1;
if (!oor_d2) begin repeat(ack_duration) @(posedge clk);
if (m_axis_tdata !== exp_d2) begin done <= 1'b0;
$display("ERROR: final mismatch");
$display(" expected = %h", exp_d2);
$display(" got = %h", m_axis_tdata);
errors++;
end
end end
endtask
if (errors == 0) // =========================================================
$display("\n========== ALL PASSED ==========\n"); // DATA STREAM (STARTS AFTER SYNC)
// =========================================================
task automatic feed_data_stream(
input int num_words,
input bit random_mode
);
logic [DATA_WIDTH-1:0] val;
val = 1;
for (int i = 0; i < num_words; i++) begin
@(posedge clk);
if (random_mode)
val = $urandom_range(1, 2**DATA_WIDTH-1);
else
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 else
$display("\n========== FAILED: %0d errors ==========\n", errors); $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