`timescale 1ns / 1ps module sampler_tb; localparam DATA_WIDTH = 12; localparam PACK_FACTOR = 7; localparam PROCESS_MODE = 0; localparam CLK_PERIOD = 15.3846; localparam OTR_OFFSET = 0; logic clk; logic rst_dut; logic rst_gen; wire [DATA_WIDTH-1:0] data_in; wire 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; sampler #( .DATA_WIDTH (DATA_WIDTH), .PACK_FACTOR (PACK_FACTOR), .PROCESS_MODE(PROCESS_MODE) ) dut ( .clk_in (clk), .rst (rst_dut), .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 // ===================================================== task automatic reset_dut(); @(posedge clk); rst_dut = 1; @(posedge clk); rst_dut = 0; endtask // ===================================================== // FEED DATA // ===================================================== 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) ); // ===================================================== // TEST TASKS // ===================================================== task automatic run_test_case( input int sample_num ); logic [DATA_WIDTH-1:0] input_values[$]; logic [DATA_WIDTH-1:0] output_values[$]; bit flag; // Startup sequence rst_gen <= 1; smp_num <= sample_num; request <= 1; @(posedge clk); // 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 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 // Wait until end // while (dut.synced) // @(posedge clk); wait(dut.synced === 0); disable stat_mon_proc; // Pop last input value. Signal is ahead of tdata for 1 cycle input_values.pop_back(); // check data if (input_values.size() != 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 < input_values.size(); i++) begin $write(" %0d", input_values[i]); if (input_values[i] != output_values[i]) flag = 1; end $write("\n"); for (int i = 0; i < input_values.size(); i++) begin $write(" %0d", output_values[i]); end $write("\n"); $display("Total: %0d", output_values.size()); if (flag) $display("FUCK"); else $display("SUCKASS"); endtask // ===================================================== // MAIN // ===================================================== initial begin $display("\n=== BASIC TEST ==="); rst_dut = 1; rst_gen = 1; smp_num = 0; repeat(2) @(posedge clk); rst_dut = 0; repeat(2) @(posedge clk); run_test_case(100); $display("\n=== RANDOM STRESS TEST ==="); // todo $display("\n=== TEST FINISHED ==="); $finish; end 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