From af7bdd598e017b0e8887d893c901ae93935d20b2 Mon Sep 17 00:00:00 2001
From: Pepijn de Vos <pepijndevos@gmail.com>
Date: Mon, 21 Oct 2019 12:00:27 +0200
Subject: use ADDSUB ALU mode to remove inverters

---
 techlibs/gowin/arith_map.v |  6 ++--
 techlibs/gowin/cells_sim.v | 78 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v
index af805b254..b6f9e8c38 100644
--- a/techlibs/gowin/arith_map.v
+++ b/techlibs/gowin/arith_map.v
@@ -40,15 +40,15 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
    \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
 
    wire [Y_WIDTH-1:0] 	AA = A_buf;
-   wire [Y_WIDTH-1:0] 	BB = BI ? ~B_buf : B_buf;
+   wire [Y_WIDTH-1:0] 	BB = B_buf;
    wire [Y_WIDTH-1:0] 	C = {CO, CI};
 
    genvar 		i;
    generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
-      ALU #(.ALU_MODE(0))
+      ALU #(.ALU_MODE(2)) // ADDSUB I3 ? add : sub
       alu(.I0(AA[i]),
 	  .I1(BB[i]),
-	  .I3(1'b0),
+	  .I3(~BI),
 	  .CIN(C[i]),
 	  .COUT(CO[i]),
 	  .SUM(Y[i])
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index de0cfa9f3..a392f5580 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -166,10 +166,80 @@ module GSR (input GSRI);
 	wire GSRO = GSRI;
 endmodule
 
-module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM);
-   parameter [3:0] ALU_MODE = 0; // default 0 = ADD
-   assign  {COUT, SUM} = CIN + I1 + I0;
-endmodule // alu
+module ALU (SUM, COUT, I0, I1, I3, CIN);
+
+input I0;
+input I1;
+input I3;
+input CIN;
+output SUM;
+output COUT;
+
+parameter ADD = 0;
+parameter SUB = 1;
+parameter ADDSUB = 2;
+parameter NE = 3;
+parameter GE = 4;
+parameter LE = 5;
+parameter CUP = 6;
+parameter CDN = 7;
+parameter CUPCDN = 8;
+parameter MULT = 9;
+
+parameter ALU_MODE = 0;
+
+reg S, C;
+
+assign SUM = S ^ CIN;
+assign COUT = S? CIN : C;
+
+always @(I0, I1, I3,CIN) begin
+	case (ALU_MODE)
+		ADD: begin
+			S = I0 ^ I1;
+			C = I0;
+		end
+		SUB: begin
+			S = I0 ^ ~I1;
+			C = I0;
+		end
+		ADDSUB: begin
+			S = I3? I0 ^ I1 : I0 ^ ~I1;
+			C = I0;
+		end
+		NE: begin
+			S = I0 ^ ~I1;
+			C = 1'b1;
+		end
+		GE: begin
+			S = I0 ^ ~I1;
+			C = I0;
+		end
+		LE: begin
+			S = ~I0 ^ I1;
+			C = I1;
+		end
+		CUP: begin
+			S = I0;
+			C = 1'b0;
+		end
+		CDN: begin
+			S = ~I0;
+			C = 1'b1;
+		end
+		CUPCDN: begin
+			S = I3? I0 : ~I0;
+			C = I0;
+		end
+		MULT: begin
+			S = I0 & I1;
+			C = I0 & I1;
+		end
+	endcase
+end
+
+endmodule
+
 
 module RAM16S4 (DO, DI, AD, WRE, CLK);
    parameter WIDTH  = 4;
-- 
cgit v1.2.3