+`default_nettype none
+
 module __MUL27X27(A, B, Y);
 
 parameter A_SIGNED = 1;
 
 (* abc9_box *)
 module MISTRAL_MUL27X27(input [26:0] A, input [26:0] B, output [53:0] Y);
 
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
 // TODO: Cyclone 10 GX timings; the below are for Cyclone V
 specify
     (A *> Y) = 3732;
     (B *> Y) = 3928;
 endspecify
 
-assign Y = $signed(A) * $signed(B);
+wire [53:0] A_, B_;
+
+if (A_SIGNED)
+    assign A_ = $signed(A);
+else
+    assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+    assign B_ = $signed(B);
+else
+    assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
 
 endmodule
 
 (* abc9_box *)
 module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y);
 
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
 // TODO: Cyclone 10 GX timings; the below are for Cyclone V
 specify
     (A *> Y) = 3180;
     (B *> Y) = 3982;
 endspecify
 
-assign Y = $signed(A) * $signed(B);
+wire [35:0] A_, B_;
+
+if (A_SIGNED)
+    assign A_ = $signed(A);
+else
+    assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+    assign B_ = $signed(B);
+else
+    assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
 
 endmodule
 
 (* abc9_box *)
 module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y);
 
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
 // TODO: Cyclone 10 GX timings; the below are for Cyclone V
 specify
     (A *> Y) = 2818;
     (B *> Y) = 3051;
 endspecify
 
-assign Y = $signed(A) * $signed(B);
+wire [17:0] A_, B_;
+
+if (A_SIGNED)
+    assign A_ = $signed(A);
+else
+    assign A_ = $unsigned(A);
+
+if (B_SIGNED)
+    assign B_ = $signed(B);
+else
+    assign B_ = $unsigned(B);
+
+assign Y = A_ * B_;
 
 endmodule
 
 module cyclonev_mac(ax, ay, resulta);
 
 parameter ax_width = 9;
+parameter signed_max = "true";
 parameter ay_scan_in_width = 9;
+parameter signed_may = "true";
 parameter result_a_width = 18;
 parameter operation_mode = "M9x9";
 
 module cyclone10gx_mac(ax, ay, resulta);
 
 parameter ax_width = 18;
+parameter signed_max = "true";
 parameter ay_scan_in_width = 18;
+parameter signed_may = "true";
 parameter result_a_width = 36;
 parameter operation_mode = "M18X18_FULL";
 
 
 
 module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y);
 
-`MAC #(.ax_width(27), .ay_scan_in_width(27), .result_a_width(54), .operation_mode("M27x27")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y));
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+    .ax_width(27),
+    .signed_max(A_SIGNED ? "true" : "false"),
+    .ay_scan_in_width(27),
+    .signed_may(B_SIGNED ? "true" : "false"),
+    .result_a_width(54),
+    .operation_mode("M27x27")
+) _TECHMAP_REPLACE_ (
+    .ax(A),
+    .ay(B),
+    .resulta(Y)
+);
 
 endmodule
 
 
 module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y);
 
-`MAC #(.ax_width(18), .ay_scan_in_width(18), .result_a_width(36), .operation_mode("M18x18_FULL")) _TECHMAP_REPLACE_ (.ax(B), .ay(A), .resulta(Y));
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+    .ax_width(18),
+    .signed_max(A_SIGNED ? "true" : "false"),
+    .ay_scan_in_width(18),
+    .signed_may(B_SIGNED ? "true" : "false"),
+    .result_a_width(36),
+    .operation_mode("M18x18_FULL")
+) _TECHMAP_REPLACE_ (
+    .ax(A),
+    .ay(B),
+    .resulta(Y)
+);
 
 endmodule
 
 
 module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y);
 
-`MAC #(.ax_width(9), .ay_scan_in_width(9), .result_a_width(18), .operation_mode("M9x9")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y));
+parameter A_SIGNED = 1;
+parameter B_SIGNED = 1;
+
+`MAC #(
+    .ax_width(9),
+    .signed_max(A_SIGNED ? "true" : "false"),
+    .ay_scan_in_width(9),
+    .signed_may(B_SIGNED ? "true" : "false"),
+    .result_a_width(18),
+    .operation_mode("M9x9")
+) _TECHMAP_REPLACE_ (
+    .ax(A),
+    .ay(B),
+    .resulta(Y)
+);
 
 endmodule
 
                                run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
                        } else if (!nodsp) {
                                // Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
-                               run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=19  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL27X27");
+                               run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=19 -D DSP_NAME=__MUL27X27");
                                run("chtype -set $mul t:$__soft_mul");
                                if (family_opt == "cyclonev") {
-                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL18X18");
+                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10 -D DSP_NAME=__MUL18X18");
                                        run("chtype -set $mul t:$__soft_mul");
-                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL9X9");
+                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL9X9");
                                        run("chtype -set $mul t:$__soft_mul");
                                } else if (family_opt == "cyclone10gx") {
-                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL18X18");
+                                       run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
                                        run("chtype -set $mul t:$__soft_mul");
                                }
                        }
 
 module top
+#(parameter X_WIDTH=6, Y_WIDTH=6, A_WIDTH=12)
 (
-    input [5:0] x,
-    input [5:0] y,
+    input [X_WIDTH-1:0] x,
+    input [Y_WIDTH-1:0] y,
 
-    output [11:0] A,
+    output [A_WIDTH-1:0] A,
 );
     assign A =  x * y;
 endmodule
 
 read_verilog ../common/mul.v
+chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
 hierarchy -top top
 proc
 equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd top # Constrain all select calls below inside the top module
 
-stat
-
 select -assert-count 1 t:MISTRAL_MUL9X9
 select -assert-none t:MISTRAL_MUL9X9 %% t:* %D
 
+# Cyclone 10 GX does not have 9x9 multipliers.
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:MISTRAL_MUL18X18
+select -assert-none t:MISTRAL_MUL18X18 %% t:* %D
+
 design -reset
 read_verilog ../common/mul.v
+chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34
 hierarchy -top top
 proc
 equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # equivalency check
 design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
 cd top # Constrain all select calls below inside the top module
 
-# Cyclone 10 GX does not have 9x9 multipliers, so we use 18x18.
 select -assert-count 1 t:MISTRAL_MUL18X18
 select -assert-none t:MISTRAL_MUL18X18 %% t:* %D
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:MISTRAL_MUL27X27
+select -assert-none t:MISTRAL_MUL27X27 %% t:* %D
+
+design -reset
+read_verilog ../common/mul.v
+chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52
+hierarchy -top top
+proc
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:MISTRAL_MUL27X27
+select -assert-none t:MISTRAL_MUL27X27 %% t:* %D