diff --git a/fp_mult_top.sv b/fp_mult_top.sv index 8f3fe96..356d2fb 100644 --- a/fp_mult_top.sv +++ b/fp_mult_top.sv @@ -11,7 +11,7 @@ module fp_mult_top ( logic [31:0] a1, b1; // Floating-Point numbers logic [2:0] rnd1; // Rounding signal - logic [31:0] z1; // a ± b + logic [31:0] z1; // a * b logic [7:0] status1; // Status Flags fp_mult multiplier(a1,b1,rnd1,z1,status1,clk,rst); diff --git a/fpu_mult.mpf b/fpu_mult.mpf index 371bd6e..cbe4dce 100644 --- a/fpu_mult.mpf +++ b/fpu_mult.mpf @@ -2304,25 +2304,27 @@ suppress = 8780 ;an explanation can be had by running: verror 8780 Project_Version = 6 Project_DefaultLib = work Project_SortMethod = unused -Project_Files_Count = 9 -Project_File_0 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/fp_mult_top.sv -Project_File_P_0 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder {Top Level} last_compile 1749470139 cover_fsm 0 cover_branch 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 0 cover_expr 0 dont_compile 0 cover_stmt 0 -Project_File_1 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/normalize_mult.sv -Project_File_P_1 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749838823 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 2 dont_compile 0 cover_expr 0 cover_stmt 0 -Project_File_2 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_modes.sv -Project_File_P_2 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder src last_compile 1749985365 cover_fsm 0 cover_branch 0 vlog_noload 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 8 cover_expr 0 dont_compile 0 cover_stmt 0 +Project_Files_Count = 10 +Project_File_0 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/normalize_mult.sv +Project_File_P_0 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749838823 cover_fsm 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 2 dont_compile 0 cover_expr 0 cover_stmt 0 +Project_File_1 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/fp_mult_top.sv +Project_File_P_1 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder {Top Level} last_compile 1749997793 cover_fsm 0 cover_branch 0 vlog_noload 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 0 dont_compile 0 cover_expr 0 cover_stmt 0 +Project_File_2 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/round_mult_tb.sv +Project_File_P_2 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder sim last_compile 1749484994 cover_fsm 0 cover_branch 0 vlog_noload 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 6 cover_expr 0 dont_compile 0 cover_stmt 0 Project_File_3 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/fp_mult.sv -Project_File_P_3 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749991254 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 3 dont_compile 0 cover_expr 0 cover_stmt 0 -Project_File_4 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/round_mult_tb.sv -Project_File_P_4 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749484994 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 6 cover_expr 0 dont_compile 0 cover_stmt 0 -Project_File_5 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/exception_mult.sv -Project_File_P_5 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749989714 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 7 dont_compile 0 cover_expr 0 cover_stmt 0 +Project_File_P_3 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749998026 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 3 cover_expr 0 dont_compile 0 cover_stmt 0 +Project_File_4 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_modes.sv +Project_File_P_4 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749985365 cover_fsm 0 cover_branch 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 8 cover_expr 0 dont_compile 0 cover_stmt 0 +Project_File_5 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/fp_mult_top_tb.sv +Project_File_P_5 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder sim last_compile 1750007782 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 9 dont_compile 0 cover_expr 0 cover_stmt 0 Project_File_6 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/normalize_mult_tb.sv -Project_File_P_6 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder sim last_compile 1749840708 cover_fsm 0 cover_branch 0 vlog_noload 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 5 dont_compile 0 cover_expr 0 cover_stmt 0 -Project_File_7 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_mult.sv -Project_File_P_7 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749991129 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 1 cover_expr 0 dont_compile 0 cover_stmt 0 +Project_File_P_6 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder sim last_compile 1749840708 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 5 dont_compile 0 cover_expr 0 cover_stmt 0 +Project_File_7 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/exception_mult.sv +Project_File_P_7 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_branch 0 vlog_noload 0 folder src last_compile 1750007927 cover_fsm 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 7 cover_expr 0 dont_compile 0 cover_stmt 0 Project_File_8 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/fp_mult_tb.sv -Project_File_P_8 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749991928 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 4 dont_compile 0 cover_expr 0 cover_stmt 0 +Project_File_P_8 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder sim last_compile 1750007807 cover_fsm 0 cover_branch 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 4 cover_expr 0 dont_compile 0 cover_stmt 0 +Project_File_9 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_mult.sv +Project_File_P_9 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749991129 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 1 cover_expr 0 dont_compile 0 cover_stmt 0 Project_Sim_Count = 0 Project_Folder_Count = 2 Project_Folder_0 = src diff --git a/sim/fp_mult_tb.sv b/sim/fp_mult_tb.sv old mode 100644 new mode 100755 index 8d35bc6..b52ec0c --- a/sim/fp_mult_tb.sv +++ b/sim/fp_mult_tb.sv @@ -1,3 +1,4 @@ + // sim/fp_mult_tb.sv `timescale 1ns/1ps @@ -6,18 +7,8 @@ module fp_mult_tb; logic [31:0] a, b, z; logic [2:0] rnd; logic [7:0] status; - logic clk = 0, rst = 0; - /* - // DEBUG signals - logic sign_res_; - logic [9:0] exp_sum_; - logic [47:0] mant_prod_; - logic [22:0] mant_norm_; - logic [9:0] exp_norm_; - logic guard_, sticky_; - logic [24:0] mant_post_rnd_; - logic [9:0] exp_post_rnd_; - */ + logic clk = 0, rst = 1; + // DUT fp_mult dut ( .a(a), @@ -27,21 +18,10 @@ module fp_mult_tb; .status(status), .clk(clk), .rst(rst) -/* - // DEBUG signals - .sign_res_(sign_res_), - .exp_sum_(exp_sum_), - .mant_prod_(mant_prod_), - .mant_norm_(mant_norm_), - .exp_norm_(exp_norm_), - .guard_(guard_), - .sticky_(sticky_), - .mant_post_rnd_(mant_post_rnd_), - .exp_post_rnd_(exp_post_rnd_) -*/ ); // Clock generation + always #1 rst = 1; always #5 clk = ~clk; typedef struct { @@ -50,59 +30,58 @@ module fp_mult_tb; logic [31:0] expected; string desc; } test_vector_t; + int i =0, j=0; - test_vector_t tests [14]; + test_vector_t tests [20]; initial begin $display("Starting fp_mult test...\n"); - // Normal multiplication cases - tests[0] = '{32'h3f800000, 32'h40000000, 32'h40000000, "1.0 * 2.0 = 2.0"}; - tests[1] = '{32'h40400000, 32'h40400000, 32'h41100000, "3.0 * 3.0 = 9.0"}; - tests[2] = '{32'hc0400000, 32'h40400000, 32'hc1100000, "-3.0 * 3.0 = 9.0"}; - tests[3] = '{32'hbf800000, 32'h40000000, 32'hc0000000, "-1.0 * 2.0 = -2.0"}; - tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "0.5 * 0.5 = 0.25"}; - tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * 0.0 = 0.0"}; - tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "42.0 * -7.0 = -294.0"}; - tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "12.34 * -0.0001 = -0.001234"}; + // Test vectors + tests[0] = '{32'h3f800000, 32'h40000000, 32'h40000000, "+1.0 * +2.0 = +2.0"}; + tests[1] = '{32'h40400000, 32'h40400000, 32'h41100000, "+3.0 * +3.0 = +9.0"}; + tests[2] = '{32'hc0400000, 32'h40400000, 32'hc1100000, "-3.0 * +3.0 = -9.0"}; + tests[3] = '{32'hbf800000, 32'h40000000, 32'hc0000000, "-1.0 * +2.0 = -2.0"}; + tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "+0.5 * +0.5 = +0.25"}; + tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * +0.0 = +0.0"}; + tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "+42.0 * -7.0 = -294.0"}; + tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "+12.34 * -0.0001 = -0.001234"}; - // Corner cases (some may fail if not handled yet) - tests[8] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"}; - tests[9] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"}; - tests[10] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"}; - tests[11] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"}; - tests[12] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf - nan"}; - tests[13] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf - nan"}; + tests[8] = '{32'h00000000, 32'h00000000, 32'h00000000, "0.0 * 0.0 = 0.0"}; + tests[9] = '{32'h80000000, 32'h80000000, 32'h00000000, "-0.0 * -0.0 = 0.0"}; + tests[10] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"}; + tests[11] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"}; + tests[12] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"}; + tests[13] = '{32'hff800000, 32'h3f800000, 32'hff800000, "-inf * 1.0 = -inf"}; + tests[14] = '{32'h7f800000, 32'hbf800000, 32'hff800000, "inf * -1.0 = -inf"}; + tests[15] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"}; + tests[16] = '{32'hff800000, 32'hff800000, 32'h7f800000, "-inf * -inf = +inf"}; + tests[17] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf"}; + tests[18] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf"}; + tests[19] = '{32'h00000000, 32'hff800000, 32'hff800000, "0.0 * -inf = -inf"}; + end + logic [31:0] z_pipe [2:0]; - rnd = 3'b000; // default round to nearest - rst = 1; #10; - rst = 0; #10; + always_ff @(negedge clk) begin + z_pipe[2] <= z_pipe[1]; + z_pipe[1] <= z_pipe[0]; + z_pipe[0] <= z; - for (int i = 0; i < 14; i++) begin - a = tests[i].a; - b = tests[i].b; - #20; - $display("[%0d] %s", i+1, tests[i].desc); - /* - // DEBUG prints - $display("fp_mult: sign bit = %h", sign_res_); - $display("fp_mult: exp (pre norm) = %h", exp_sum_); - $display("fp_mult: mant (pre norm) = %h", mant_prod_); - $display("fp_mult: exp (norm) = %h", exp_norm_); - $display("fp_mult: mant (norm) = %h", mant_norm_); - $display("fp_mult: guard,sticky = %h,%h", guard_,sticky_); - $display("fp_mult: exp (post rnd) = %h", exp_post_rnd_); - $display("fp_mult: mant (post rnd) = %h", mant_post_rnd_); - */ - $display(" A=%h B=%h => Z=%h (expected %h) %s\n", - a, b, z, tests[i].expected, - (z === tests[i].expected) ? "PASS" : "FAIL"); + if (i >= 5) begin + j = i - 5; + $display("[%0d] %s", j+1, tests[j].desc); + $display(" A=%h B=%h => Z=%h (expected %h) %s\n", + tests[j].a, tests[j].b, z_pipe[0], tests[j].expected, + (z_pipe[0] === tests[j].expected) ? "PASS" : "FAIL"); end - $display("\nFinished fp_mult test."); - $stop; + a <= tests[i].a; + b <= tests[i].b; + i <= i + 1; + + if (i == 19 + 5) $stop; end -endmodule +endmodule diff --git a/sim/fp_mult_top_tb.sv b/sim/fp_mult_top_tb.sv new file mode 100755 index 0000000..0862adf --- /dev/null +++ b/sim/fp_mult_top_tb.sv @@ -0,0 +1,89 @@ +// sim/fp_mult_top_tb.sv +`timescale 1ns/1ps + +module fp_mult_top_tb; + + logic [31:0] a, b, z; + logic [2:0] rnd; + logic [7:0] status; + logic clk = 0, rst = 1; + + // DUT + fp_mult_top dut ( + .a(a), + .b(b), + .rnd(rnd), + .z(z), + .status(status), + .clk(clk), + .rst(rst) + ); + + // Clock generation + always #1 rst = 1; + always #5 clk = ~clk; + + typedef struct { + logic [31:0] a; + logic [31:0] b; + logic [31:0] expected; + string desc; + } test_vector_t; + int i =0, j=0; + + // Test vectors + test_vector_t tests [20]; + + initial begin + + $display("Starting fp_mult test...\n"); + + // Test cases + tests[0] = '{32'h3f800000, 32'h40000000, 32'h40000000, "+1.0 * +2.0 = +2.0"}; + tests[1] = '{32'h40400000, 32'h40400000, 32'h41100000, "+3.0 * +3.0 = +9.0"}; + tests[2] = '{32'hc0400000, 32'h40400000, 32'hc1100000, "-3.0 * +3.0 = -9.0"}; + tests[3] = '{32'hbf800000, 32'h40000000, 32'hc0000000, "-1.0 * +2.0 = -2.0"}; + tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "+0.5 * +0.5 = +0.25"}; + tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * +0.0 = +0.0"}; + tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "+42.0 * -7.0 = -294.0"}; + tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "+12.34 * -0.0001 = -0.001234"}; + + tests[8] = '{32'h00000000, 32'h00000000, 32'h00000000, "0.0 * 0.0 = 0.0"}; + tests[9] = '{32'h80000000, 32'h80000000, 32'h00000000, "-0.0 * -0.0 = 0.0"}; + tests[10] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"}; + tests[11] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"}; + tests[12] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"}; + tests[13] = '{32'hff800000, 32'h3f800000, 32'hff800000, "-inf * 1.0 = -inf"}; + tests[14] = '{32'h7f800000, 32'hbf800000, 32'hff800000, "inf * -1.0 = -inf"}; + tests[15] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"}; + tests[16] = '{32'hff800000, 32'hff800000, 32'h7f800000, "-inf * -inf = +inf"}; + tests[17] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf"}; + tests[18] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf"}; + tests[19] = '{32'h00000000, 32'hff800000, 32'hff800000, "0.0 * -inf = -inf"}; + + end + + logic [31:0] z_pipe [2:0]; + + always_ff @(negedge clk) begin + z_pipe[2] <= z_pipe[1]; + z_pipe[1] <= z_pipe[0]; + z_pipe[0] <= z; + + if (i >= 7) begin + j = i - 7; + $display("[%0d] %s", j+1, tests[j].desc); + $display(" A=%h B=%h => Z=%h (expected %h) %s\n", + tests[j].a, tests[j].b, z_pipe[0], tests[j].expected, + (z_pipe[0] == tests[j].expected) ? "PASS" : "FAIL"); + end + + a <= tests[i].a; + b <= tests[i].b; + i <= i + 1; + + if (i == 19 + 7) $stop; + end + + +endmodule diff --git a/src/exception_mult.sv b/src/exception_mult.sv index 817cbf4..94a48b5 100644 --- a/src/exception_mult.sv +++ b/src/exception_mult.sv @@ -72,7 +72,7 @@ module exception_mult ( {ZERO, INF}, {INF, ZERO}: begin - z = {1'b0, z_num(INF)}; + z = {sign, z_num(INF)}; nan_f = 1; end diff --git a/src/fp_mult.sv b/src/fp_mult.sv index 1a478e1..9e18d72 100644 --- a/src/fp_mult.sv +++ b/src/fp_mult.sv @@ -6,125 +6,151 @@ module fp_mult ( input logic [31:0] b, // input operand B input logic [2:0] round, // rounding mode output logic [31:0] z, // result - output logic [7:0] status, // status flags (placeholder) + output logic [7:0] status, // status flags input logic clk, input logic rst - /* - // debug outputs - output logic sign_res_, - output logic [9:0] exp_sum_, - output logic [47:0] mant_prod_, - output logic [22:0] mant_norm_, - output logic [9:0] exp_norm_, - output logic guard_, sticky_, - output logic [24:0] mant_post_rnd_, - output logic [9:0] exp_post_rnd_ - */ ); - // === STEP 0: Parse inputs - logic sign_a, sign_b; - logic [7:0] exp_a, exp_b; - logic [23:0] mant_a, mant_b; // includes hidden bit + // Stage 0: Decode inputs + logic sign; + logic [7:0] exp_a, exp_b; + logic [23:0] mant_a, mant_b; + logic [47:0] s0_mantissa; + logic [9:0] s0_exponent; always_comb begin - sign_a = a[31]; - sign_b = b[31]; - exp_a = a[30:23]; - exp_b = b[30:23]; - mant_a = (exp_a == 8'd0) ? {1'b0, a[22:0]} : {1'b1, a[22:0]}; - mant_b = (exp_b == 8'd0) ? {1'b0, b[22:0]} : {1'b1, b[22:0]}; - // ^ Add hiden leading '1' on normalized numbers - // This will lead to always 24-bits mantissa internal representation - // for multiplication + sign = a[31] ^ b[31]; + exp_a = a[30:23]; + exp_b = b[30:23]; + s0_exponent = exp_a + exp_b - 127; + + mant_a = (exp_a == 0) ? {1'b0, a[22:0]} : {1'b1, a[22:0]}; + mant_b = (exp_b == 0) ? {1'b0, b[22:0]} : {1'b1, b[22:0]}; + s0_mantissa = mant_a * mant_b; end - // === STEP 1: Floating point number sign calculation - logic sign_res; - assign sign_res = sign_a ^ sign_b; - //assign sign_res_ = sign_res; // DEBUG + // === Stage 1: Normalize === + logic [47:0] s1_mant_in; + logic [9:0] s1_exp_in; + logic [22:0] s1_mant_out; + logic [9:0] s1_exp_out; + logic s1_guard_out, s1_sticky_out; + logic [31:0] s1_a, s1_b; + logic s1_sign; - // === STEP 2,3. Exponent addition, Exponent subtraction of bias - logic [9:0] exp_sum; - always_comb begin - exp_sum = exp_a + exp_b - 127; // apply bias - //exp_sum_ = exp_sum; // DEBUG - end - - // === STEP 4: Mantissa multiplication (including leading ones) - logic [47:0] mant_prod; - always_comb begin - mant_prod = mant_a * mant_b; - //mant_prod_ = mant_prod; // DEBUG - end - - // === STEP 5: Truncation and normalization - logic [22:0] mant_norm; - logic [9:0] exp_norm; - logic guard, sticky; - - normalize_mult norm_inst ( - .mantissa_in(mant_prod), - .exponent_in(exp_sum), - .mantissa_out(mant_norm), - .exponent_out(exp_norm), - .guard_bit(guard), - .sticky_bit(sticky) + normalize_mult normalize_inst ( + .mantissa_in(s1_mant_in), + .exponent_in(s1_exp_in), + .mantissa_out(s1_mant_out), + .exponent_out(s1_exp_out), + .guard_bit(s1_guard_out), + .sticky_bit(s1_sticky_out) ); - //assign mant_norm_ = mant_norm; // DEBUG - //assign exp_norm_ = exp_norm; // DEBUG - //assign guard_ = guard; // DEBUG - //assign sticky_ = sticky; // DEBUG - // === STEP 6: Pipeline stage - // Ehhh... We dont do that here... + always_ff @(posedge clk or negedge rst) begin + if (!rst) begin + s1_mant_in <= 0; + s1_exp_in <= 0; + s1_a <= 0; + s1_b <= 0; + s1_sign <= 0; + end else begin + s1_mant_in <= s0_mantissa; + s1_exp_in <= s0_exponent; + s1_a <= a; + s1_b <= b; + s1_sign <= sign; + end + end - // === STEP 7: Rounding - logic [24:0] mant_post_rnd; - logic [9:0] exp_post_rnd; - logic inexact; + // === Stage 2: Round === + logic [22:0] s2_mant_in; + logic [9:0] s2_exp_in; + logic s2_guard_in, s2_sticky_in; + logic [31:0] s2_a, s2_b; + logic s2_sign; + logic [24:0] s2_mant_out; + logic [9:0] s2_exp_out; + logic s2_inexact; round_mult round_inst ( - .mantissa_in(mant_norm), - .exponent_in(exp_norm), - .sign_in(sign_res), - .guard_bit(guard), - .sticky_bit(sticky), + .mantissa_in(s2_mant_in), + .exponent_in(s2_exp_in), + .sign_in(s2_sign), + .guard_bit(s2_guard_in), + .sticky_bit(s2_sticky_in), .round(round), - .mantissa_out(mant_post_rnd), - .exponent_out(exp_post_rnd), - .inexact(inexact) + .mantissa_out(s2_mant_out), + .exponent_out(s2_exp_out), + .inexact(s2_inexact) ); - //assign mant_post_rnd_ = mant_post_rnd; // DEBUG - //assign exp_post_rnd_ = exp_post_rnd; // DEBUG - // === STEP 8: Exception handling - // overflow / underflow: - logic [31:0] z_calc; - logic ovf, unf; - - assign z_calc = {sign_res, exp_post_rnd[7:0], mant_post_rnd[22:0]}; - always_comb begin - ovf = (exp_post_rnd > 10'd254); // MAX normal exponent - unf = (exp_post_rnd < 10'd1); // MIN normal exponent + always_ff @(posedge clk or negedge rst) begin + if (!rst) begin + s2_mant_in <= 0; + s2_exp_in <= 0; + s2_guard_in <= 0; + s2_sticky_in <= 0; + s2_a <= 0; + s2_b <= 0; + s2_sign <= 0; + end else begin + s2_mant_in <= s1_mant_out; + s2_exp_in <= s1_exp_out; + s2_guard_in <= s1_guard_out; + s2_sticky_in <= s1_sticky_out; + s2_a <= s1_a; + s2_b <= s1_b; + s2_sign <= s1_sign; + end end - exception_mult exc_inst ( - .a(a), - .b(b), - .z_calc(z_calc), - .ovf(ovf), - .unf(unf), - .inexact(inexact), + // === Stage 3: Exception Handling === + logic [31:0] s3_a, s3_b; + logic [31:0] s3_z_calc_in; + logic s3_ovf_in, s3_unf_in; + logic s3_inexact; + logic [31:0] s3_z_out; + logic [7:0] s3_status_out; + + exception_mult exception_handler ( + .a(s3_a), + .b(s3_b), + .z_calc(s3_z_calc_in), + .ovf(s3_ovf_in), + .unf(s3_unf_in), + .inexact(s3_inexact), .round(round), - .z(z), - .zero_f(status[0]), - .inf_f(status[1]), - .nan_f(status[2]), - .tiny_f(status[3]), - .huge_f(status[4]), - .inexact_f(status[5]) + .z(s3_z_out), + .zero_f(s3_status_out[0]), + .inf_f(s3_status_out[1]), + .nan_f(s3_status_out[2]), + .tiny_f(s3_status_out[3]), + .huge_f(s3_status_out[4]), + .inexact_f(s3_status_out[5]) ); - + + always_ff @(posedge clk or negedge rst) begin + if (!rst) begin + s3_a <= 0; + s3_b <= 0; + s3_z_calc_in <= 0; + s3_ovf_in <= 0; + s3_unf_in <= 0; + s3_inexact <= 0; + z <= 0; + status <= 0; + end else begin + s3_a <= s2_a; + s3_b <= s2_b; + s3_z_calc_in <= {s2_sign, s2_exp_out[7:0], s2_mant_out[22:0]}; + s3_ovf_in <= (s2_exp_out > 8'd254); + s3_unf_in <= (s2_exp_out < 8'd1); + s3_inexact <= s2_inexact; + z <= s3_z_out; + status <= s3_status_out; + end + end + endmodule