From a3528649c82ed7c6d14850affef8e9368f4fe065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Tue, 23 Feb 2021 19:42:51 +0100 Subject: memory_dff: Remove now-useless write port handling. --- techlibs/common/prep.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc index 93b0910d6..132d6aec2 100644 --- a/techlibs/common/prep.cc +++ b/techlibs/common/prep.cc @@ -61,7 +61,7 @@ struct PrepPass : public ScriptPass log(" do not run any of the memory_* passes\n"); log("\n"); log(" -rdff\n"); - log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n"); + log(" call 'memory_dff'. This enables merging of FFs into\n"); log(" memory read ports.\n"); log("\n"); log(" -nokeepdc\n"); @@ -79,7 +79,7 @@ struct PrepPass : public ScriptPass } string top_module, fsm_opts; - bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff; + bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, rdff; void clear_flags() override { @@ -91,7 +91,7 @@ struct PrepPass : public ScriptPass memxmode = false; nomemmode = false; nokeepdc = false; - nordff = true; + rdff = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -137,11 +137,11 @@ struct PrepPass : public ScriptPass continue; } if (args[argidx] == "-nordff") { - nordff = true; + rdff = false; continue; } if (args[argidx] == "-rdff") { - nordff = false; + rdff = true; continue; } if (args[argidx] == "-nokeepdc") { @@ -202,7 +202,8 @@ struct PrepPass : public ScriptPass run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc"); } if (!nomemmode) { - run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : "")); + if (help_mode || rdff) + run("memory_dff", "(if -rdff)"); if (help_mode || memxmode) run("memory_memx", "(if -memx)"); run("opt_clean"); -- cgit v1.2.3 From 55dc5a4e4f7335741d2155dc0183ed4e26e8ddf8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 29 Mar 2021 22:01:57 -0700 Subject: abc9: fix SCC issues (#2694) * xilinx: add SCC test for DSP48E1 * xilinx: Gate DSP48E1 being a whitebox behind ALLOW_WHITEBOX_DSP48E1 Have a test that checks it works through ABC9 when enabled * abc9 to break SCCs using $__ABC9_SCC_BREAKER module * Add test * abc9_ops: remove refs to (* abc9_keep *) on wires * abc9_ops: do not bypass cells in an SCC * Add myself to CODEOWNERS for abc9* * Fix compile * abc9_ops: run -prep_hier before scc * Fix tests * Remove bug reference pending fix * abc9: fix for -prep_hier -dff * xaiger: restore PI handling * abc9_ops: -prep_xaiger sigmap * abc9_ops: -mark_scc -> -break_scc * abc9: eliminate hard-coded abc9.box from tests Also tidy up * Address review --- techlibs/common/abc9_model.v | 4 ++++ techlibs/common/abc9_unmap.v | 5 +++++ 2 files changed, 9 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v index 4fee60f75..570a1ec40 100644 --- a/techlibs/common/abc9_model.v +++ b/techlibs/common/abc9_model.v @@ -6,6 +6,10 @@ module $__ABC9_DELAY (input I, output O); endspecify endmodule +module $__ABC9_SCC_BREAKER (input [WIDTH-1:0] I, output [WIDTH-1:0] O); +parameter WIDTH = 0; +endmodule + (* abc9_flop, abc9_box, lib_whitebox *) module $__DFF_N__$abc9_flop (input C, D, Q, output n1); assign n1 = D; diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index c39648c62..b1bc4fb6e 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -9,3 +9,8 @@ module $__DFF_x__$abc9_flop (input C, D, (* init = 1'b0 *) input Q, output n1); $error("Unrecognised _TECHMAP_CELLTYPE_"); endgenerate endmodule + +module $__ABC9_SCC_BREAKER (input [WIDTH-1:0] I, output [WIDTH-1:0] O); +parameter WIDTH = 0; +assign O = I; +endmodule -- cgit v1.2.3 From 72787f52fc31954e4b7dc3dc34d86705fc4e9dd1 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Tue, 8 Jun 2021 00:39:36 +0200 Subject: Fixing old e-mail addresses and deadnames s/((Claire|Xen|Xenia|Clifford)\s+)+(Wolf|Xen)\s+<(claire|clifford)@(symbioticeda.com|clifford.at|yosyshq.com)>/Claire Xenia Wolf /gi; s/((Nina|Nak|N\.)\s+)+Engelhardt\s+/N. Engelhardt /gi; s/((David)\s+)+Shah\s+<(dave|david)@(symbioticeda.com|yosyshq.com|ds0.me)>/David Shah /gi; s/((Miodrag)\s+)+Milanovic\s+<(miodrag|micko)@(symbioticeda.com|yosyshq.com)>/Miodrag Milanovic /gi; s,https?://www.clifford.at/yosys/,http://yosyshq.net/yosys/,g; --- techlibs/common/mul2dsp.v | 4 ++-- techlibs/common/prep.cc | 2 +- techlibs/common/simcells.v | 2 +- techlibs/common/simlib.v | 2 +- techlibs/common/synth.cc | 2 +- techlibs/common/techmap.v | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index f22f47b4a..69d70b948 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -1,9 +1,9 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * 2019 Eddie Hung - * 2019 David Shah + * 2019 David Shah * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc index 132d6aec2..c354956bc 100644 --- a/techlibs/common/prep.cc +++ b/techlibs/common/prep.cc @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 27ef44232..7d9bebe2a 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 5c9efad27..42a355c2d 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 89d6e530e..79e5933e0 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 2ab28e6e6..d3dc85f24 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -1,7 +1,7 @@ /* * yosys -- Yosys Open SYnthesis Suite * - * Copyright (C) 2012 Clifford Wolf + * Copyright (C) 2012 Claire Xenia Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above -- cgit v1.2.3 From 92e705cb51d8c8f6d9f1550ed103b677a2447c93 Mon Sep 17 00:00:00 2001 From: Claire Xenia Wolf Date: Wed, 9 Jun 2021 12:16:33 +0200 Subject: Fix files with CRLF line endings --- techlibs/common/mul2dsp.v | 636 +++++++++++++++++++++++----------------------- 1 file changed, 318 insertions(+), 318 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v index 69d70b948..ca2b3c5cf 100644 --- a/techlibs/common/mul2dsp.v +++ b/techlibs/common/mul2dsp.v @@ -1,318 +1,318 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Claire Xenia Wolf - * 2019 Eddie Hung - * 2019 David Shah - * - * 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. - * - * --- - * - * Tech-mapping rules for decomposing arbitrarily-sized $mul cells - * into an equivalent collection of smaller `DSP_NAME cells (with the - * same interface as $mul) no larger than `DSP_[AB]_MAXWIDTH, attached - * to $shl and $add cells. - * - */ - -`ifndef DSP_A_MAXWIDTH -$fatal(1, "Macro DSP_A_MAXWIDTH must be defined"); -`endif -`ifndef DSP_B_MAXWIDTH -$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); -`endif -`ifndef DSP_B_MAXWIDTH -$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); -`endif -`ifndef DSP_A_MAXWIDTH_PARTIAL -`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH -`endif -`ifndef DSP_B_MAXWIDTH_PARTIAL -`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH -`endif - -`ifndef DSP_NAME -$fatal(1, "Macro DSP_NAME must be defined"); -`endif - -`define MAX(a,b) (a > b ? a : b) -`define MIN(a,b) (a < b ? a : b) - -(* techmap_celltype = "$mul $__mul" *) -module _80_mul (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - (* force_downto *) - input [A_WIDTH-1:0] A; - (* force_downto *) - input [B_WIDTH-1:0] B; - (* force_downto *) - output [Y_WIDTH-1:0] Y; - - parameter _TECHMAP_CELLTYPE_ = ""; - - generate - if (0) begin end -`ifdef DSP_A_MINWIDTH - else if (A_WIDTH < `DSP_A_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif -`ifdef DSP_B_MINWIDTH - else if (B_WIDTH < `DSP_B_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif -`ifdef DSP_Y_MINWIDTH - else if (Y_WIDTH < `DSP_Y_MINWIDTH) - wire _TECHMAP_FAIL_ = 1; -`endif -`ifdef DSP_SIGNEDONLY - else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED && !B_SIGNED) - \$mul #( - .A_SIGNED(1), - .B_SIGNED(1), - .A_WIDTH(A_WIDTH + 1), - .B_WIDTH(B_WIDTH + 1), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A({1'b0, A}), - .B({1'b0, B}), - .Y(Y) - ); -`endif - else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH) - \$mul #( - .A_SIGNED(B_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(B_WIDTH), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(B), - .B(A), - .Y(Y) - ); - else begin - wire [1023:0] _TECHMAP_DO_ = "proc; clean"; - -`ifdef DSP_SIGNEDONLY - localparam sign_headroom = 1; -`else - localparam sign_headroom = 0; -`endif - - genvar i; - if (A_WIDTH > `DSP_A_MAXWIDTH) begin - localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); - localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL); - localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); - localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH; - if (A_SIGNED && B_SIGNED) begin : blk - (* force_downto *) - wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) - wire signed [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) - wire signed [Y_WIDTH-1:0] partial_sum [n:0]; - end - else begin : blk - (* force_downto *) - wire [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) - wire [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) - wire [Y_WIDTH-1:0] partial_sum [n:0]; - end - - for (i = 0; i < n; i=i+1) begin:sliceA - \$__mul #( - .A_SIGNED(sign_headroom), - .B_SIGNED(B_SIGNED), - .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(partial_Y_WIDTH) - ) mul ( - .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}), - .B(B), - .Y(blk.partial[i]) - ); - // TODO: Currently a 'cascade' approach to summing the partial - // products is taken here, but a more efficient 'binary - // reduction' approach also exists... - if (i == 0) - assign blk.partial_sum[i] = blk.partial[i]; - else - assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1]; - end - - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(last_A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(last_Y_WIDTH) - ) sliceA.last ( - .A(A[A_WIDTH-1 -: last_A_WIDTH]), - .B(B), - .Y(blk.last_partial) - ); - assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1]; - assign Y = blk.partial_sum[n]; - end - else if (B_WIDTH > `DSP_B_MAXWIDTH) begin - localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); - localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL); - localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); - localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH; - if (A_SIGNED && B_SIGNED) begin : blk - (* force_downto *) - wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) - wire signed [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) - wire signed [Y_WIDTH-1:0] partial_sum [n:0]; - end - else begin : blk - (* force_downto *) - wire [partial_Y_WIDTH-1:0] partial [n-1:0]; - (* force_downto *) - wire [last_Y_WIDTH-1:0] last_partial; - (* force_downto *) - wire [Y_WIDTH-1:0] partial_sum [n:0]; - end - - for (i = 0; i < n; i=i+1) begin:sliceB - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(sign_headroom), - .A_WIDTH(A_WIDTH), - .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL), - .Y_WIDTH(partial_Y_WIDTH) - ) mul ( - .A(A), - .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}), - .Y(blk.partial[i]) - ); - // TODO: Currently a 'cascade' approach to summing the partial - // products is taken here, but a more efficient 'binary - // reduction' approach also exists... - if (i == 0) - assign blk.partial_sum[i] = blk.partial[i]; - else - assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1]; - end - - \$__mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(last_B_WIDTH), - .Y_WIDTH(last_Y_WIDTH) - ) mul_sliceB_last ( - .A(A), - .B(B[B_WIDTH-1 -: last_B_WIDTH]), - .Y(blk.last_partial) - ); - assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1]; - assign Y = blk.partial_sum[n]; - end - else begin - if (A_SIGNED) begin : blkA - wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); - end - else begin : blkA - wire [`DSP_A_MAXWIDTH-1:0] Aext = A; - end - if (B_SIGNED) begin : blkB - wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B); - end - else begin : blkB - wire [`DSP_B_MAXWIDTH-1:0] Bext = B; - end - - `DSP_NAME #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(`DSP_A_MAXWIDTH), - .B_WIDTH(`DSP_B_MAXWIDTH), - .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)), - ) _TECHMAP_REPLACE_ ( - .A(blkA.Aext), - .B(blkB.Bext), - .Y(Y) - ); - end - end - endgenerate -endmodule - -(* techmap_celltype = "$mul $__mul" *) -module _90_soft_mul (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - (* force_downto *) - input [A_WIDTH-1:0] A; - (* force_downto *) - input [B_WIDTH-1:0] B; - (* force_downto *) - output [Y_WIDTH-1:0] Y; - - // Indirection necessary since mapping - // back to $mul will cause recursion - generate - if (A_SIGNED && !B_SIGNED) - \$__soft_mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(1), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH+1), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B({1'b0,B}), - .Y(Y) - ); - else if (!A_SIGNED && B_SIGNED) - \$__soft_mul #( - .A_SIGNED(1), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH+1), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A({1'b0,A}), - .B(B), - .Y(Y) - ); - else - \$__soft_mul #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(A), - .B(B), - .Y(Y) - ); - endgenerate -endmodule +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2019 Eddie Hung + * 2019 gatecat + * + * 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. + * + * --- + * + * Tech-mapping rules for decomposing arbitrarily-sized $mul cells + * into an equivalent collection of smaller `DSP_NAME cells (with the + * same interface as $mul) no larger than `DSP_[AB]_MAXWIDTH, attached + * to $shl and $add cells. + * + */ + +`ifndef DSP_A_MAXWIDTH +$fatal(1, "Macro DSP_A_MAXWIDTH must be defined"); +`endif +`ifndef DSP_B_MAXWIDTH +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); +`endif +`ifndef DSP_B_MAXWIDTH +$fatal(1, "Macro DSP_B_MAXWIDTH must be defined"); +`endif +`ifndef DSP_A_MAXWIDTH_PARTIAL +`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH +`endif +`ifndef DSP_B_MAXWIDTH_PARTIAL +`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH +`endif + +`ifndef DSP_NAME +$fatal(1, "Macro DSP_NAME must be defined"); +`endif + +`define MAX(a,b) (a > b ? a : b) +`define MIN(a,b) (a < b ? a : b) + +(* techmap_celltype = "$mul $__mul" *) +module _80_mul (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] Y; + + parameter _TECHMAP_CELLTYPE_ = ""; + + generate + if (0) begin end +`ifdef DSP_A_MINWIDTH + else if (A_WIDTH < `DSP_A_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_B_MINWIDTH + else if (B_WIDTH < `DSP_B_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_Y_MINWIDTH + else if (Y_WIDTH < `DSP_Y_MINWIDTH) + wire _TECHMAP_FAIL_ = 1; +`endif +`ifdef DSP_SIGNEDONLY + else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED && !B_SIGNED) + \$mul #( + .A_SIGNED(1), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH + 1), + .B_WIDTH(B_WIDTH + 1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A({1'b0, A}), + .B({1'b0, B}), + .Y(Y) + ); +`endif + else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH) + \$mul #( + .A_SIGNED(B_SIGNED), + .B_SIGNED(A_SIGNED), + .A_WIDTH(B_WIDTH), + .B_WIDTH(A_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(B), + .B(A), + .Y(Y) + ); + else begin + wire [1023:0] _TECHMAP_DO_ = "proc; clean"; + +`ifdef DSP_SIGNEDONLY + localparam sign_headroom = 1; +`else + localparam sign_headroom = 0; +`endif + + genvar i; + if (A_WIDTH > `DSP_A_MAXWIDTH) begin + localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL); + localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom); + localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH; + if (A_SIGNED && B_SIGNED) begin : blk + (* force_downto *) + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) + wire signed [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) + wire signed [Y_WIDTH-1:0] partial_sum [n:0]; + end + else begin : blk + (* force_downto *) + wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) + wire [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) + wire [Y_WIDTH-1:0] partial_sum [n:0]; + end + + for (i = 0; i < n; i=i+1) begin:sliceA + \$__mul #( + .A_SIGNED(sign_headroom), + .B_SIGNED(B_SIGNED), + .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(partial_Y_WIDTH) + ) mul ( + .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}), + .B(B), + .Y(blk.partial[i]) + ); + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... + if (i == 0) + assign blk.partial_sum[i] = blk.partial[i]; + else + assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1]; + end + + \$__mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(last_A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(last_Y_WIDTH) + ) sliceA.last ( + .A(A[A_WIDTH-1 -: last_A_WIDTH]), + .B(B), + .Y(blk.last_partial) + ); + assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1]; + assign Y = blk.partial_sum[n]; + end + else if (B_WIDTH > `DSP_B_MAXWIDTH) begin + localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); + localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL); + localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom); + localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH; + if (A_SIGNED && B_SIGNED) begin : blk + (* force_downto *) + wire signed [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) + wire signed [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) + wire signed [Y_WIDTH-1:0] partial_sum [n:0]; + end + else begin : blk + (* force_downto *) + wire [partial_Y_WIDTH-1:0] partial [n-1:0]; + (* force_downto *) + wire [last_Y_WIDTH-1:0] last_partial; + (* force_downto *) + wire [Y_WIDTH-1:0] partial_sum [n:0]; + end + + for (i = 0; i < n; i=i+1) begin:sliceB + \$__mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(sign_headroom), + .A_WIDTH(A_WIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL), + .Y_WIDTH(partial_Y_WIDTH) + ) mul ( + .A(A), + .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}), + .Y(blk.partial[i]) + ); + // TODO: Currently a 'cascade' approach to summing the partial + // products is taken here, but a more efficient 'binary + // reduction' approach also exists... + if (i == 0) + assign blk.partial_sum[i] = blk.partial[i]; + else + assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1]; + end + + \$__mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(last_B_WIDTH), + .Y_WIDTH(last_Y_WIDTH) + ) mul_sliceB_last ( + .A(A), + .B(B[B_WIDTH-1 -: last_B_WIDTH]), + .Y(blk.last_partial) + ); + assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1]; + assign Y = blk.partial_sum[n]; + end + else begin + if (A_SIGNED) begin : blkA + wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A); + end + else begin : blkA + wire [`DSP_A_MAXWIDTH-1:0] Aext = A; + end + if (B_SIGNED) begin : blkB + wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B); + end + else begin : blkB + wire [`DSP_B_MAXWIDTH-1:0] Bext = B; + end + + `DSP_NAME #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(`DSP_A_MAXWIDTH), + .B_WIDTH(`DSP_B_MAXWIDTH), + .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)), + ) _TECHMAP_REPLACE_ ( + .A(blkA.Aext), + .B(blkB.Bext), + .Y(Y) + ); + end + end + endgenerate +endmodule + +(* techmap_celltype = "$mul $__mul" *) +module _90_soft_mul (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + (* force_downto *) + input [A_WIDTH-1:0] A; + (* force_downto *) + input [B_WIDTH-1:0] B; + (* force_downto *) + output [Y_WIDTH-1:0] Y; + + // Indirection necessary since mapping + // back to $mul will cause recursion + generate + if (A_SIGNED && !B_SIGNED) + \$__soft_mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(1), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH+1), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B({1'b0,B}), + .Y(Y) + ); + else if (!A_SIGNED && B_SIGNED) + \$__soft_mul #( + .A_SIGNED(1), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH+1), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A({1'b0,A}), + .B(B), + .Y(Y) + ); + else + \$__soft_mul #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(A), + .B(B), + .Y(Y) + ); + endgenerate +endmodule -- cgit v1.2.3 From 19720b970dff017c47805e37745b9fcf29843c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Fri, 21 May 2021 02:26:52 +0200 Subject: memory: Introduce $meminit_v2 cell, with EN input. --- techlibs/common/simlib.v | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 42a355c2d..ad654c8a4 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -2233,6 +2233,30 @@ endmodule // -------------------------------------------------------- +module \$meminit_v2 (ADDR, DATA, EN); + +parameter MEMID = ""; +parameter ABITS = 8; +parameter WIDTH = 8; +parameter WORDS = 1; + +parameter PRIORITY = 0; + +input [ABITS-1:0] ADDR; +input [WORDS*WIDTH-1:0] DATA; +input [WIDTH-1:0] EN; + +initial begin + if (MEMID != "") begin + $display("ERROR: Found non-simulatable instance of $meminit_v2!"); + $finish; + end +end + +endmodule + +// -------------------------------------------------------- + module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); parameter MEMID = ""; -- cgit v1.2.3 From fd7921776387a05edadcc90d1300670d49a73d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Thu, 27 May 2021 20:54:29 +0200 Subject: Add v2 memory cells. --- techlibs/common/simlib.v | 169 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index ad654c8a4..cf0839ebe 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -2182,6 +2182,34 @@ end endmodule +module \$memrd_v2 (CLK, EN, ARST, SRST, ADDR, DATA); + +parameter MEMID = ""; +parameter ABITS = 8; +parameter WIDTH = 8; + +parameter CLK_ENABLE = 0; +parameter CLK_POLARITY = 0; +parameter TRANSPARENCY_MASK = 0; +parameter COLLISION_X_MASK = 0; +parameter ARST_VALUE = 0; +parameter SRST_VALUE = 0; +parameter INIT_VALUE = 0; +parameter CE_OVER_SRST = 0; + +input CLK, EN, ARST, SRST; +input [ABITS-1:0] ADDR; +output [WIDTH-1:0] DATA; + +initial begin + if (MEMID != "") begin + $display("ERROR: Found non-simulatable instance of $memrd_v2!"); + $finish; + end +end + +endmodule + // -------------------------------------------------------- module \$memwr (CLK, EN, ADDR, DATA); @@ -2208,6 +2236,31 @@ end endmodule +module \$memwr_v2 (CLK, EN, ADDR, DATA); + +parameter MEMID = ""; +parameter ABITS = 8; +parameter WIDTH = 8; + +parameter CLK_ENABLE = 0; +parameter CLK_POLARITY = 0; +parameter PORTID = 0; +parameter PRIORITY_MASK = 0; + +input CLK; +input [WIDTH-1:0] EN; +input [ABITS-1:0] ADDR; +input [WIDTH-1:0] DATA; + +initial begin + if (MEMID != "") begin + $display("ERROR: Found non-simulatable instance of $memwr_v2!"); + $finish; + end +end + +endmodule + // -------------------------------------------------------- module \$meminit (ADDR, DATA); @@ -2344,6 +2397,122 @@ end endmodule +module \$mem_v2 (RD_CLK, RD_EN, RD_ARST, RD_SRST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); + +parameter MEMID = ""; +parameter signed SIZE = 4; +parameter signed OFFSET = 0; +parameter signed ABITS = 2; +parameter signed WIDTH = 8; +parameter signed INIT = 1'bx; + +parameter signed RD_PORTS = 1; +parameter RD_CLK_ENABLE = 1'b1; +parameter RD_CLK_POLARITY = 1'b1; +parameter RD_TRANSPARENCY_MASK = 1'b0; +parameter RD_COLLISION_X_MASK = 1'b0; +parameter RD_WIDE_CONTINUATION = 1'b0; +parameter RD_CE_OVER_SRST = 1'b0; +parameter RD_ARST_VALUE = 1'b0; +parameter RD_SRST_VALUE = 1'b0; +parameter RD_INIT_VALUE = 1'b0; + +parameter signed WR_PORTS = 1; +parameter WR_CLK_ENABLE = 1'b1; +parameter WR_CLK_POLARITY = 1'b1; +parameter WR_PRIORITY_MASK = 1'b0; +parameter WR_WIDE_CONTINUATION = 1'b0; + +input [RD_PORTS-1:0] RD_CLK; +input [RD_PORTS-1:0] RD_EN; +input [RD_PORTS-1:0] RD_ARST; +input [RD_PORTS-1:0] RD_SRST; +input [RD_PORTS*ABITS-1:0] RD_ADDR; +output reg [RD_PORTS*WIDTH-1:0] RD_DATA; + +input [WR_PORTS-1:0] WR_CLK; +input [WR_PORTS*WIDTH-1:0] WR_EN; +input [WR_PORTS*ABITS-1:0] WR_ADDR; +input [WR_PORTS*WIDTH-1:0] WR_DATA; + +reg [WIDTH-1:0] memory [SIZE-1:0]; + +integer i, j, k; +reg [WR_PORTS-1:0] LAST_WR_CLK; +reg [RD_PORTS-1:0] LAST_RD_CLK; + +function port_active; + input clk_enable; + input clk_polarity; + input last_clk; + input this_clk; + begin + casez ({clk_enable, clk_polarity, last_clk, this_clk}) + 4'b0???: port_active = 1; + 4'b1101: port_active = 1; + 4'b1010: port_active = 1; + default: port_active = 0; + endcase + end +endfunction + +initial begin + for (i = 0; i < SIZE; i = i+1) + memory[i] = INIT >>> (i*WIDTH); + RD_DATA = RD_INIT_VALUE; +end + +always @(RD_CLK, RD_ARST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin +`ifdef SIMLIB_MEMDELAY + #`SIMLIB_MEMDELAY; +`endif + for (i = 0; i < RD_PORTS; i = i+1) begin + if (RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin + // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); + RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; + + for (j = 0; j < WR_PORTS; j = j+1) begin + if (RD_TRANSPARENCY_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS]) + for (k = 0; k < WIDTH; k = k+1) + if (WR_EN[j*WIDTH+k]) + RD_DATA[i*WIDTH+k] <= WR_DATA[j*WIDTH+k]; + if (RD_COLLISION_X_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS]) + for (k = 0; k < WIDTH; k = k+1) + if (WR_EN[j*WIDTH+k]) + RD_DATA[i*WIDTH+k] <= 1'bx; + end + end + end + + for (i = 0; i < WR_PORTS; i = i+1) begin + if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i])) + for (j = 0; j < WIDTH; j = j+1) + if (WR_EN[i*WIDTH+j]) begin + // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]); + memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j]; + end + end + + for (i = 0; i < RD_PORTS; i = i+1) begin + if (!RD_CLK_ENABLE[i]) begin + // $display("Combinatorial read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); + RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; + end + end + + for (i = 0; i < RD_PORTS; i = i+1) begin + if (RD_SRST[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]) && (RD_EN[i] || !RD_CE_OVER_SRST[i])) + RD_DATA[i*WIDTH +: WIDTH] <= RD_SRST_VALUE[i*WIDTH +: WIDTH]; + if (RD_ARST[i]) + RD_DATA[i*WIDTH +: WIDTH] <= RD_ARST_VALUE[i*WIDTH +: WIDTH]; + end + + LAST_RD_CLK <= RD_CLK; + LAST_WR_CLK <= WR_CLK; +end + +endmodule + `endif // -------------------------------------------------------- -- cgit v1.2.3 From ec2b5548fe9b8d291365a84a0c3fc87654643359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Fri, 1 Oct 2021 04:33:00 +0200 Subject: Add $aldff and $aldffe: flip-flops with async load. --- techlibs/common/gen_fine_ffs.py | 49 +++++++ techlibs/common/simcells.v | 284 ++++++++++++++++++++++++++++++++++++++++ techlibs/common/simlib.v | 49 +++++++ 3 files changed, 382 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py index 5d331e767..25c6ef171 100644 --- a/techlibs/common/gen_fine_ffs.py +++ b/techlibs/common/gen_fine_ffs.py @@ -133,6 +133,55 @@ endmodule """ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- +//- $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q) +//- +//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - {L:0|1} a | a +//- d {C:\\|/} - - | d +//- - - - - | q +//- +module \$_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin + if (L == {L:0|1}) + Q <= AD; + else + Q <= D; +end +endmodule +""", +""" +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q) +//- +//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive} +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - {L:0|1} a - | a +//- d {C:\\|/} - - {E:0|1} | d +//- - - - - - | q +//- +module \$_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin + if (L == {L:0|1}) + Q <= AD; + else if (E == {E:0|1}) + Q <= D; +end +endmodule +""", +""" +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- //- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q) //- //- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive} diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 7d9bebe2a..ad1fdc817 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -1252,6 +1252,290 @@ always @(posedge C or posedge R) begin end endmodule +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_NN_ (D, C, L, AD, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 0 a | a +//- d \ - - | d +//- - - - - | q +//- +module \$_ALDFF_NN_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_NP_ (D, C, L, AD, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 1 a | a +//- d \ - - | d +//- - - - - | q +//- +module \$_ALDFF_NP_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_PN_ (D, C, L, AD, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 0 a | a +//- d / - - | d +//- - - - - | q +//- +module \$_ALDFF_PN_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFF_PP_ (D, C, L, AD, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load. +//- +//- Truth table: D C L AD | Q +//- ----------+--- +//- - - 1 a | a +//- d / - - | d +//- - - - - | q +//- +module \$_ALDFF_PP_ (D, C, L, AD, Q); +input D, C, L, AD; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NNN_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d \ - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_NNN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NNP_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with negative polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d \ - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_NNP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NPN_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d \ - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_NPN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_NPP_ (D, C, L, AD, E, Q) +//- +//- A negative edge D-type flip-flop with positive polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d \ - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_NPP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(negedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PNN_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d / - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_PNN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PNP_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with negative polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 0 a - | a +//- d / - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_PNP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or negedge L) begin + if (L == 0) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PPN_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load and negative +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d / - - 0 | d +//- - - - - - | q +//- +module \$_ALDFFE_PPN_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 0) + Q <= D; +end +endmodule + +// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +//- +//- $_ALDFFE_PPP_ (D, C, L, AD, E, Q) +//- +//- A positive edge D-type flip-flop with positive polarity async load and positive +//- polarity clock enable. +//- +//- Truth table: D C L AD E | Q +//- ------------+--- +//- - - 1 a - | a +//- d / - - 1 | d +//- - - - - - | q +//- +module \$_ALDFFE_PPP_ (D, C, L, AD, E, Q); +input D, C, L, AD, E; +output reg Q; +always @(posedge C or posedge L) begin + if (L == 1) + Q <= AD; + else if (E == 1) + Q <= D; +end +endmodule + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| //- //- $_DFFSR_NNN_ (C, S, R, D, Q) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index cf0839ebe..e9129f690 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1890,6 +1890,30 @@ endmodule // -------------------------------------------------------- +module \$aldff (CLK, ALOAD, AD, D, Q); + +parameter WIDTH = 0; +parameter CLK_POLARITY = 1'b1; +parameter ALOAD_POLARITY = 1'b1; + +input CLK, ALOAD; +input [WIDTH-1:0] AD; +input [WIDTH-1:0] D; +output reg [WIDTH-1:0] Q; +wire pos_clk = CLK == CLK_POLARITY; +wire pos_aload = ALOAD == ALOAD_POLARITY; + +always @(posedge pos_clk, posedge pos_aload) begin + if (pos_aload) + Q <= AD; + else + Q <= D; +end + +endmodule + +// -------------------------------------------------------- + module \$sdff (CLK, SRST, D, Q); parameter WIDTH = 0; @@ -1939,6 +1963,31 @@ endmodule // -------------------------------------------------------- +module \$aldffe (CLK, ALOAD, AD, EN, D, Q); + +parameter WIDTH = 0; +parameter CLK_POLARITY = 1'b1; +parameter EN_POLARITY = 1'b1; +parameter ALOAD_POLARITY = 1'b1; + +input CLK, ALOAD, EN; +input [WIDTH-1:0] D; +input [WIDTH-1:0] AD; +output reg [WIDTH-1:0] Q; +wire pos_clk = CLK == CLK_POLARITY; +wire pos_aload = ALOAD == ALOAD_POLARITY; + +always @(posedge pos_clk, posedge pos_aload) begin + if (pos_aload) + Q <= AD; + else if (EN == EN_POLARITY) + Q <= D; +end + +endmodule + +// -------------------------------------------------------- + module \$sdffe (CLK, SRST, EN, D, Q); parameter WIDTH = 0; -- cgit v1.2.3 From e7d89e653c9d295d3cc9547b83660658e4d1c95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Sat, 2 Oct 2021 01:23:43 +0200 Subject: Hook up $aldff support in various passes. --- techlibs/common/techmap.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index d3dc85f24..667773e1b 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -64,7 +64,7 @@ module _90_simplemap_various; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *) +(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $aldff $aldffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *) module _90_simplemap_registers; endmodule -- cgit v1.2.3 From 93508d58dafbbffcedffa70b21a197b6fca8bb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Mon, 24 Jan 2022 16:02:29 +0100 Subject: Add $bmux and $demux cells. --- techlibs/common/simlib.v | 72 ++++++++++++++++++++++++++++++++--------------- techlibs/common/techmap.v | 39 ++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 24 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index e9129f690..b14488ff4 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1292,6 +1292,33 @@ endmodule // -------------------------------------------------------- +module \$bmux (A, S, Y); + +parameter WIDTH = 0; +parameter S_WIDTH = 0; + +input [(WIDTH << S_WIDTH)-1:0] A; +input [S_WIDTH-1:0] S; +output [WIDTH-1:0] Y; + +wire [WIDTH-1:0] bm0_out, bm1_out; + +generate + if (S_WIDTH > 1) begin:muxlogic + \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm0 (.A(A), .S(S[S_WIDTH-2:0]), .Y(bm0_out)); + \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm1 (.A(A[(WIDTH << S_WIDTH)-1:WIDTH << (S_WIDTH - 1)]), .S(S[S_WIDTH-2:0]), .Y(bm1_out)); + assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out; + end else if (S_WIDTH == 1) begin:simple + assign Y = S ? A[1] : A[0]; + end else begin:passthru + assign Y = A; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + module \$pmux (A, B, S, Y); parameter WIDTH = 0; @@ -1317,6 +1344,26 @@ end endmodule +// -------------------------------------------------------- + +module \$demux (A, S, Y); + +parameter WIDTH = 1; +parameter S_WIDTH = 1; + +input [WIDTH-1:0] A; +input [S_WIDTH-1:0] S; +output [(WIDTH << S_WIDTH)-1:0] Y; + +genvar i; +generate + for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices + assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0; + end +endgenerate + +endmodule + // -------------------------------------------------------- `ifndef SIMLIB_NOLUT @@ -1326,30 +1373,9 @@ parameter WIDTH = 0; parameter LUT = 0; input [WIDTH-1:0] A; -output reg Y; - -wire lut0_out, lut1_out; +output Y; -generate - if (WIDTH <= 1) begin:simple - assign {lut1_out, lut0_out} = LUT; - end else begin:complex - \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) ); - \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) ); - end - - if (WIDTH > 0) begin:lutlogic - always @* begin - casez ({A[WIDTH-1], lut0_out, lut1_out}) - 3'b?11: Y = 1'b1; - 3'b?00: Y = 1'b0; - 3'b0??: Y = lut0_out; - 3'b1??: Y = lut1_out; - default: Y = 1'bx; - endcase - end - end -endgenerate +\$bmux #(.WIDTH(1), .S_WIDTH(WIDTH)) mux(.A(LUT), .S(A), .Y(Y)); endmodule diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 667773e1b..91d385b80 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -59,7 +59,7 @@ module _90_simplemap_compare_ops; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$pos $slice $concat $mux $tribuf" *) +(* techmap_celltype = "$pos $slice $concat $mux $tribuf $bmux" *) module _90_simplemap_various; endmodule @@ -597,6 +597,43 @@ module _90_pmux (A, B, S, Y); assign Y = |S ? Y_B : A; endmodule +// -------------------------------------------------------- +// Demultiplexers +// -------------------------------------------------------- + +(* techmap_celltype = "$demux" *) +module _90_demux (A, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + (* force_downto *) + input [WIDTH-1:0] A; + (* force_downto *) + input [S_WIDTH-1:0] S; + (* force_downto *) + output [(WIDTH << S_WIDTH)-1:0] Y; + + generate + if (S_WIDTH == 0) begin + assign Y = A; + end else if (S_WIDTH == 1) begin + assign Y[0+:WIDTH] = S ? 0 : A; + assign Y[WIDTH+:WIDTH] = S ? A : 0; + end else begin + localparam SPLIT = S_WIDTH / 2; + wire [(1 << (S_WIDTH-SPLIT))-1:0] YH; + wire [(1 << SPLIT)-1:0] YL; + $demux #(.WIDTH(1), .S_WIDTH(SPLIT)) lo (.A(1'b1), .S(S[SPLIT-1:0]), .Y(YL)); + $demux #(.WIDTH(1), .S_WIDTH(S_WIDTH-SPLIT)) hi (.A(1'b1), .S(S[S_WIDTH-1:SPLIT]), .Y(YH)); + genvar i; + for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin + localparam [S_WIDTH-1:0] IDX = i; + assign Y[i*WIDTH+:WIDTH] = (YL[IDX[SPLIT-1:0]] & YH[IDX[S_WIDTH-1:SPLIT]]) ? A : 0; + end + end + endgenerate +endmodule + // -------------------------------------------------------- // LUTs -- cgit v1.2.3