aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/gowin
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/gowin')
-rw-r--r--techlibs/gowin/.gitignore2
-rw-r--r--techlibs/gowin/Makefile.inc21
-rw-r--r--techlibs/gowin/arith_map.v59
-rw-r--r--techlibs/gowin/brams.txt31
-rwxr-xr-xtechlibs/gowin/brams_init.py8
-rw-r--r--techlibs/gowin/brams_init3.vh12
-rw-r--r--techlibs/gowin/brams_map.v142
-rw-r--r--techlibs/gowin/cells_map.v307
-rw-r--r--techlibs/gowin/cells_sim.v461
-rw-r--r--techlibs/gowin/determine_init.cc72
-rw-r--r--techlibs/gowin/lutrams.txt17
-rw-r--r--techlibs/gowin/lutrams_map.v31
-rw-r--r--techlibs/gowin/synth_gowin.cc133
13 files changed, 1249 insertions, 47 deletions
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 679d7eff5..fe5d9d6e6 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -1,6 +1,27 @@
OBJS += techlibs/gowin/synth_gowin.o
+OBJS += techlibs/gowin/determine_init.o
+
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.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
new file mode 100644
index 000000000..b6f9e8c38
--- /dev/null
+++ b/techlibs/gowin/arith_map.v
@@ -0,0 +1,59 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ input [A_WIDTH-1:0] A;
+ input [B_WIDTH-1:0] B;
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ output [Y_WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ wire [Y_WIDTH-1:0] A_buf, B_buf;
+ \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+ \$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 = 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(2)) // ADDSUB I3 ? add : sub
+ alu(.I0(AA[i]),
+ .I1(BB[i]),
+ .I3(~BI),
+ .CIN(C[i]),
+ .COUT(CO[i]),
+ .SUM(Y[i])
+ );
+ end endgenerate
+ assign X = AA ^ BB;
+endmodule
+
diff --git a/techlibs/gowin/brams.txt b/techlibs/gowin/brams.txt
new file mode 100644
index 000000000..e406f9c51
--- /dev/null
+++ b/techlibs/gowin/brams.txt
@@ -0,0 +1,31 @@
+bram $__GW1NR_SDP
+ init 1
+ abits 9 @a9d36
+ dbits 32 @a9d36
+ abits 10 @a10d18
+ dbits 16 @a10d18
+ abits 11 @a11d9
+ dbits 8 @a11d9
+ abits 12 @a12d4
+ dbits 4 @a12d4
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 4 1 @a9d36
+ enable 2 1 @a10d18
+ enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__GW1NR_SDP
+ min bits 2048
+ min efficiency 5
+ 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_init3.vh b/techlibs/gowin/brams_init3.vh
new file mode 100644
index 000000000..84397fa24
--- /dev/null
+++ b/techlibs/gowin/brams_init3.vh
@@ -0,0 +1,12 @@
+localparam [15:0] INIT_0 = {
+ INIT[ 60], INIT[ 56], INIT[ 52], INIT[ 48], INIT[ 44], INIT[ 40], INIT[ 36], INIT[ 32], INIT[ 28], INIT[ 24], INIT[ 20], INIT[ 16], INIT[ 12], INIT[ 8], INIT[ 4], INIT[ 0]
+};
+localparam [15:0] INIT_1 = {
+ INIT[ 61], INIT[ 57], INIT[ 53], INIT[ 49], INIT[ 45], INIT[ 41], INIT[ 37], INIT[ 33], INIT[ 29], INIT[ 25], INIT[ 21], INIT[ 17], INIT[ 13], INIT[ 9], INIT[ 5], INIT[ 1]
+};
+localparam [15:0] INIT_2 = {
+ INIT[ 62], INIT[ 58], INIT[ 54], INIT[ 50], INIT[ 46], INIT[ 42], INIT[ 38], INIT[ 34], INIT[ 30], INIT[ 26], INIT[ 22], INIT[ 18], INIT[ 14], INIT[ 10], INIT[ 6], INIT[ 2]
+};
+localparam [15:0] INIT_3 = {
+ INIT[ 63], INIT[ 59], INIT[ 55], INIT[ 51], INIT[ 47], INIT[ 43], INIT[ 39], INIT[ 35], INIT[ 31], INIT[ 27], INIT[ 23], INIT[ 19], INIT[ 15], INIT[ 11], INIT[ 7], INIT[ 3]
+};
diff --git a/techlibs/gowin/brams_map.v b/techlibs/gowin/brams_map.v
new file mode 100644
index 000000000..fbebc4af8
--- /dev/null
+++ b/techlibs/gowin/brams_map.v
@@ -0,0 +1,142 @@
+/* Semi Dual Port (SDP) memory have the following configurations:
+ * Memory Config RAM(BIT) Port Mode Memory Depth Data Depth
+ * ----------------|---------| ----------|--------------|------------|
+ * B-SRAM_16K_SD1 16K 16Kx1 16,384 1
+ * B-SRAM_8K_SD2 16K 8Kx2 8,192 2
+ * B-SRAM_4K_SD4 16K 4Kx2 4,096 4
+ */
+module \$__GW1NR_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 16;
+ 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_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),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .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),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .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),
+ .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({{(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),
+ .BLK_SEL(3'b000),
+ .RESET_MODE("SYNC")
+ ) _TECHMAP_REPLACE_ (
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WREA(A1EN), .OCE(1'b0), .CEA(1'b1),
+ .WREB(1'b0), .CEB(B1EN),
+ .RESETA(1'b0), .RESETB(1'b0), .BLKSEL(3'b000),
+ .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),
+ .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({{(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, {(10-CFG_ABITS){1'b0}}, A1EN}),
+ .ADB({B1ADDR, {(14-CFG_ABITS){1'b0}}})
+ );
+ end else begin
+ wire TECHMAP_FAIL = 1'b1;
+ end endgenerate
+
+endmodule
diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v
index e1f85effa..aee912256 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -1,31 +1,282 @@
-module \$_DFF_N_ (input D, C, output Q); DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
-module \$_DFF_P_ (input D, C, output Q); DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C)); endmodule
+`default_nettype none
+//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_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
+ else
+ DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFF D Flip-Flop
+module \$_DFF_P_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(1'b0));
+ else
+ DFF _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFFE D Flip-Flop with Clock Enable
+module \$_DFFE_PP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
+ else
+ DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_DFFE_PN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
+ else
+ DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFFNE D Flip-Flop with Negative-Edge Clock and Clock Enable
+module \$_DFFE_NP_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E), .SET(1'b0));
+ else
+ DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+module \$_DFFE_NN_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, E, output Q);
+ generate
+ if (_TECHMAP_WIREINIT_Q_ === 1'b1)
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E), .SET(1'b0));
+ else
+ DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CE(!E));
+ endgenerate
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+endmodule
+
+// DFFR D Flip-Flop with Synchronous Reset
+module \$__DFFS_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+module \$__DFFS_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFNR D Flip-Flop with Negative-Edge Clock and Synchronous Reset
+module \$__DFFS_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFS_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFRE D Flip-Flop with Clock Enable and Synchronous Reset
+module \$__DFFSE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFSE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFNRE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Synchronous Reset
+module \$__DFFSE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFSE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNRE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .RESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFS D Flip-Flop with Synchronous Set
+module \$__DFFS_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFS_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFNS D Flip-Flop with Negative-Edge Clock and Synchronous Set
+module \$__DFFS_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFS_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFSE D Flip-Flop with Clock Enable and Synchronous Set
+module \$__DFFSE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFSE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFNSE D Flip-Flop with Negative-Edge Clock,Clock Enable,and Synchronous Set
+module \$__DFFSE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFSE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNSE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .SET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFP D Flip-Flop with Asynchronous Preset
+module \$_DFF_PP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$_DFF_PN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFNP D Flip-Flop with Negative-Edge Clock and Asynchronous Preset
+module \$_DFF_NP1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$_DFF_NN1_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFC D Flip-Flop with Asynchronous Clear
+module \$_DFF_PP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$_DFF_PN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFNC D Flip-Flop with Negative-Edge Clock and Asynchronous Clear
+module \$_DFF_NP0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$_DFF_NN0_ #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, output Q);
+ DFFNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFPE D Flip-Flop with Clock Enable and Asynchronous Preset
+module \$__DFFE_PP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFE_PN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFNPE D Flip-Flop with Negative-Edge Clock,Clock Enable, and Asynchronous Preset
+module \$__DFFE_NP1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+module \$__DFFE_NN1 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNPE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .PRESET(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b0;
+endmodule
+
+// DFFCE D Flip-Flop with Clock Enable and Asynchronous Clear
+module \$__DFFE_PP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFE_PN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
+// DFFNCE D Flip-Flop with Negative-Edge Clock,Clock Enable and Asynchronous Clear
+module \$__DFFE_NP0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+module \$__DFFE_NN0 #(parameter _TECHMAP_WIREINIT_Q_ = 1'bx) (input D, C, R, E, output Q);
+ DFFNCE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(C), .CLEAR(!R), .CE(E));
+ wire _TECHMAP_REMOVEINIT_Q_ = _TECHMAP_WIREINIT_Q_ !== 1'b1;
+endmodule
+
module \$lut (A, Y);
- parameter WIDTH = 0;
- parameter LUT = 0;
-
- input [WIDTH-1:0] A;
- output Y;
-
- generate
- if (WIDTH == 1) begin
- LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]));
- end else
- if (WIDTH == 2) begin
- LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]), .I1(A[1]));
- end else
- if (WIDTH == 3) begin
- LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]));
- end else
- 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 begin
- wire _TECHMAP_FAIL_ = 1;
- end
- endgenerate
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]), .I1(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.F(Y),
+ .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ end else
+ 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
+ endgenerate
endmodule
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 947942626..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,6 +179,113 @@ module DFFN (output reg Q, input CLK, D);
Q <= D;
endmodule
+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;
endmodule
@@ -54,6 +302,219 @@ 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 (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;
+ parameter INIT_0 = 16'h0000;
+ parameter INIT_1 = 16'h0000;
+ parameter INIT_2 = 16'h0000;
+ parameter INIT_3 = 16'h0000;
+
+ input [WIDTH-1:0] AD;
+ input [WIDTH-1:0] DI;
+ output [WIDTH-1:0] DO;
+ input CLK;
+ input WRE;
+
+ reg [15:0] mem0, mem1, mem2, mem3;
+
+ initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+ end
+
+ assign DO[0] = mem0[AD];
+ assign DO[1] = mem1[AD];
+ assign DO[2] = mem2[AD];
+ assign DO[3] = mem3[AD];
+
+ always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ mem2[AD] <= DI[2];
+ mem3[AD] <= DI[3];
+ end
+ end
+
+endmodule // RAM16S4
+
+
+(* blackbox *)
+module SDP (DO, DI, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCE, RESETA, RESETB);
+//1'b0: Bypass mode; 1'b1 Pipeline mode
+parameter READ_MODE = 1'b0;
+parameter BIT_WIDTH_0 = 32; // 1, 2, 4, 8, 16, 32
+parameter BIT_WIDTH_1 = 32; // 1, 2, 4, 8, 16, 32
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+parameter INIT_RAM_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+
+input CLKA, CEA, CLKB, CEB;
+input OCE; // clock enable of memory output register
+input RESETA, RESETB; // resets output registers, not memory contents
+input WREA, WREB; // 1'b0: read enabled; 1'b1: write enabled
+input [13:0] ADA, ADB;
+input [31:0] DI;
+input [2:0] BLKSEL;
+output [31:0] DO;
+
+endmodule
+
diff --git a/techlibs/gowin/determine_init.cc b/techlibs/gowin/determine_init.cc
new file mode 100644
index 000000000..d9a0880f6
--- /dev/null
+++ b/techlibs/gowin/determine_init.cc
@@ -0,0 +1,72 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct DetermineInitPass : public Pass {
+ DetermineInitPass() : Pass("determine_init", "Determine the init value of cells") { }
+ void help() YS_OVERRIDE
+ {
+ log("\n");
+ log(" determine_init [selection]\n");
+ log("\n");
+ log("Determine the init value of cells that doesn't allow unknown init value.\n");
+ log("\n");
+ }
+
+ Const determine_init(Const init)
+ {
+ for (int i = 0; i < GetSize(init); i++) {
+ if (init[i] != State::S0 && init[i] != State::S1)
+ init[i] = State::S0;
+ }
+
+ return init;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing DETERMINE_INIT pass (determine init value for cells).\n");
+
+ extra_args(args, args.size(), design);
+
+ int cnt = 0;
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\RAM16S4")
+ {
+ cell->setParam("\\INIT_0", determine_init(cell->getParam("\\INIT_0")));
+ cell->setParam("\\INIT_1", determine_init(cell->getParam("\\INIT_1")));
+ cell->setParam("\\INIT_2", determine_init(cell->getParam("\\INIT_2")));
+ cell->setParam("\\INIT_3", determine_init(cell->getParam("\\INIT_3")));
+ cnt++;
+ }
+ }
+ }
+ log_header(design, "Updated %d cells with determined init value.\n", cnt);
+ }
+} DetermineInitPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/lutrams.txt b/techlibs/gowin/lutrams.txt
new file mode 100644
index 000000000..9db530251
--- /dev/null
+++ b/techlibs/gowin/lutrams.txt
@@ -0,0 +1,17 @@
+bram $__GW1NR_RAM16S4
+ init 1
+ abits 4
+ dbits 4
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 0 1
+ transp 0 1
+ clocks 0 1
+ clkpol 0 1
+endbram
+
+match $__GW1NR_RAM16S4
+ make_outreg
+ min wports 1
+endmatch
diff --git a/techlibs/gowin/lutrams_map.v b/techlibs/gowin/lutrams_map.v
new file mode 100644
index 000000000..a50ab365a
--- /dev/null
+++ b/techlibs/gowin/lutrams_map.v
@@ -0,0 +1,31 @@
+module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 4;
+ parameter CFG_DBITS = 4;
+
+ parameter [63:0] INIT = 64'bx;
+ input CLK1;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ `include "brams_init3.vh"
+
+ RAM16S4
+ #(.INIT_0(INIT_0),
+ .INIT_1(INIT_1),
+ .INIT_2(INIT_2),
+ .INIT_3(INIT_3))
+ _TECHMAP_REPLACE_
+ (.AD(B1ADDR),
+ .DI(B1DATA),
+ .DO(A1DATA),
+ .CLK(CLK1),
+ .WRE(B1EN));
+
+
+endmodule
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 44dec265d..c5b41b503 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -29,7 +29,7 @@ struct SynthGowinPass : public ScriptPass
{
SynthGowinPass() : ScriptPass("synth_gowin", "synthesis for Gowin FPGAs") { }
- virtual void help() YS_OVERRIDE
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -49,8 +49,29 @@ struct SynthGowinPass : public ScriptPass
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
+ log(" -nodffe\n");
+ log(" do not use flipflops with CE in output netlist\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use BRAM cells in output netlist\n");
+ log("\n");
+ log(" -nolutram\n");
+ log(" do not use distributed RAM cells in output netlist\n");
+ log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
log(" -retime\n");
- log(" run 'abc' with -dff option\n");
+ log(" run 'abc' with '-dff -D 1' options\n");
+ log("\n");
+ log(" -nowidelut\n");
+ log(" do not use muxes to implement LUTs larger than LUT4s\n");
+ log("\n");
+ log(" -noiopads\n");
+ log(" do not emit IOB at top level ports\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");
@@ -59,16 +80,23 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
- bool retime;
+ bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads;
- virtual void clear_flags() YS_OVERRIDE
+ void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vout_file = "";
retime = false;
+ flatten = true;
+ nobram = false;
+ nodffe = false;
+ nolutram = false;
+ nowidelut = false;
+ abc9 = false;
+ noiopads = false;
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
clear_flags();
@@ -96,12 +124,40 @@ struct SynthGowinPass : public ScriptPass
retime = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-nolutram" || /*deprecated*/args[argidx] == "-nodram") {
+ nolutram = true;
+ continue;
+ }
+ if (args[argidx] == "-nodffe") {
+ nodffe = true;
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-nowidelut") {
+ nowidelut = true;
+ continue;
+ }
+ //if (args[argidx] == "-abc9") {
+ // abc9 = true;
+ // continue;
+ //}
+ if (args[argidx] == "-noiopads") {
+ noiopads = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
- log_cmd_error("This comannd only operates on fully selected designs!\n");
+ log_cmd_error("This command only operates on fully selected designs!\n");
log_header(design, "Executing SYNTH_GOWIN pass.\n");
log_push();
@@ -111,7 +167,7 @@ struct SynthGowinPass : public ScriptPass
log_pop();
}
- virtual void script() YS_OVERRIDE
+ void script() YS_OVERRIDE
{
if (check_label("begin"))
{
@@ -119,7 +175,7 @@ struct SynthGowinPass : public ScriptPass
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
- if (check_label("flatten"))
+ if (flatten && check_label("flatten", "(unless -noflatten)"))
{
run("proc");
run("flatten");
@@ -132,31 +188,70 @@ struct SynthGowinPass : public ScriptPass
run("synth -run coarse");
}
- if (check_label("fine"))
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/gowin/brams.txt");
+ run("techmap -map +/gowin/brams_map.v -map +/gowin/cells_sim.v");
+ }
+
+ if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
+ {
+ run("memory_bram -rules +/gowin/lutrams.txt");
+ run("techmap -map +/gowin/lutrams_map.v");
+ run("determine_init");
+ }
+
+ if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
- run("techmap");
- run("clean -purge");
- run("splitnets -ports");
- run("setundef -undriven -zero");
+ }
+
+ if (check_label("map_gates"))
+ {
+ run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
+ run("techmap -map +/techmap.v");
if (retime || help_mode)
- run("abc -dff", "(only if -retime)");
+ run("abc -dff -D 1", "(only if -retime)");
+ run("splitnets");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("dff2dffs -match-init");
+ run("opt_clean");
+ if (!nodffe)
+ run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
+ run("techmap -map +/gowin/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
}
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 -inpad IBUF O:I -outpad OBUF I:O");
- run("clean -purge");
+ run("setundef -undriven -params -zero");
+ run("hilomap -singleton -hicell VCC V -locell GND G");
+ if (!noiopads || help_mode)
+ 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");
}
if (check_label("check"))
@@ -169,7 +264,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()));
}
}