diff options
Diffstat (limited to 'techlibs')
-rw-r--r-- | techlibs/coolrunner2/synth_coolrunner2.cc | 2 | ||||
-rw-r--r-- | techlibs/gowin/.gitignore | 2 | ||||
-rw-r--r-- | techlibs/gowin/Makefile.inc | 10 | ||||
-rw-r--r-- | techlibs/gowin/arith_map.v | 6 | ||||
-rw-r--r-- | techlibs/gowin/bram.txt | 10 | ||||
-rwxr-xr-x | techlibs/gowin/brams_init.py | 8 | ||||
-rw-r--r-- | techlibs/gowin/brams_map.v | 63 | ||||
-rw-r--r-- | techlibs/gowin/cells_map.v | 102 | ||||
-rw-r--r-- | techlibs/gowin/cells_sim.v | 349 | ||||
-rw-r--r-- | techlibs/gowin/synth_gowin.cc | 42 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 545 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.py | 14 | ||||
-rw-r--r-- | techlibs/xilinx/cells_xtra.v | 150 | ||||
-rw-r--r-- | techlibs/xilinx/lut_map.v | 8 |
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), |