`timescale 1ns / 1ps module tb_accumulator; localparam DATA_WIDTH = 12; localparam ACCUM_WIDTH = 32; localparam N_MAX = 64; localparam WINDOW_SIZE = 4; localparam PACKET_SIZE = 8; // bytes localparam READ_BATCH_SIZE = (PACKET_SIZE*8)/ACCUM_WIDTH; // = 2 reg clk_in; reg rst; reg [DATA_WIDTH-1:0] s_axis_tdata; reg s_axis_tvalid; reg start; reg [31:0] smp_num; reg [15:0] seq_num; wire [ACCUM_WIDTH-1:0] out_data; wire out_valid; wire readout_begin; reg batch_req; reg finish; integer i; integer out_count; reg [ACCUM_WIDTH-1:0] expected [0:READ_BATCH_SIZE-1]; reg [ACCUM_WIDTH-1:0] got [0:READ_BATCH_SIZE-1]; accumulator #( .DATA_WIDTH(DATA_WIDTH), .ACCUM_WIDTH(ACCUM_WIDTH), .N_MAX(N_MAX), .WINDOW_SIZE(WINDOW_SIZE), .PACKET_SIZE(PACKET_SIZE) ) dut ( .clk_in(clk_in), .rst(rst), .s_axis_tdata(s_axis_tdata), .s_axis_tvalid(s_axis_tvalid), .start(start), .smp_num(smp_num), .seq_num(seq_num), .out_data(out_data), .out_valid(out_valid), .readout_begin(readout_begin), .batch_req(batch_req), .finish(finish) ); // clock 100 MHz initial begin clk_in = 0; forever #5 clk_in = ~clk_in; end // send one sample task send_sample(input [DATA_WIDTH-1:0] val); begin @(posedge clk_in); s_axis_tdata <= val; s_axis_tvalid <= 1'b1; end endtask // one idle cycle after valid stream task end_stream; begin @(posedge clk_in); s_axis_tvalid <= 1'b0; s_axis_tdata <= '0; end endtask // pulse start task pulse_start; begin @(posedge clk_in); start <= 1'b1; @(posedge clk_in); start <= 1'b0; end endtask // pulse batch request task pulse_batch_req; begin @(posedge clk_in); batch_req <= 1'b1; @(posedge clk_in); batch_req <= 1'b0; end endtask initial begin repeat(100) @(posedge clk_in); // init rst = 1'b1; s_axis_tdata = '0; s_axis_tvalid= 1'b0; start = 1'b0; smp_num = 32'd8; seq_num = 16'd2; batch_req = 1'b0; finish = 1'b0; expected[0] = 32'd60; expected[1] = 32'd92; repeat(50) @(posedge clk_in); rst = 1'b0; repeat(50) @(posedge clk_in); $display("=== TEST START ==="); pulse_start(); // seq 0: [1..8] send_sample(12'd1); send_sample(12'd2); send_sample(12'd3); send_sample(12'd4); send_sample(12'd5); send_sample(12'd6); send_sample(12'd7); send_sample(12'd8); end_stream(); // небольшой зазор repeat(5) @(posedge clk_in); // seq 1: [11..18] send_sample(12'd11); send_sample(12'd12); send_sample(12'd13); send_sample(12'd14); send_sample(12'd15); send_sample(12'd16); send_sample(12'd17); send_sample(12'd18); end_stream(); $display("[%0t] all input data sent, waiting readout_begin...", $time); wait(readout_begin == 1'b1); $display("[%0t] readout_begin asserted", $time); repeat(22) @(posedge clk_in); pulse_batch_req(); out_count = 0; // ждём два слова while (out_count < READ_BATCH_SIZE) begin @(posedge clk_in); if (out_valid) begin got[out_count] = out_data; $display("[%0t] out_valid: got[%0d] = %0d", $time, out_count, out_data); out_count = out_count + 1; end end // проверка for (i = 0; i < READ_BATCH_SIZE; i = i + 1) begin if (got[i] !== expected[i]) begin $error("Mismatch at index %0d: got=%0d expected=%0d", i, got[i], expected[i]); end else begin $display("OK index %0d: %0d", i, got[i]); end end // завершаем readout @(posedge clk_in); finish <= 1'b1; repeat(10) @(posedge clk_in); $display("=== TEST PASSED ==="); $finish; end endmodule