`timescale 1ns / 1ps

module tb_streaming_dot_product8;
    reg clk;
    reg rst;
    reg in_valid;
    reg [7:0] a_data;
    reg [7:0] b_data;
    reg last_in;

    wire result_valid;
    wire [31:0] result;

    integer errors = 0;
    integer tests_run = 0;
    integer cycle_count = 0;
    integer i;

    streaming_dot_product8 uut (
        .clk(clk),
        .rst(rst),
        .in_valid(in_valid),
        .a_data(a_data),
        .b_data(b_data),
        .last_in(last_in),
        .result_valid(result_valid),
        .result(result)
    );

    initial begin
        clk = 1'b0;
        forever #5 clk = ~clk;
    end

// Generated by generate_golden.py and copied here. Do not edit by hand.
localparam integer NUM_TESTS = 60;
reg test_rst [0:NUM_TESTS-1];
reg test_in_valid [0:NUM_TESTS-1];
reg [7:0] test_a_data [0:NUM_TESTS-1];
reg [7:0] test_b_data [0:NUM_TESTS-1];
reg test_last_in [0:NUM_TESTS-1];
reg expected_result_valid [0:NUM_TESTS-1];
reg [31:0] expected_result [0:NUM_TESTS-1];
reg [255:0] test_tag [0:NUM_TESTS-1];

initial begin
    test_rst[0] = 1'b1;
    test_in_valid[0] = 1'b0;
    test_a_data[0] = 8'h00;
    test_b_data[0] = 8'h00;
    test_last_in[0] = 1'b0;
    expected_result_valid[0] = 1'b0;
    expected_result[0] = 32'h00000000;
    test_tag[0] = "startup_reset";
    test_rst[1] = 1'b1;
    test_in_valid[1] = 1'b1;
    test_a_data[1] = 8'h0c;
    test_b_data[1] = 8'hfd;
    test_last_in[1] = 1'b1;
    expected_result_valid[1] = 1'b0;
    expected_result[1] = 32'h00000000;
    test_tag[1] = "reset_ignore_input";
    test_rst[2] = 1'b0;
    test_in_valid[2] = 1'b0;
    test_a_data[2] = 8'h00;
    test_b_data[2] = 8'h00;
    test_last_in[2] = 1'b1;
    expected_result_valid[2] = 1'b0;
    expected_result[2] = 32'h00000000;
    test_tag[2] = "post_reset_idle_last_ignored";
    test_rst[3] = 1'b0;
    test_in_valid[3] = 1'b1;
    test_a_data[3] = 8'h01;
    test_b_data[3] = 8'h08;
    test_last_in[3] = 1'b0;
    expected_result_valid[3] = 1'b0;
    expected_result[3] = 32'h00000000;
    test_tag[3] = "vec0_basic_p0";
    test_rst[4] = 1'b0;
    test_in_valid[4] = 1'b1;
    test_a_data[4] = 8'h02;
    test_b_data[4] = 8'h07;
    test_last_in[4] = 1'b0;
    expected_result_valid[4] = 1'b0;
    expected_result[4] = 32'h00000000;
    test_tag[4] = "vec0_basic_p1";
    test_rst[5] = 1'b0;
    test_in_valid[5] = 1'b1;
    test_a_data[5] = 8'h03;
    test_b_data[5] = 8'h06;
    test_last_in[5] = 1'b0;
    expected_result_valid[5] = 1'b0;
    expected_result[5] = 32'h00000000;
    test_tag[5] = "vec0_basic_p2";
    test_rst[6] = 1'b0;
    test_in_valid[6] = 1'b1;
    test_a_data[6] = 8'h04;
    test_b_data[6] = 8'h05;
    test_last_in[6] = 1'b0;
    expected_result_valid[6] = 1'b0;
    expected_result[6] = 32'h00000000;
    test_tag[6] = "vec0_basic_p3";
    test_rst[7] = 1'b0;
    test_in_valid[7] = 1'b1;
    test_a_data[7] = 8'h05;
    test_b_data[7] = 8'h04;
    test_last_in[7] = 1'b0;
    expected_result_valid[7] = 1'b0;
    expected_result[7] = 32'h00000000;
    test_tag[7] = "vec0_basic_p4";
    test_rst[8] = 1'b0;
    test_in_valid[8] = 1'b1;
    test_a_data[8] = 8'h06;
    test_b_data[8] = 8'h03;
    test_last_in[8] = 1'b0;
    expected_result_valid[8] = 1'b0;
    expected_result[8] = 32'h00000000;
    test_tag[8] = "vec0_basic_p5";
    test_rst[9] = 1'b0;
    test_in_valid[9] = 1'b1;
    test_a_data[9] = 8'h07;
    test_b_data[9] = 8'h02;
    test_last_in[9] = 1'b0;
    expected_result_valid[9] = 1'b0;
    expected_result[9] = 32'h00000000;
    test_tag[9] = "vec0_basic_p6";
    test_rst[10] = 1'b0;
    test_in_valid[10] = 1'b1;
    test_a_data[10] = 8'h08;
    test_b_data[10] = 8'h01;
    test_last_in[10] = 1'b1;
    expected_result_valid[10] = 1'b0;
    expected_result[10] = 32'h00000000;
    test_tag[10] = "vec0_basic_p7";
    test_rst[11] = 1'b0;
    test_in_valid[11] = 1'b1;
    test_a_data[11] = 8'hfd;
    test_b_data[11] = 8'h0a;
    test_last_in[11] = 1'b0;
    expected_result_valid[11] = 1'b0;
    expected_result[11] = 32'h00000000;
    test_tag[11] = "vec1_mixed_p0";
    test_rst[12] = 1'b0;
    test_in_valid[12] = 1'b1;
    test_a_data[12] = 8'h04;
    test_b_data[12] = 8'hfb;
    test_last_in[12] = 1'b0;
    expected_result_valid[12] = 1'b1;
    expected_result[12] = 32'h00000078;
    test_tag[12] = "vec1_mixed_p1";
    test_rst[13] = 1'b0;
    test_in_valid[13] = 1'b1;
    test_a_data[13] = 8'h00;
    test_b_data[13] = 8'h09;
    test_last_in[13] = 1'b0;
    expected_result_valid[13] = 1'b0;
    expected_result[13] = 32'h00000000;
    test_tag[13] = "vec1_mixed_p2";
    test_rst[14] = 1'b0;
    test_in_valid[14] = 1'b1;
    test_a_data[14] = 8'hf8;
    test_b_data[14] = 8'hfe;
    test_last_in[14] = 1'b0;
    expected_result_valid[14] = 1'b0;
    expected_result[14] = 32'h00000000;
    test_tag[14] = "vec1_mixed_p3";
    test_rst[15] = 1'b0;
    test_in_valid[15] = 1'b1;
    test_a_data[15] = 8'h07;
    test_b_data[15] = 8'h03;
    test_last_in[15] = 1'b0;
    expected_result_valid[15] = 1'b0;
    expected_result[15] = 32'h00000000;
    test_tag[15] = "vec1_mixed_p4";
    test_rst[16] = 1'b0;
    test_in_valid[16] = 1'b1;
    test_a_data[16] = 8'hff;
    test_b_data[16] = 8'h0c;
    test_last_in[16] = 1'b0;
    expected_result_valid[16] = 1'b0;
    expected_result[16] = 32'h00000000;
    test_tag[16] = "vec1_mixed_p5";
    test_rst[17] = 1'b0;
    test_in_valid[17] = 1'b1;
    test_a_data[17] = 8'h0f;
    test_b_data[17] = 8'hfc;
    test_last_in[17] = 1'b0;
    expected_result_valid[17] = 1'b0;
    expected_result[17] = 32'h00000000;
    test_tag[17] = "vec1_mixed_p6";
    test_rst[18] = 1'b0;
    test_in_valid[18] = 1'b1;
    test_a_data[18] = 8'hfa;
    test_b_data[18] = 8'hf9;
    test_last_in[18] = 1'b1;
    expected_result_valid[18] = 1'b0;
    expected_result[18] = 32'h00000000;
    test_tag[18] = "vec1_mixed_p7";
    test_rst[19] = 1'b0;
    test_in_valid[19] = 1'b1;
    test_a_data[19] = 8'h7f;
    test_b_data[19] = 8'h7f;
    test_last_in[19] = 1'b0;
    expected_result_valid[19] = 1'b0;
    expected_result[19] = 32'h00000000;
    test_tag[19] = "vec2_extreme_p0";
    test_rst[20] = 1'b0;
    test_in_valid[20] = 1'b1;
    test_a_data[20] = 8'h80;
    test_b_data[20] = 8'h7f;
    test_last_in[20] = 1'b0;
    expected_result_valid[20] = 1'b1;
    expected_result[20] = 32'hffffffd5;
    test_tag[20] = "vec2_extreme_p1";
    test_rst[21] = 1'b0;
    test_in_valid[21] = 1'b1;
    test_a_data[21] = 8'h40;
    test_b_data[21] = 8'hc0;
    test_last_in[21] = 1'b0;
    expected_result_valid[21] = 1'b0;
    expected_result[21] = 32'h00000000;
    test_tag[21] = "vec2_extreme_p2";
    test_rst[22] = 1'b0;
    test_in_valid[22] = 1'b1;
    test_a_data[22] = 8'hc0;
    test_b_data[22] = 8'hc0;
    test_last_in[22] = 1'b0;
    expected_result_valid[22] = 1'b0;
    expected_result[22] = 32'h00000000;
    test_tag[22] = "vec2_extreme_p3";
    test_rst[23] = 1'b0;
    test_in_valid[23] = 1'b1;
    test_a_data[23] = 8'h01;
    test_b_data[23] = 8'h80;
    test_last_in[23] = 1'b0;
    expected_result_valid[23] = 1'b0;
    expected_result[23] = 32'h00000000;
    test_tag[23] = "vec2_extreme_p4";
    test_rst[24] = 1'b0;
    test_in_valid[24] = 1'b1;
    test_a_data[24] = 8'hff;
    test_b_data[24] = 8'h80;
    test_last_in[24] = 1'b0;
    expected_result_valid[24] = 1'b0;
    expected_result[24] = 32'h00000000;
    test_tag[24] = "vec2_extreme_p5";
    test_rst[25] = 1'b0;
    test_in_valid[25] = 1'b1;
    test_a_data[25] = 8'h32;
    test_b_data[25] = 8'hfd;
    test_last_in[25] = 1'b0;
    expected_result_valid[25] = 1'b0;
    expected_result[25] = 32'h00000000;
    test_tag[25] = "vec2_extreme_p6";
    test_rst[26] = 1'b0;
    test_in_valid[26] = 1'b1;
    test_a_data[26] = 8'hce;
    test_b_data[26] = 8'hfd;
    test_last_in[26] = 1'b1;
    expected_result_valid[26] = 1'b0;
    expected_result[26] = 32'h00000000;
    test_tag[26] = "vec2_extreme_p7";
    test_rst[27] = 1'b0;
    test_in_valid[27] = 1'b1;
    test_a_data[27] = 8'h09;
    test_b_data[27] = 8'hfe;
    test_last_in[27] = 1'b0;
    expected_result_valid[27] = 1'b0;
    expected_result[27] = 32'h00000000;
    test_tag[27] = "partial_before_reset_p0";
    test_rst[28] = 1'b0;
    test_in_valid[28] = 1'b1;
    test_a_data[28] = 8'hf5;
    test_b_data[28] = 8'h05;
    test_last_in[28] = 1'b0;
    expected_result_valid[28] = 1'b1;
    expected_result[28] = 32'hffffff81;
    test_tag[28] = "partial_before_reset_p1";
    test_rst[29] = 1'b1;
    test_in_valid[29] = 1'b0;
    test_a_data[29] = 8'h00;
    test_b_data[29] = 8'h00;
    test_last_in[29] = 1'b0;
    expected_result_valid[29] = 1'b0;
    expected_result[29] = 32'h00000000;
    test_tag[29] = "mid_vector_reset";
    test_rst[30] = 1'b0;
    test_in_valid[30] = 1'b0;
    test_a_data[30] = 8'h00;
    test_b_data[30] = 8'h00;
    test_last_in[30] = 1'b0;
    expected_result_valid[30] = 1'b0;
    expected_result[30] = 32'h00000000;
    test_tag[30] = "idle_after_mid_vector_reset";
    test_rst[31] = 1'b0;
    test_in_valid[31] = 1'b1;
    test_a_data[31] = 8'h0a;
    test_b_data[31] = 8'h0a;
    test_last_in[31] = 1'b0;
    expected_result_valid[31] = 1'b0;
    expected_result[31] = 32'h00000000;
    test_tag[31] = "vec3_flush_pending_p0";
    test_rst[32] = 1'b0;
    test_in_valid[32] = 1'b1;
    test_a_data[32] = 8'h14;
    test_b_data[32] = 8'h01;
    test_last_in[32] = 1'b0;
    expected_result_valid[32] = 1'b0;
    expected_result[32] = 32'h00000000;
    test_tag[32] = "vec3_flush_pending_p1";
    test_rst[33] = 1'b0;
    test_in_valid[33] = 1'b1;
    test_a_data[33] = 8'he2;
    test_b_data[33] = 8'h02;
    test_last_in[33] = 1'b0;
    expected_result_valid[33] = 1'b0;
    expected_result[33] = 32'h00000000;
    test_tag[33] = "vec3_flush_pending_p2";
    test_rst[34] = 1'b0;
    test_in_valid[34] = 1'b1;
    test_a_data[34] = 8'h28;
    test_b_data[34] = 8'hfd;
    test_last_in[34] = 1'b0;
    expected_result_valid[34] = 1'b0;
    expected_result[34] = 32'h00000000;
    test_tag[34] = "vec3_flush_pending_p3";
    test_rst[35] = 1'b0;
    test_in_valid[35] = 1'b1;
    test_a_data[35] = 8'hce;
    test_b_data[35] = 8'hfc;
    test_last_in[35] = 1'b0;
    expected_result_valid[35] = 1'b0;
    expected_result[35] = 32'h00000000;
    test_tag[35] = "vec3_flush_pending_p4";
    test_rst[36] = 1'b0;
    test_in_valid[36] = 1'b1;
    test_a_data[36] = 8'h3c;
    test_b_data[36] = 8'h05;
    test_last_in[36] = 1'b0;
    expected_result_valid[36] = 1'b0;
    expected_result[36] = 32'h00000000;
    test_tag[36] = "vec3_flush_pending_p5";
    test_rst[37] = 1'b0;
    test_in_valid[37] = 1'b1;
    test_a_data[37] = 8'hba;
    test_b_data[37] = 8'h06;
    test_last_in[37] = 1'b0;
    expected_result_valid[37] = 1'b0;
    expected_result[37] = 32'h00000000;
    test_tag[37] = "vec3_flush_pending_p6";
    test_rst[38] = 1'b0;
    test_in_valid[38] = 1'b1;
    test_a_data[38] = 8'h50;
    test_b_data[38] = 8'hf9;
    test_last_in[38] = 1'b1;
    expected_result_valid[38] = 1'b0;
    expected_result[38] = 32'h00000000;
    test_tag[38] = "vec3_flush_pending_p7";
    test_rst[39] = 1'b1;
    test_in_valid[39] = 1'b0;
    test_a_data[39] = 8'h00;
    test_b_data[39] = 8'h00;
    test_last_in[39] = 1'b0;
    expected_result_valid[39] = 1'b0;
    expected_result[39] = 32'h00000000;
    test_tag[39] = "reset_flush_pending_output";
    test_rst[40] = 1'b0;
    test_in_valid[40] = 1'b0;
    test_a_data[40] = 8'h00;
    test_b_data[40] = 8'h00;
    test_last_in[40] = 1'b0;
    expected_result_valid[40] = 1'b0;
    expected_result[40] = 32'h00000000;
    test_tag[40] = "idle_after_flush_reset";
    test_rst[41] = 1'b0;
    test_in_valid[41] = 1'b1;
    test_a_data[41] = 8'h00;
    test_b_data[41] = 8'h00;
    test_last_in[41] = 1'b0;
    expected_result_valid[41] = 1'b0;
    expected_result[41] = 32'h00000000;
    test_tag[41] = "vec4_zero_p0";
    test_rst[42] = 1'b0;
    test_in_valid[42] = 1'b1;
    test_a_data[42] = 8'h00;
    test_b_data[42] = 8'h05;
    test_last_in[42] = 1'b0;
    expected_result_valid[42] = 1'b0;
    expected_result[42] = 32'h00000000;
    test_tag[42] = "vec4_zero_p1";
    test_rst[43] = 1'b0;
    test_in_valid[43] = 1'b1;
    test_a_data[43] = 8'h0c;
    test_b_data[43] = 8'h00;
    test_last_in[43] = 1'b0;
    expected_result_valid[43] = 1'b0;
    expected_result[43] = 32'h00000000;
    test_tag[43] = "vec4_zero_p2";
    test_rst[44] = 1'b0;
    test_in_valid[44] = 1'b1;
    test_a_data[44] = 8'h00;
    test_b_data[44] = 8'hf9;
    test_last_in[44] = 1'b0;
    expected_result_valid[44] = 1'b0;
    expected_result[44] = 32'h00000000;
    test_tag[44] = "vec4_zero_p3";
    test_rst[45] = 1'b0;
    test_in_valid[45] = 1'b1;
    test_a_data[45] = 8'hf7;
    test_b_data[45] = 8'h00;
    test_last_in[45] = 1'b0;
    expected_result_valid[45] = 1'b0;
    expected_result[45] = 32'h00000000;
    test_tag[45] = "vec4_zero_p4";
    test_rst[46] = 1'b0;
    test_in_valid[46] = 1'b1;
    test_a_data[46] = 8'h00;
    test_b_data[46] = 8'h01;
    test_last_in[46] = 1'b0;
    expected_result_valid[46] = 1'b0;
    expected_result[46] = 32'h00000000;
    test_tag[46] = "vec4_zero_p5";
    test_rst[47] = 1'b0;
    test_in_valid[47] = 1'b1;
    test_a_data[47] = 8'h03;
    test_b_data[47] = 8'h00;
    test_last_in[47] = 1'b0;
    expected_result_valid[47] = 1'b0;
    expected_result[47] = 32'h00000000;
    test_tag[47] = "vec4_zero_p6";
    test_rst[48] = 1'b0;
    test_in_valid[48] = 1'b1;
    test_a_data[48] = 8'h00;
    test_b_data[48] = 8'h00;
    test_last_in[48] = 1'b1;
    expected_result_valid[48] = 1'b0;
    expected_result[48] = 32'h00000000;
    test_tag[48] = "vec4_zero_p7";
    test_rst[49] = 1'b0;
    test_in_valid[49] = 1'b1;
    test_a_data[49] = 8'h05;
    test_b_data[49] = 8'hf7;
    test_last_in[49] = 1'b0;
    expected_result_valid[49] = 1'b0;
    expected_result[49] = 32'h00000000;
    test_tag[49] = "vec5_back_to_back_p0";
    test_rst[50] = 1'b0;
    test_in_valid[50] = 1'b1;
    test_a_data[50] = 8'hfc;
    test_b_data[50] = 8'hf8;
    test_last_in[50] = 1'b0;
    expected_result_valid[50] = 1'b1;
    expected_result[50] = 32'h00000000;
    test_tag[50] = "vec5_back_to_back_p1";
    test_rst[51] = 1'b0;
    test_in_valid[51] = 1'b1;
    test_a_data[51] = 8'h03;
    test_b_data[51] = 8'hf9;
    test_last_in[51] = 1'b0;
    expected_result_valid[51] = 1'b0;
    expected_result[51] = 32'h00000000;
    test_tag[51] = "vec5_back_to_back_p2";
    test_rst[52] = 1'b0;
    test_in_valid[52] = 1'b1;
    test_a_data[52] = 8'hfe;
    test_b_data[52] = 8'hfa;
    test_last_in[52] = 1'b0;
    expected_result_valid[52] = 1'b0;
    expected_result[52] = 32'h00000000;
    test_tag[52] = "vec5_back_to_back_p3";
    test_rst[53] = 1'b0;
    test_in_valid[53] = 1'b1;
    test_a_data[53] = 8'h01;
    test_b_data[53] = 8'hfb;
    test_last_in[53] = 1'b0;
    expected_result_valid[53] = 1'b0;
    expected_result[53] = 32'h00000000;
    test_tag[53] = "vec5_back_to_back_p4";
    test_rst[54] = 1'b0;
    test_in_valid[54] = 1'b1;
    test_a_data[54] = 8'h00;
    test_b_data[54] = 8'hfc;
    test_last_in[54] = 1'b0;
    expected_result_valid[54] = 1'b0;
    expected_result[54] = 32'h00000000;
    test_tag[54] = "vec5_back_to_back_p5";
    test_rst[55] = 1'b0;
    test_in_valid[55] = 1'b1;
    test_a_data[55] = 8'hff;
    test_b_data[55] = 8'hfd;
    test_last_in[55] = 1'b0;
    expected_result_valid[55] = 1'b0;
    expected_result[55] = 32'h00000000;
    test_tag[55] = "vec5_back_to_back_p6";
    test_rst[56] = 1'b0;
    test_in_valid[56] = 1'b1;
    test_a_data[56] = 8'h02;
    test_b_data[56] = 8'hfe;
    test_last_in[56] = 1'b1;
    expected_result_valid[56] = 1'b0;
    expected_result[56] = 32'h00000000;
    test_tag[56] = "vec5_back_to_back_p7";
    test_rst[57] = 1'b0;
    test_in_valid[57] = 1'b0;
    test_a_data[57] = 8'h00;
    test_b_data[57] = 8'h00;
    test_last_in[57] = 1'b0;
    expected_result_valid[57] = 1'b0;
    expected_result[57] = 32'h00000000;
    test_tag[57] = "drain_idle0";
    test_rst[58] = 1'b0;
    test_in_valid[58] = 1'b0;
    test_a_data[58] = 8'h00;
    test_b_data[58] = 8'h00;
    test_last_in[58] = 1'b0;
    expected_result_valid[58] = 1'b1;
    expected_result[58] = 32'hffffffe4;
    test_tag[58] = "drain_idle1";
    test_rst[59] = 1'b0;
    test_in_valid[59] = 1'b0;
    test_a_data[59] = 8'h00;
    test_b_data[59] = 8'h00;
    test_last_in[59] = 1'b1;
    expected_result_valid[59] = 1'b0;
    expected_result[59] = 32'h00000000;
    test_tag[59] = "drain_idle2";
end

    task apply_cycle;
        input integer idx;
        begin
            rst = test_rst[idx];
            in_valid = test_in_valid[idx];
            a_data = test_a_data[idx];
            b_data = test_b_data[idx];
            last_in = test_last_in[idx];

            @(posedge clk);
            #1;

            cycle_count = cycle_count + 1;
            tests_run = tests_run + 1;

            if (result_valid !== expected_result_valid[idx]) begin
                $display("ERROR [cycle %0d][%0s]: result_valid mismatch. Expected %b, got %b (rst=%b in_valid=%b a=0x%02h b=0x%02h last_in=%b)",
                         cycle_count, test_tag[idx], expected_result_valid[idx], result_valid,
                         test_rst[idx], test_in_valid[idx], test_a_data[idx], test_b_data[idx], test_last_in[idx]);
                errors = errors + 1;
            end

            if (result !== expected_result[idx]) begin
                $display("ERROR [cycle %0d][%0s]: result mismatch. Expected 0x%08h, got 0x%08h (rst=%b in_valid=%b a=0x%02h b=0x%02h last_in=%b)",
                         cycle_count, test_tag[idx], expected_result[idx], result,
                         test_rst[idx], test_in_valid[idx], test_a_data[idx], test_b_data[idx], test_last_in[idx]);
                errors = errors + 1;
            end
        end
    endtask

    initial begin
        rst = 1'b0;
        in_valid = 1'b0;
        a_data = 8'h00;
        b_data = 8'h00;
        last_in = 1'b0;

        $display("===========================================");
        $display(" Streaming 8-Element Dot Product Testbench");
        $display("===========================================");

        for (i = 0; i < NUM_TESTS; i = i + 1) begin
            apply_cycle(i);
        end

        $display("");
        $display("===========================================");
        $display("  Tests Run: %0d", tests_run);
        $display("===========================================");

        if (errors == 0) begin
            $display("TEST_RESULT: PASS");
        end else begin
            $display("TEST_RESULT: FAIL (%0d errors)", errors);
        end

        $finish;
    end
endmodule
