`timescale 1ns/1ps

module round_mult_tb;

    logic [22:0] mantissa_in;
    logic [7:0]  exponent_in;
    logic guard_bit, round_bit, sticky_bit;
    logic [22:0] mantissa_out;
    logic [7:0]  exponent_out;

    round_mult dut (
        .mantissa_in(mantissa_in),
        .exponent_in(exponent_in),
        .guard_bit(guard_bit),
        .round_bit(round_bit),
        .sticky_bit(sticky_bit),
        .mantissa_out(mantissa_out),
        .exponent_out(exponent_out)
    );

    initial begin
        integer i;

        logic [22:0] mant_in     [10];
        logic [7:0]  exp_in      [10];
        logic        g_bit       [10];
        logic        r_bit       [10];
        logic        s_bit       [10];
        logic [22:0] expected_m  [10];
        logic [7:0]  expected_e  [10];
        string       notes       [10];

        $display("Starting round_mult test...\n");

        mant_in[0] = 23'h400000; exp_in[0] = 8'd100; g_bit[0] = 1; r_bit[0] = 0; s_bit[0] = 0; expected_m[0] = 23'h400000; expected_e[0] = 8'd100; notes[0] = "Tie: do not round (even)";
        mant_in[1] = 23'h400001; exp_in[1] = 8'd100; g_bit[1] = 1; r_bit[1] = 0; s_bit[1] = 0; expected_m[1] = 23'h400002; expected_e[1] = 8'd100; notes[1] = "Round up (tie ? odd LSB)";
        mant_in[2] = 23'h400000; exp_in[2] = 8'd100; g_bit[2] = 1; r_bit[2] = 1; s_bit[2] = 0; expected_m[2] = 23'h400001; expected_e[2] = 8'd100; notes[2] = "Round up (guard + round)";
        mant_in[3] = 23'h400000; exp_in[3] = 8'd100; g_bit[3] = 1; r_bit[3] = 0; s_bit[3] = 1; expected_m[3] = 23'h400001; expected_e[3] = 8'd100; notes[3] = "Round up (guard + sticky)";
        mant_in[4] = 23'h7FFFFF; exp_in[4] = 8'd100; g_bit[4] = 1; r_bit[4] = 1; s_bit[4] = 1; expected_m[4] = 23'h400000; expected_e[4] = 8'd101; notes[4] = "Overflow during rounding";
        mant_in[5] = 23'h123456; exp_in[5] = 8'd90;  g_bit[5] = 0; r_bit[5] = 0; s_bit[5] = 0; expected_m[5] = 23'h123456; expected_e[5] = 8'd90;  notes[5] = "No rounding";
        mant_in[6] = 23'h123456; exp_in[6] = 8'd90;  g_bit[6] = 1; r_bit[6] = 0; s_bit[6] = 0; expected_m[6] = 23'h123456; expected_e[6] = 8'd90;  notes[6] = "Guard only, no round";
        mant_in[7] = 23'h123456; exp_in[7] = 8'd90;  g_bit[7] = 1; r_bit[7] = 1; s_bit[7] = 0; expected_m[7] = 23'h123457; expected_e[7] = 8'd90;  notes[7] = "Guard + Round";
        mant_in[8] = 23'h123456; exp_in[8] = 8'd90;  g_bit[8] = 1; r_bit[8] = 0; s_bit[8] = 1; expected_m[8] = 23'h123457; expected_e[8] = 8'd90;  notes[8] = "Guard + Sticky";
        mant_in[9] = 23'h123456; exp_in[9] = 8'd90;  g_bit[9] = 1; r_bit[9] = 1; s_bit[9] = 1; expected_m[9] = 23'h123457; expected_e[9] = 8'd90;  notes[9] = "Guard + Round + Sticky";

        for (i = 0; i < 10; i++) begin
            mantissa_in = mant_in[i];
            exponent_in = exp_in[i];
            guard_bit   = g_bit[i];
            round_bit   = r_bit[i];
            sticky_bit  = s_bit[i];

            #10;
            $display("[%0d] %s\n    IN:  mant=%h, exp=%0d, GRS=%b%b%b\n    OUT: mant=%h, exp=%0d (expected: mant=%h, exp=%0d)\n",
                     i+1, notes[i],
                     mantissa_in, exponent_in, guard_bit, round_bit, sticky_bit,
                     mantissa_out, exponent_out,
                     expected_m[i], expected_e[i]
            );
        end

        $display("Finished round_mult test.");
        $stop;
    end

endmodule

