`timescale 1ns / 1ps module sampler_tb; // ========================================================= // PARAMETERS // ========================================================= localparam DATA_WIDTH = 12; localparam PACK_FACTOR = 1; localparam PROCESS_MODE = 0; localparam CLK_PERIOD = 15.3846; // ========================================================= // SIGNALS // ========================================================= logic clk; logic rst; logic [DATA_WIDTH-1:0] data_in; logic out_of_range; logic [31:0] smp_num; logic done; logic request; logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata; logic m_axis_tvalid; // ========================================================= // DUT // ========================================================= sampler #( .DATA_WIDTH(DATA_WIDTH), .PACK_FACTOR(PACK_FACTOR), .PROCESS_MODE(PROCESS_MODE) ) dut ( .clk_in(clk), .rst(rst), .data_in(data_in), .out_of_range(out_of_range), .smp_num(smp_num), .done(done), .m_axis_tdata(m_axis_tdata), .m_axis_tvalid(m_axis_tvalid), .request(request) ); // ========================================================= // CLOCK // ========================================================= initial begin clk = 0; forever #(CLK_PERIOD/2) clk = ~clk; end // ========================================================= // RESET (ONLY ONCE) // ========================================================= initial begin rst = 1; done = 0; data_in = 0; out_of_range = 0; smp_num = 0; repeat(5) @(posedge clk); rst = 0; end // ========================================================= // CONFIG // ========================================================= task automatic set_config( 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 else begin wait(request == 1'b1); repeat(delay_before_ack) @(posedge clk); done <= 1'b1; repeat(ack_duration) @(posedge clk); done <= 1'b0; end endtask // ========================================================= // 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 $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; end endmodule