aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc2
-rw-r--r--techlibs/gowin/.gitignore2
-rw-r--r--techlibs/gowin/Makefile.inc10
-rw-r--r--techlibs/gowin/arith_map.v6
-rw-r--r--techlibs/gowin/bram.txt10
-rwxr-xr-xtechlibs/gowin/brams_init.py8
-rw-r--r--techlibs/gowin/brams_map.v63
-rw-r--r--techlibs/gowin/cells_map.v102
-rw-r--r--techlibs/gowin/cells_sim.v349
-rw-r--r--techlibs/gowin/synth_gowin.cc42
-rw-r--r--techlibs/xilinx/cells_sim.v545
-rw-r--r--techlibs/xilinx/cells_xtra.py14
-rw-r--r--techlibs/xilinx/cells_xtra.v150
-rw-r--r--techlibs/xilinx/lut_map.v8
14 files changed, 1106 insertions, 205 deletions
diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc
index 21bbcaef4..014c68622 100644
--- a/techlibs/coolrunner2/synth_coolrunner2.cc
+++ b/techlibs/coolrunner2/synth_coolrunner2.cc
@@ -194,8 +194,6 @@ struct SynthCoolrunner2Pass : public ScriptPass
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
}
-
- log_pop();
}
} SynthCoolrunner2Pass;
diff --git a/techlibs/gowin/.gitignore b/techlibs/gowin/.gitignore
new file mode 100644
index 000000000..d6c48e90d
--- /dev/null
+++ b/techlibs/gowin/.gitignore
@@ -0,0 +1,2 @@
+brams_init.mk
+bram_init_*.vh
diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc
index 6f2159349..d2853704b 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -15,3 +15,13 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/dram.txt))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_init3.vh))
+EXTRA_OBJS += techlibs/gowin/brams_init.mk
+.SECONDARY: techlibs/gowin/brams_init.mk
+
+techlibs/gowin/brams_init.mk: techlibs/gowin/brams_init.py
+ $(Q) mkdir -p techlibs/gowin
+ $(P) python3 $<
+ $(Q) touch $@
+
+techlibs/gowin/bram_init_16.vh: techlibs/gowin/brams_init.mk
+$(eval $(call add_gen_share_file,share/gowin,techlibs/gowin/bram_init_16.vh))
diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v
index e15de6423..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(32'b0))
+ 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/bram.txt b/techlibs/gowin/bram.txt
index b5f9a981c..e406f9c51 100644
--- a/techlibs/gowin/bram.txt
+++ b/techlibs/gowin/bram.txt
@@ -1,6 +1,7 @@
bram $__GW1NR_SDP
-# uncomment when done
-# init 1
+ init 1
+ abits 9 @a9d36
+ dbits 32 @a9d36
abits 10 @a10d18
dbits 16 @a10d18
abits 11 @a11d9
@@ -14,7 +15,8 @@ bram $__GW1NR_SDP
groups 2
ports 1 1
wrmode 1 0
- enable 1 1 @a10d18
+ enable 4 1 @a9d36
+ enable 2 1 @a10d18
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
transp 0 0
clocks 2 3
@@ -24,6 +26,6 @@ endbram
match $__GW1NR_SDP
min bits 2048
min efficiency 5
- shuffle_enable B
+ shuffle_enable A
make_transp
endmatch
diff --git a/techlibs/gowin/brams_init.py b/techlibs/gowin/brams_init.py
new file mode 100755
index 000000000..b78eb8da5
--- /dev/null
+++ b/techlibs/gowin/brams_init.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+
+with open("techlibs/gowin/bram_init_16.vh", "w") as f:
+ for i in range(0, 0x40):
+ low = i << 8
+ hi = ((i+1) << 8)-1
+ snippet = "INIT[%d:%d]" % (hi, low)
+ print(".INIT_RAM_%02X({%s})," % (i, snippet), file=f)
diff --git a/techlibs/gowin/brams_map.v b/techlibs/gowin/brams_map.v
index e963cfa88..fbebc4af8 100644
--- a/techlibs/gowin/brams_map.v
+++ b/techlibs/gowin/brams_map.v
@@ -8,26 +8,28 @@
module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 16;
- parameter CFG_ENABLE_A = 3;
-
- parameter [16383:0] INIT = 16384'hx;
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
+ parameter CFG_ENABLE_A = 1;
+ parameter [16383:0] INIT = 16384'hx;
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
input CLK2;
input CLK3;
input [CFG_ABITS-1:0] A1ADDR;
input [CFG_DBITS-1:0] A1DATA;
- input [CFG_ENABLE_A-1:0] A1EN;
+ input [CFG_ENABLE_A-1:0] A1EN;
input [CFG_ABITS-1:0] B1ADDR;
output [CFG_DBITS-1:0] B1DATA;
input B1EN;
+ wire [31-CFG_DBITS:0] open;
+
generate if (CFG_DBITS == 1) begin
SDP #(
+ `include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(1),
.BIT_WIDTH_1(1),
@@ -38,10 +40,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
- .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ .DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
+ .DO({open, B1DATA}),
+ .ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS == 2) begin
SDP #(
+ `include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(2),
.BIT_WIDTH_1(2),
@@ -52,10 +58,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
- .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ .DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
+ .DO({open, B1DATA}),
+ .ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 4) begin
SDP #(
+ `include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(4),
.BIT_WIDTH_1(4),
@@ -66,10 +76,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0),
.WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
- .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ .DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
+ .DO({open, B1DATA}),
+ .ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 8) begin
SDP #(
+ `include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(8),
.BIT_WIDTH_1(8),
@@ -80,10 +94,14 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
.WREB(1'b0), .CEB(B1EN),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
- .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ .DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
+ .DO({open, B1DATA}),
+ .ADA({A1ADDR, {(14-CFG_ABITS){1'b0}}}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else if (CFG_DBITS <= 16) begin
SDP #(
+ `include "bram_init_16.vh"
.READ_MODE(0),
.BIT_WIDTH_0(16),
.BIT_WIDTH_1(16),
@@ -91,10 +109,31 @@ module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
.RESET_MODE("SYNC")
) _TECHMAP_REPLACE_ (
.CLKA(CLK2), .CLKB(CLK3),
- .WREA(A1EN), .OCE(1'b0),
+ .WREA(|A1EN), .OCE(1'b0),
+ .WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .DI({{(32-CFG_DBITS){1'b0}}, A1DATA}),
+ .DO({open, B1DATA}),
+ .ADA({A1ADDR, {(12-CFG_ABITS){1'b0}}, A1EN}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
+ );
+ end else if (CFG_DBITS <= 32) begin
+ SDP #(
+ `include "bram_init_16.vh"
+ .READ_MODE(0),
+ .BIT_WIDTH_0(32),
+ .BIT_WIDTH_1(32),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(|A1EN), .OCE(1'b0),
.WREB(1'b0), .CEB(B1EN), .CEA(1'b1),
.RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
- .DI(A1DATA), .DO(B1DATA), .ADA(A1ADDR), .ADB(B1ADDR)
+ .DI(A1DATA),
+ .DO(B1DATA),
+ .ADA({A1ADDR, {(10-CFG_ABITS){1'b0}}, A1EN}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
);
end else begin
wire TECHMAP_FAIL = 1'b1;
diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v
index ebdc88a0a..9845e56a7 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -1,9 +1,83 @@
+//All DFF* have INIT, but the hardware is always initialised to the reset
+//value regardless. The parameter is ignored.
+
+// DFFN D Flip-Flop with Negative-Edge Clock
module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
-module \$_DFF_P_ #(parameter INIT = 1'b0) (input D, C, output Q); DFF #(.INIT(INIT)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+// DFF D Flip-Flop
+module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+
+// DFFE D Flip-Flop with Clock Enable
+module \$_DFFE_PP_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
+module \$_DFFE_PN_ (input D, C, E, output Q); DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
+
+// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
+module \$_DFFE_NP_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E)); endmodule
+module \$_DFFE_NN_ (input D, C, E, output Q); DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E)); endmodule
+// DFFR D Flip-Flop with Synchronous Reset
module \$__DFFS_PN0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
module \$__DFFS_PP0_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
-module \$__DFFS_PP1_ (input D, C, R, output Q); DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
+
+// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
+module \$__DFFS_NN0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R)); endmodule
+module \$__DFFS_NP0_ (input D, C, R, output Q); DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R)); endmodule
+
+// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
+module \$__DFFSE_PN0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
+module \$__DFFSE_PP0 (input D, C, R, E, output Q); DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
+
+// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
+module \$__DFFNSE_PN0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E)); endmodule
+module \$__DFFNSE_PP0 (input D, C, R, E, output Q); DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E)); endmodule
+
+// DFFS D Flip-Flop with Synchronous Set
+module \$__DFFS_PN1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
+module \$__DFFS_PP1_ (input D, C, R, output Q); DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
+
+// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
+module \$__DFFS_NN1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R)); endmodule
+module \$__DFFS_NP1_ (input D, C, R, output Q); DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R)); endmodule
+
+// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
+module \$__DFFSE_PN1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
+module \$__DFFSE_PP1 (input D, C, R, E, output Q); DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
+
+// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
+module \$__DFFSE_NN1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E)); endmodule
+module \$__DFFSE_NP1 (input D, C, R, E, output Q); DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E)); endmodule
+
+// DFFP D Flip-Flop with Asynchronous Preset
+module \$_DFF_PP1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
+
+// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
+module \$_DFF_NP1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R)); endmodule
+
+// DFFC D Flip-Flop with Asynchronous Clear
+module \$_DFF_PP0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
+
+// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
+module \$_DFF_NP0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R)); endmodule
+module \$_DFF_NN0_ (input D, C, R, output Q); DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R)); endmodule
+
+// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
+module \$__DFFE_PP1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
+module \$__DFFE_PN1 (input D, C, R, E, output Q); DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
+
+// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
+module \$__DFFE_NP1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E)); endmodule
+module \$__DFFE_NN1 (input D, C, R, E, output Q); DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E)); endmodule
+
+// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
+module \$__DFFE_PP0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
+module \$__DFFE_PN0 (input D, C, R, E, output Q); DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
+
+// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
+module \$__DFFE_NP0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E)); endmodule
+module \$__DFFE_NN0 (input D, C, R, E, output Q); DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E)); endmodule
+
module \$lut (A, Y);
parameter WIDTH = 0;
@@ -28,6 +102,30 @@ module \$lut (A, Y);
if (WIDTH == 4) begin
LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
.I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[15: 0]), .WIDTH(4)) lut0 (.A(A[3:0]), .Y(f0));
+ \$lut #(.LUT(LUT[31:16]), .WIDTH(4)) lut1 (.A(A[3:0]), .Y(f1));
+ MUX2_LUT5 mux5(.I0(f0), .I1(f1), .S0(A[4]), .O(Y));
+ end else
+ if (WIDTH == 6) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[31: 0]), .WIDTH(5)) lut0 (.A(A[4:0]), .Y(f0));
+ \$lut #(.LUT(LUT[63:32]), .WIDTH(5)) lut1 (.A(A[4:0]), .Y(f1));
+ MUX2_LUT6 mux6(.I0(f0), .I1(f1), .S0(A[5]), .O(Y));
+ end else
+ if (WIDTH == 7) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[63: 0]), .WIDTH(6)) lut0 (.A(A[5:0]), .Y(f0));
+ \$lut #(.LUT(LUT[127:64]), .WIDTH(6)) lut1 (.A(A[5:0]), .Y(f1));
+ MUX2_LUT7 mux7(.I0(f0), .I1(f1), .S0(A[6]), .O(Y));
+ end else
+ if (WIDTH == 8) begin
+ wire f0, f1;
+ \$lut #(.LUT(LUT[127: 0]), .WIDTH(7)) lut0 (.A(A[6:0]), .Y(f0));
+ \$lut #(.LUT(LUT[255:128]), .WIDTH(7)) lut1 (.A(A[6:0]), .Y(f1));
+ MUX2_LUT8 mux8(.I0(f0), .I1(f1), .S0(A[7]), .O(Y));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index ebb238bad..a67855dab 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -24,6 +24,41 @@ module LUT4(output F, input I0, I1, I2, I3);
assign F = I0 ? s1[1] : s1[0];
endmodule
+module MUX2 (O, I0, I1, S0);
+ input I0,I1;
+ input S0;
+ output O;
+ assign O = S0 ? I1 : I0;
+endmodule
+
+module MUX2_LUT5 (O, I0, I1, S0);
+ input I0,I1;
+ input S0;
+ output O;
+ MUX2 mux2_lut5 (O, I0, I1, S0);
+endmodule
+
+module MUX2_LUT6 (O, I0, I1, S0);
+ input I0,I1;
+ input S0;
+ output O;
+ MUX2 mux2_lut6 (O, I0, I1, S0);
+endmodule
+
+module MUX2_LUT7 (O, I0, I1, S0);
+ input I0,I1;
+ input S0;
+ output O;
+ MUX2 mux2_lut7 (O, I0, I1, S0);
+endmodule
+
+module MUX2_LUT8 (O, I0, I1, S0);
+ input I0,I1;
+ input S0;
+ output O;
+ MUX2 mux2_lut8 (O, I0, I1, S0);
+endmodule
+
module DFF (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
@@ -31,6 +66,112 @@ module DFF (output reg Q, input CLK, D);
Q <= D;
endmodule
+module DFFE (output reg Q, input D, CLK, CE);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (CE)
+ Q <= D;
+ end
+endmodule // DFFE (positive clock edge; clock enable)
+
+
+module DFFS (output reg Q, input D, CLK, SET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFS (positive clock edge; synchronous set)
+
+
+module DFFSE (output reg Q, input D, CLK, CE, SET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+end
+endmodule // DFFSE (positive clock edge; synchronous set takes precedence over clock enable)
+
+
+module DFFR (output reg Q, input D, CLK, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFR (positive clock edge; synchronous reset)
+
+
+module DFFRE (output reg Q, input D, CLK, CE, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFRE (positive clock edge; synchronous reset takes precedence over clock enable)
+
+
+module DFFP (output reg Q, input D, CLK, PRESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFP (positive clock edge; asynchronous preset)
+
+
+module DFFPE (output reg Q, input D, CLK, CE, PRESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFPE (positive clock edge; asynchronous preset; clock enable)
+
+
+module DFFC (output reg Q, input D, CLK, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFC (positive clock edge; asynchronous clear)
+
+
+module DFFCE (output reg Q, input D, CLK, CE, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFCE (positive clock edge; asynchronous clear; clock enable)
+
+
module DFFN (output reg Q, input CLK, D);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;
@@ -38,16 +179,112 @@ module DFFN (output reg Q, input CLK, D);
Q <= D;
endmodule
-module DFFR (output reg Q, input D, CLK, RESET);
- parameter [0:0] INIT = 1'b0;
- initial Q = INIT;
- always @(posedge CLK) begin
- if (RESET)
- Q <= 1'b0;
- else
- Q <= D;
- end
-endmodule // DFFR (positive clock edge; synchronous reset)
+module DFFNE (output reg Q, input D, CLK, CE);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (CE)
+ Q <= D;
+ end
+endmodule // DFFNE (negative clock edge; clock enable)
+
+
+module DFFNS (output reg Q, input D, CLK, SET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFNS (negative clock edge; synchronous set)
+
+
+module DFFNSE (output reg Q, input D, CLK, CE, SET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (SET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+end
+endmodule // DFFNSE (negative clock edge; synchronous set takes precedence over clock enable)
+
+
+module DFFNR (output reg Q, input D, CLK, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFNR (negative clock edge; synchronous reset)
+
+
+module DFFNRE (output reg Q, input D, CLK, CE, RESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK) begin
+ if (RESET)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNRE (negative clock edge; synchronous reset takes precedence over clock enable)
+
+
+module DFFNP (output reg Q, input D, CLK, PRESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else
+ Q <= D;
+ end
+endmodule // DFFNP (negative clock edge; asynchronous preset)
+
+
+module DFFNPE (output reg Q, input D, CLK, CE, PRESET);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge PRESET) begin
+ if(PRESET)
+ Q <= 1'b1;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNPE (negative clock edge; asynchronous preset; clock enable)
+
+
+module DFFNC (output reg Q, input D, CLK, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else
+ Q <= D;
+ end
+endmodule // DFFNC (negative clock edge; asynchronous clear)
+
+
+module DFFNCE (output reg Q, input D, CLK, CE, CLEAR);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(negedge CLK or posedge CLEAR) begin
+ if(CLEAR)
+ Q <= 1'b0;
+ else if (CE)
+ Q <= D;
+ end
+endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable)
+
+// TODO add more DFF sim cells
module VCC(output V);
assign V = 1;
@@ -65,14 +302,98 @@ module OBUF(output O, input I);
assign O = I;
endmodule
+module TBUF (O, I, OEN);
+ input I, OEN;
+ output O;
+ assign O = OEN ? I : 1'bz;
+endmodule
+
+module IOBUF (O, IO, I, OEN);
+ input I,OEN;
+ output O;
+ inout IO;
+ assign IO = OEN ? I : 1'bz;
+ assign I = IO;
+endmodule
+
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;
+
+localparam ADD = 0;
+localparam SUB = 1;
+localparam ADDSUB = 2;
+localparam NE = 3;
+localparam GE = 4;
+localparam LE = 5;
+localparam CUP = 6;
+localparam CDN = 7;
+localparam CUPCDN = 8;
+localparam MULT = 9;
+
+parameter ALU_MODE = 0;
+
+reg S, C;
+
+assign SUM = S ^ CIN;
+assign COUT = S? CIN : C;
+
+always @* 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;
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index ac3dbfb29..3c1426414 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -64,6 +64,12 @@ struct SynthGowinPass : public ScriptPass
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
+ log(" -nowidelut\n");
+ log(" do not use muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -abc9\n");
+ log(" use new ABC9 flow (EXPERIMENTAL)\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
@@ -71,7 +77,7 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
- bool retime, nobram, nodram, flatten, nodffe;
+ bool retime, nobram, nodram, flatten, nodffe, nowidelut, abc9;
void clear_flags() YS_OVERRIDE
{
@@ -82,6 +88,8 @@ struct SynthGowinPass : public ScriptPass
nobram = false;
nodffe = false;
nodram = false;
+ nowidelut = false;
+ abc9 = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -128,6 +136,14 @@ struct SynthGowinPass : public ScriptPass
flatten = false;
continue;
}
+ if (args[argidx] == "-nowidelut") {
+ nowidelut = true;
+ continue;
+ }
+ if (args[argidx] == "-abc9") {
+ abc9 = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -163,8 +179,8 @@ struct SynthGowinPass : public ScriptPass
{
run("synth -run coarse");
}
-
- if (!nobram && check_label("bram", "(skip if -nobram)"))
+
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/gowin/bram.txt");
run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v");
@@ -186,6 +202,7 @@ struct SynthGowinPass : public ScriptPass
run("techmap -map +/techmap.v");
if (retime || help_mode)
run("abc -dff", "(only if -retime)");
+ run("splitnets");
}
if (check_label("map_ffs"))
@@ -202,16 +219,25 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_luts"))
{
- run("abc -lut 4");
+ if (nowidelut && abc9) {
+ run("abc9 -lut 4");
+ } else if (nowidelut && !abc9) {
+ run("abc -lut 4");
+ } else if (!nowidelut && abc9) {
+ run("abc9 -lut 4:8");
+ } else if (!nowidelut && !abc9) {
+ run("abc -lut 4:8");
+ }
run("clean");
}
if (check_label("map_cells"))
{
run("techmap -map +/gowin/cells_map.v");
- run("hilomap -hicell VCC V -locell GND G");
- run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O", "(unless -noiopads)");
- run("dffinit -ff DFF Q INIT");
+ run("setundef -undriven -params -zero");
+ run("hilomap -singleton -hicell VCC V -locell GND G");
+ run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
+ "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");
run("clean");
}
@@ -226,7 +252,7 @@ struct SynthGowinPass : public ScriptPass
if (check_label("vout"))
{
if (!vout_file.empty() || help_mode)
- run(stringf("write_verilog -nodec -attr2comment -defparam -renameprefix gen %s",
+ run(stringf("write_verilog -decimal -attr2comment -defparam -renameprefix gen %s",
help_mode ? "<file-name>" : vout_file.c_str()));
}
}
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 03985b1be..1be43f9d4 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -59,6 +59,34 @@ module OBUF(
assign O = I;
endmodule
+module IOBUF (
+ (* iopad_external_pin *)
+ inout IO,
+ output O,
+ input I,
+ input T
+);
+ parameter integer DRIVE = 12;
+ parameter IBUF_LOW_PWR = "TRUE";
+ parameter IOSTANDARD = "DEFAULT";
+ parameter SLEW = "SLOW";
+ assign IO = T ? 1'bz : I;
+ assign O = IO;
+endmodule
+
+module OBUFT (
+ (* iopad_external_pin *)
+ output O,
+ input I,
+ input T
+);
+ parameter CAPACITANCE = "DONT_CARE";
+ parameter integer DRIVE = 12;
+ parameter IOSTANDARD = "DEFAULT";
+ parameter SLEW = "SLOW";
+ assign O = T ? 1'bz : I;
+endmodule
+
module BUFG(
(* clkbuf_driver *)
output O,
@@ -126,7 +154,11 @@ endmodule
// assign O = IO, IO = T ? 1'bz : I;
// endmodule
-module INV(output O, input I);
+module INV(
+ (* clkbuf_inv = "I" *)
+ output O,
+ input I
+);
assign O = !I;
endmodule
@@ -581,6 +613,515 @@ module SRLC32E (
endgenerate
endmodule
+// DSP
+
+// Virtex 2, Virtex 2 Pro, Spartan 3.
+
+// Asynchronous mode.
+
+module MULT18X18 (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ output signed [35:0] P
+);
+
+assign P = A * B;
+
+endmodule
+
+// Synchronous mode.
+
+module MULT18X18S (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ output reg signed [35:0] P,
+ (* clkbuf_sink *)
+ input C,
+ input CE,
+ input R
+);
+
+always @(posedge C)
+ if (R)
+ P <= 0;
+ else if (CE)
+ P <= A * B;
+
+endmodule
+
+// Spartan 3E, Spartan 3A.
+
+module MULT18X18SIO (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ output signed [35:0] P,
+ (* clkbuf_sink *)
+ input CLK,
+ input CEA,
+ input CEB,
+ input CEP,
+ input RSTA,
+ input RSTB,
+ input RSTP,
+ input signed [17:0] BCIN,
+ output signed [17:0] BCOUT
+);
+
+parameter integer AREG = 1;
+parameter integer BREG = 1;
+parameter B_INPUT = "DIRECT";
+parameter integer PREG = 1;
+
+// The multiplier.
+wire signed [35:0] P_MULT;
+assign P_MULT = A_MULT * B_MULT;
+
+// The cascade output.
+assign BCOUT = B_MULT;
+
+// The B input multiplexer.
+wire signed [17:0] B_MUX;
+assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN;
+
+// The registers.
+reg signed [17:0] A_REG;
+reg signed [17:0] B_REG;
+reg signed [35:0] P_REG;
+
+initial begin
+ A_REG = 0;
+ B_REG = 0;
+ P_REG = 0;
+end
+
+always @(posedge CLK) begin
+ if (RSTA)
+ A_REG <= 0;
+ else if (CEA)
+ A_REG <= A;
+
+ if (RSTB)
+ B_REG <= 0;
+ else if (CEB)
+ B_REG <= B_MUX;
+
+ if (RSTP)
+ P_REG <= 0;
+ else if (CEP)
+ P_REG <= P_MULT;
+end
+
+// The register enables.
+wire signed [17:0] A_MULT;
+wire signed [17:0] B_MULT;
+assign A_MULT = (AREG == 1) ? A_REG : A;
+assign B_MULT = (BREG == 1) ? B_REG : B_MUX;
+assign P = (PREG == 1) ? P_REG : P_MULT;
+
+endmodule
+
+// Spartan 3A DSP.
+
+module DSP48A (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ input signed [47:0] C,
+ input signed [17:0] D,
+ input signed [47:0] PCIN,
+ input CARRYIN,
+ input [7:0] OPMODE,
+ output signed [47:0] P,
+ output signed [17:0] BCOUT,
+ output signed [47:0] PCOUT,
+ output CARRYOUT,
+ (* clkbuf_sink *)
+ input CLK,
+ input CEA,
+ input CEB,
+ input CEC,
+ input CED,
+ input CEM,
+ input CECARRYIN,
+ input CEOPMODE,
+ input CEP,
+ input RSTA,
+ input RSTB,
+ input RSTC,
+ input RSTD,
+ input RSTM,
+ input RSTCARRYIN,
+ input RSTOPMODE,
+ input RSTP
+);
+
+parameter integer A0REG = 0;
+parameter integer A1REG = 1;
+parameter integer B0REG = 0;
+parameter integer B1REG = 1;
+parameter integer CREG = 1;
+parameter integer DREG = 1;
+parameter integer MREG = 1;
+parameter integer CARRYINREG = 1;
+parameter integer OPMODEREG = 1;
+parameter integer PREG = 1;
+parameter CARRYINSEL = "CARRYIN";
+parameter RSTTYPE = "SYNC";
+
+// This is a strict subset of Spartan 6 -- reuse its model.
+
+DSP48A1 #(
+ .A0REG(A0REG),
+ .A1REG(A1REG),
+ .B0REG(B0REG),
+ .B1REG(B1REG),
+ .CREG(CREG),
+ .DREG(DREG),
+ .MREG(MREG),
+ .CARRYINREG(CARRYINREG),
+ .CARRYOUTREG(0),
+ .OPMODEREG(OPMODEREG),
+ .PREG(PREG),
+ .CARRYINSEL(CARRYINSEL),
+ .RSTTYPE(RSTTYPE)
+) upgrade (
+ .A(A),
+ .B(B),
+ .C(C),
+ .D(D),
+ .PCIN(PCIN),
+ .CARRYIN(CARRYIN),
+ .OPMODE(OPMODE),
+ // M unconnected
+ .P(P),
+ .BCOUT(BCOUT),
+ .PCOUT(PCOUT),
+ .CARRYOUT(CARRYOUT),
+ // CARRYOUTF unconnected
+ .CLK(CLK),
+ .CEA(CEA),
+ .CEB(CEB),
+ .CEC(CEC),
+ .CED(CED),
+ .CEM(CEM),
+ .CECARRYIN(CECARRYIN),
+ .CEOPMODE(CEOPMODE),
+ .CEP(CEP),
+ .RSTA(RSTA),
+ .RSTB(RSTB),
+ .RSTC(RSTC),
+ .RSTD(RSTD),
+ .RSTM(RSTM),
+ .RSTCARRYIN(RSTCARRYIN),
+ .RSTOPMODE(RSTOPMODE),
+ .RSTP(RSTP)
+);
+
+endmodule
+
+// Spartan 6.
+
+module DSP48A1 (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ input signed [47:0] C,
+ input signed [17:0] D,
+ input signed [47:0] PCIN,
+ input CARRYIN,
+ input [7:0] OPMODE,
+ output signed [35:0] M,
+ output signed [47:0] P,
+ output signed [17:0] BCOUT,
+ output signed [47:0] PCOUT,
+ output CARRYOUT,
+ output CARRYOUTF,
+ (* clkbuf_sink *)
+ input CLK,
+ input CEA,
+ input CEB,
+ input CEC,
+ input CED,
+ input CEM,
+ input CECARRYIN,
+ input CEOPMODE,
+ input CEP,
+ input RSTA,
+ input RSTB,
+ input RSTC,
+ input RSTD,
+ input RSTM,
+ input RSTCARRYIN,
+ input RSTOPMODE,
+ input RSTP
+);
+
+parameter integer A0REG = 0;
+parameter integer A1REG = 1;
+parameter integer B0REG = 0;
+parameter integer B1REG = 1;
+parameter integer CREG = 1;
+parameter integer DREG = 1;
+parameter integer MREG = 1;
+parameter integer CARRYINREG = 1;
+parameter integer CARRYOUTREG = 1;
+parameter integer OPMODEREG = 1;
+parameter integer PREG = 1;
+parameter CARRYINSEL = "OPMODE5";
+parameter RSTTYPE = "SYNC";
+
+wire signed [35:0] M_MULT;
+wire signed [47:0] P_IN;
+wire signed [17:0] A0_OUT;
+wire signed [17:0] B0_OUT;
+wire signed [17:0] A1_OUT;
+wire signed [17:0] B1_OUT;
+wire signed [17:0] B1_IN;
+wire signed [47:0] C_OUT;
+wire signed [17:0] D_OUT;
+wire signed [7:0] OPMODE_OUT;
+wire CARRYIN_OUT;
+wire CARRYOUT_IN;
+wire CARRYIN_IN;
+reg signed [47:0] XMUX;
+reg signed [47:0] ZMUX;
+
+// The registers.
+reg signed [17:0] A0_REG;
+reg signed [17:0] A1_REG;
+reg signed [17:0] B0_REG;
+reg signed [17:0] B1_REG;
+reg signed [47:0] C_REG;
+reg signed [17:0] D_REG;
+reg signed [35:0] M_REG;
+reg signed [47:0] P_REG;
+reg [7:0] OPMODE_REG;
+reg CARRYIN_REG;
+reg CARRYOUT_REG;
+
+initial begin
+ A0_REG = 0;
+ A1_REG = 0;
+ B0_REG = 0;
+ B1_REG = 0;
+ C_REG = 0;
+ D_REG = 0;
+ M_REG = 0;
+ P_REG = 0;
+ OPMODE_REG = 0;
+ CARRYIN_REG = 0;
+ CARRYOUT_REG = 0;
+end
+
+generate
+
+if (RSTTYPE == "SYNC") begin
+ always @(posedge CLK) begin
+ if (RSTA) begin
+ A0_REG <= 0;
+ A1_REG <= 0;
+ end else if (CEA) begin
+ A0_REG <= A;
+ A1_REG <= A0_OUT;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTB) begin
+ B0_REG <= 0;
+ B1_REG <= 0;
+ end else if (CEB) begin
+ B0_REG <= B;
+ B1_REG <= B1_IN;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTC) begin
+ C_REG <= 0;
+ end else if (CEC) begin
+ C_REG <= C;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTD) begin
+ D_REG <= 0;
+ end else if (CED) begin
+ D_REG <= D;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTM) begin
+ M_REG <= 0;
+ end else if (CEM) begin
+ M_REG <= M_MULT;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTP) begin
+ P_REG <= 0;
+ end else if (CEP) begin
+ P_REG <= P_IN;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTOPMODE) begin
+ OPMODE_REG <= 0;
+ end else if (CEOPMODE) begin
+ OPMODE_REG <= OPMODE;
+ end
+ end
+
+ always @(posedge CLK) begin
+ if (RSTCARRYIN) begin
+ CARRYIN_REG <= 0;
+ CARRYOUT_REG <= 0;
+ end else if (CECARRYIN) begin
+ CARRYIN_REG <= CARRYIN_IN;
+ CARRYOUT_REG <= CARRYOUT_IN;
+ end
+ end
+end else begin
+ always @(posedge CLK, posedge RSTA) begin
+ if (RSTA) begin
+ A0_REG <= 0;
+ A1_REG <= 0;
+ end else if (CEA) begin
+ A0_REG <= A;
+ A1_REG <= A0_OUT;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTB) begin
+ if (RSTB) begin
+ B0_REG <= 0;
+ B1_REG <= 0;
+ end else if (CEB) begin
+ B0_REG <= B;
+ B1_REG <= B1_IN;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTC) begin
+ if (RSTC) begin
+ C_REG <= 0;
+ end else if (CEC) begin
+ C_REG <= C;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTD) begin
+ if (RSTD) begin
+ D_REG <= 0;
+ end else if (CED) begin
+ D_REG <= D;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTM) begin
+ if (RSTM) begin
+ M_REG <= 0;
+ end else if (CEM) begin
+ M_REG <= M_MULT;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTP) begin
+ if (RSTP) begin
+ P_REG <= 0;
+ end else if (CEP) begin
+ P_REG <= P_IN;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTOPMODE) begin
+ if (RSTOPMODE) begin
+ OPMODE_REG <= 0;
+ end else if (CEOPMODE) begin
+ OPMODE_REG <= OPMODE;
+ end
+ end
+
+ always @(posedge CLK, posedge RSTCARRYIN) begin
+ if (RSTCARRYIN) begin
+ CARRYIN_REG <= 0;
+ CARRYOUT_REG <= 0;
+ end else if (CECARRYIN) begin
+ CARRYIN_REG <= CARRYIN_IN;
+ CARRYOUT_REG <= CARRYOUT_IN;
+ end
+ end
+end
+
+endgenerate
+
+// The register enables.
+assign A0_OUT = (A0REG == 1) ? A0_REG : A;
+assign A1_OUT = (A1REG == 1) ? A1_REG : A0_OUT;
+assign B0_OUT = (B0REG == 1) ? B0_REG : B;
+assign B1_OUT = (B1REG == 1) ? B1_REG : B1_IN;
+assign C_OUT = (CREG == 1) ? C_REG : C;
+assign D_OUT = (DREG == 1) ? D_REG : D;
+assign M = (MREG == 1) ? M_REG : M_MULT;
+assign P = (PREG == 1) ? P_REG : P_IN;
+assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE;
+assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN_IN;
+assign CARRYOUT = (CARRYOUTREG == 1) ? CARRYOUT_REG : CARRYOUT_IN;
+assign CARRYOUTF = CARRYOUT;
+
+// The pre-adder.
+wire signed [17:0] PREADDER;
+assign B1_IN = OPMODE_OUT[4] ? PREADDER : B0_OUT;
+assign PREADDER = OPMODE_OUT[6] ? D_OUT - B0_OUT : D_OUT + B0_OUT;
+
+// The multiplier.
+assign M_MULT = A1_OUT * B1_OUT;
+
+// The carry in selection.
+assign CARRYIN_IN = (CARRYINSEL == "OPMODE5") ? OPMODE_OUT[5] : CARRYIN;
+
+// The post-adder inputs.
+always @* begin
+ case (OPMODE_OUT[1:0])
+ 2'b00: XMUX <= 0;
+ 2'b01: XMUX <= M;
+ 2'b10: XMUX <= P;
+ 2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT};
+ default: XMUX <= 48'hxxxxxxxxxxxx;
+ endcase
+end
+
+always @* begin
+ case (OPMODE_OUT[3:2])
+ 2'b00: ZMUX <= 0;
+ 2'b01: ZMUX <= PCIN;
+ 2'b10: ZMUX <= P;
+ 2'b11: ZMUX <= C_OUT;
+ default: ZMUX <= 48'hxxxxxxxxxxxx;
+ endcase
+end
+
+// The post-adder.
+wire signed [48:0] X_EXT;
+wire signed [48:0] Z_EXT;
+assign X_EXT = XMUX;
+assign Z_EXT = ZMUX;
+assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT);
+
+// Cascade outputs.
+assign BCOUT = B1_OUT;
+assign PCOUT = P;
+
+endmodule
+
+// TODO: DSP48 (Virtex 4).
+
+// TODO: DSP48E (Virtex 5).
+
+// Virtex 6, Series 7.
+
module DSP48E1 (
output [29:0] ACOUT,
output [17:0] BCOUT,
@@ -1043,3 +1584,5 @@ module DSP48E1 (
endgenerate
endmodule
+
+// TODO: DSP48E2 (Ultrascale).
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index ef7ce856a..82e403f78 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -204,11 +204,11 @@ CELLS = [
Cell('URAM288_BASE', port_attrs={'CLK': ['clkbuf_sink']}),
# Multipliers and DSP.
- Cell('MULT18X18'), # Spartan 3
- Cell('MULT18X18S', port_attrs={'C': ['clkbuf_sink']}), # Spartan 3
- Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
- Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
- Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
+ # Cell('MULT18X18'), # Virtex 2, Spartan 3
+ # Cell('MULT18X18S', port_attrs={'C': ['clkbuf_sink']}), # Spartan 3
+ # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
+ # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
+ # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4
Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5
#Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
@@ -326,7 +326,7 @@ CELLS = [
Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),
# I/O.
- Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
+ # Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUF_DCIEN', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUF_INTERMDISABLE', port_attrs={'IO': ['iopad_external_pin']}),
Cell('IOBUFE3', port_attrs={'IO': ['iopad_external_pin']}),
@@ -342,7 +342,7 @@ CELLS = [
Cell('OBUFDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
Cell('OBUFDS_DPHY', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Output + tristate.
- Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
+ # Cell('OBUFT', port_attrs={'O': ['iopad_external_pin']}),
Cell('OBUFTDS', port_attrs={'O': ['iopad_external_pin'], 'OB': ['iopad_external_pin']}),
# Pulls.
Cell('KEEPER'),
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 72a3b6cbb..671d16e8a 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -6218,133 +6218,6 @@ module URAM288_BASE (...);
input SLEEP;
endmodule
-module MULT18X18 (...);
- output [35:0] P;
- input [17:0] A;
- input [17:0] B;
-endmodule
-
-module MULT18X18S (...);
- output [35:0] P;
- input [17:0] A;
- input [17:0] B;
- (* clkbuf_sink *)
- input C;
- input CE;
- input R;
-endmodule
-
-module MULT18X18SIO (...);
- parameter integer AREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer PREG = 1;
- output [17:0] BCOUT;
- output [35:0] P;
- input [17:0] A;
- input [17:0] B;
- input [17:0] BCIN;
- input CEA;
- input CEB;
- input CEP;
- (* clkbuf_sink *)
- input CLK;
- input RSTA;
- input RSTB;
- input RSTP;
-endmodule
-
-module DSP48A (...);
- parameter integer A0REG = 0;
- parameter integer A1REG = 1;
- parameter integer B0REG = 0;
- parameter integer B1REG = 1;
- parameter integer CARRYINREG = 1;
- parameter CARRYINSEL = "CARRYIN";
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter RSTTYPE = "SYNC";
- output [17:0] BCOUT;
- output CARRYOUT;
- output [47:0] P;
- output [47:0] PCOUT;
- input [17:0] A;
- input [17:0] B;
- input [47:0] C;
- input CARRYIN;
- input CEA;
- input CEB;
- input CEC;
- input CECARRYIN;
- input CED;
- input CEM;
- input CEOPMODE;
- input CEP;
- (* clkbuf_sink *)
- input CLK;
- input [17:0] D;
- input [7:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTB;
- input RSTC;
- input RSTCARRYIN;
- input RSTD;
- input RSTM;
- input RSTOPMODE;
- input RSTP;
-endmodule
-
-module DSP48A1 (...);
- parameter integer A0REG = 0;
- parameter integer A1REG = 1;
- parameter integer B0REG = 0;
- parameter integer B1REG = 1;
- parameter integer CARRYINREG = 1;
- parameter integer CARRYOUTREG = 1;
- parameter CARRYINSEL = "OPMODE5";
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter RSTTYPE = "SYNC";
- output [17:0] BCOUT;
- output CARRYOUT;
- output CARRYOUTF;
- output [35:0] M;
- output [47:0] P;
- output [47:0] PCOUT;
- input [17:0] A;
- input [17:0] B;
- input [47:0] C;
- input CARRYIN;
- input CEA;
- input CEB;
- input CEC;
- input CECARRYIN;
- input CED;
- input CEM;
- input CEOPMODE;
- input CEP;
- (* clkbuf_sink *)
- input CLK;
- input [17:0] D;
- input [7:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTB;
- input RSTC;
- input RSTCARRYIN;
- input RSTD;
- input RSTM;
- input RSTOPMODE;
- input RSTP;
-endmodule
-
module DSP48 (...);
parameter integer AREG = 1;
parameter integer BREG = 1;
@@ -8287,18 +8160,6 @@ module IBUFGDS_DIFF_OUT (...);
input IB;
endmodule
-module IOBUF (...);
- parameter integer DRIVE = 12;
- parameter IBUF_LOW_PWR = "TRUE";
- parameter IOSTANDARD = "DEFAULT";
- parameter SLEW = "SLOW";
- output O;
- (* iopad_external_pin *)
- inout IO;
- input I;
- input T;
-endmodule
-
module IOBUF_DCIEN (...);
parameter integer DRIVE = 12;
parameter IBUF_LOW_PWR = "TRUE";
@@ -8500,17 +8361,6 @@ module OBUFDS_DPHY (...);
input LPTX_T;
endmodule
-module OBUFT (...);
- parameter CAPACITANCE = "DONT_CARE";
- parameter integer DRIVE = 12;
- parameter IOSTANDARD = "DEFAULT";
- parameter SLEW = "SLOW";
- (* iopad_external_pin *)
- output O;
- input I;
- input T;
-endmodule
-
module OBUFTDS (...);
parameter CAPACITANCE = "DONT_CARE";
parameter IOSTANDARD = "DEFAULT";
diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v
index 13d3c3268..62d501632 100644
--- a/techlibs/xilinx/lut_map.v
+++ b/techlibs/xilinx/lut_map.v
@@ -56,8 +56,12 @@ module \$lut (A, Y);
generate
if (WIDTH == 1) begin
- LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]));
+ if (P_LUT == 2'b01) begin
+ INV _TECHMAP_REPLACE_ (.O(Y), .I(A[0]));
+ end else begin
+ LUT1 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(A[0]));
+ end
end else
if (WIDTH == 2) begin
LUT2 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.O(Y),