From d7f29bb23f9bb2c74e02bc1221bcf27efc7ee4dc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Mar 2014 11:54:22 +0100 Subject: Improved techmap of shift with wide B inputs --- techlibs/common/stdcells.v | 50 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index fdee26b6f..a51dcb944 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -165,6 +165,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; parameter WIDTH = Y_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -181,11 +182,16 @@ generate .A(A), .Y(chain[WIDTH-1:0]) ); - assign Y = chain[WIDTH*(B_WIDTH+1)-1 : WIDTH*B_WIDTH]; - for (i = 0; i < B_WIDTH; i = i + 1) begin:V + assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; + for (i = 0; i < BB_WIDTH; i = i + 1) begin:V wire [WIDTH-1:0] unshifted, shifted, result; assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; + wire BBIT; + if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) + assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; + else + assign BBIT = B[i]; \$__shift #( .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) @@ -200,7 +206,7 @@ generate .A(unshifted), .B(shifted), .Y(result), - .S(B[i]) + .S(BBIT) ); end endgenerate @@ -218,6 +224,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -225,7 +232,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate - wire [WIDTH*(B_WIDTH+1)-1:0] chain; + wire [WIDTH*(BB_WIDTH+1)-1:0] chain; \$pos #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), @@ -234,11 +241,16 @@ generate .A(A), .Y(chain[WIDTH-1:0]) ); - assign Y = chain[WIDTH*(B_WIDTH+1)-1 : WIDTH*B_WIDTH]; - for (i = 0; i < B_WIDTH; i = i + 1) begin:V + assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; + for (i = 0; i < BB_WIDTH; i = i + 1) begin:V wire [WIDTH-1:0] unshifted, shifted, result; assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; + wire BBIT; + if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) + assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; + else + assign BBIT = B[i]; \$__shift #( .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) @@ -253,7 +265,7 @@ generate .A(unshifted), .B(shifted), .Y(result), - .S(B[i]) + .S(BBIT) ); end endgenerate @@ -271,6 +283,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = Y_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -292,6 +305,11 @@ generate wire [WIDTH-1:0] unshifted, shifted, result; assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; + wire BBIT; + if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) + assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; + else + assign BBIT = B[i]; \$__shift #( .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) @@ -306,7 +324,7 @@ generate .A(unshifted), .B(shifted), .Y(result), - .S(B[i]) + .S(BBIT) ); end endgenerate @@ -324,6 +342,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -331,7 +350,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate - wire [WIDTH*(B_WIDTH+1)-1:0] chain; + wire [WIDTH*(BB_WIDTH+1)-1:0] chain; \$pos #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), @@ -342,18 +361,23 @@ generate ); for (i = 0; i < Y_WIDTH; i = i + 1) begin:Y if (i < WIDTH) begin - assign Y[i] = chain[WIDTH*B_WIDTH + i]; + assign Y[i] = chain[WIDTH*BB_WIDTH + i]; end else if (A_SIGNED) begin - assign Y[i] = chain[WIDTH*B_WIDTH + WIDTH-1]; + assign Y[i] = chain[WIDTH*BB_WIDTH + WIDTH-1]; end else begin assign Y[i] = 0; end end - for (i = 0; i < B_WIDTH; i = i + 1) begin:V + for (i = 0; i < BB_WIDTH; i = i + 1) begin:V wire [WIDTH-1:0] unshifted, shifted, result; assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; + wire BBIT; + if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) + assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; + else + assign BBIT = B[i]; \$__shift #( .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) @@ -368,7 +392,7 @@ generate .A(unshifted), .B(shifted), .Y(result), - .S(B[i]) + .S(BBIT) ); end endgenerate -- cgit v1.2.3 From 8406e7f7b6cb8e79f7df02c2c616073a51c1ea9e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Mar 2014 12:15:44 +0100 Subject: Strictly zero-extend unsigned A-inputs of shift operations in techmap --- techlibs/common/stdcells.v | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index a51dcb944..cddaf4c6f 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -174,7 +174,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate wire [WIDTH*(B_WIDTH+1)-1:0] chain; - \$pos #( + \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH) @@ -233,7 +233,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$pos #( + \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH) @@ -292,7 +292,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate wire [WIDTH*(B_WIDTH+1)-1:0] chain; - \$pos #( + \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH) @@ -351,7 +351,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$pos #( + \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH) -- cgit v1.2.3 From 973507d85b0a20118f6a56ec787d44d6b574d3a6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Mar 2014 13:22:10 +0100 Subject: Fixes for improved techmap of shifts with large B inputs --- techlibs/common/stdcells.v | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index cddaf4c6f..a05ea2786 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -165,7 +165,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; parameter WIDTH = Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -173,7 +173,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate - wire [WIDTH*(B_WIDTH+1)-1:0] chain; + wire [WIDTH*(BB_WIDTH+1)-1:0] chain; \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), @@ -224,7 +224,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -283,7 +283,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; @@ -291,7 +291,7 @@ output [Y_WIDTH-1:0] Y; genvar i; generate - wire [WIDTH*(B_WIDTH+1)-1:0] chain; + wire [WIDTH*(BB_WIDTH+1)-1:0] chain; \$bu0 #( .A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), @@ -300,8 +300,8 @@ generate .A(A), .Y(chain[WIDTH-1:0]) ); - assign Y = chain[WIDTH*(B_WIDTH+1)-1 : WIDTH*B_WIDTH]; - for (i = 0; i < B_WIDTH; i = i + 1) begin:V + assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; + for (i = 0; i < BB_WIDTH; i = i + 1) begin:V wire [WIDTH-1:0] unshifted, shifted, result; assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; @@ -342,7 +342,7 @@ parameter B_WIDTH = 1; parameter Y_WIDTH = 1; localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 1 < B_WIDTH ? $clog2(WIDTH) + 1 : B_WIDTH; +localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; -- cgit v1.2.3 From 7aa2d746b76a354daedd4c8a7b4d8c15b1805b21 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 11 Mar 2014 14:42:58 +0100 Subject: Merged addition of SED makefile variable from github.com/Siesh1oo/yosys (see https://github.com/cliffordwolf/yosys/pull/28) --- techlibs/common/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 6d94d5c9b..c68b13f6c 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -2,7 +2,7 @@ EXTRA_TARGETS += techlibs/common/blackbox.v techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib.v techlibs/common/simcells.v - cat techlibs/common/simlib.v techlibs/common/simcells.v | sed -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new + cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v EXTRA_TARGETS += share/simlib.v share/simcells.v share/blackbox.v share/pmux2mux.v -- cgit v1.2.3 From d4a1b0af5b41d1360c74a73fb2ae92ee5f6c3bd0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 31 Mar 2014 14:14:40 +0200 Subject: Added support for dlatchsr cells --- techlibs/common/simcells.v | 104 +++++++++++++++++++++++++++++++++++++++++++++ techlibs/common/simlib.v | 32 ++++++++++++++ 2 files changed, 136 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 10a809db6..5ecec7891 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -325,3 +325,107 @@ always @* begin end endmodule +module \$_DLATCHSR_NNN_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 0) + Q <= 0; + else if (S == 0) + Q <= 1; + else if (E == 0) + Q <= D; +end +endmodule + +module \$_DLATCHSR_NNP_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 1) + Q <= 0; + else if (S == 0) + Q <= 1; + else if (E == 0) + Q <= D; +end +endmodule + +module \$_DLATCHSR_NPN_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 0) + Q <= 0; + else if (S == 1) + Q <= 1; + else if (E == 0) + Q <= D; +end +endmodule + +module \$_DLATCHSR_NPP_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 1) + Q <= 0; + else if (S == 1) + Q <= 1; + else if (E == 0) + Q <= D; +end +endmodule + +module \$_DLATCHSR_PNN_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 0) + Q <= 0; + else if (S == 0) + Q <= 1; + else if (E == 1) + Q <= D; +end +endmodule + +module \$_DLATCHSR_PNP_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 1) + Q <= 0; + else if (S == 0) + Q <= 1; + else if (E == 1) + Q <= D; +end +endmodule + +module \$_DLATCHSR_PPN_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 0) + Q <= 0; + else if (S == 1) + Q <= 1; + else if (E == 1) + Q <= D; +end +endmodule + +module \$_DLATCHSR_PPP_ (E, S, R, D, Q); +input E, S, R, D; +output reg Q; +always @* begin + if (R == 1) + Q <= 0; + else if (S == 1) + Q <= 1; + else if (E == 1) + Q <= D; +end +endmodule + diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 4436abfe7..908314f84 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1097,6 +1097,38 @@ endmodule // -------------------------------------------------------- +module \$dlatchsr (EN, SET, CLR, D, Q); + +parameter WIDTH = 0; +parameter EN_POLARITY = 1'b1; +parameter SET_POLARITY = 1'b1; +parameter CLR_POLARITY = 1'b1; + +input EN; +input [WIDTH-1:0] SET, CLR, D; +output reg [WIDTH-1:0] Q; + +wire pos_en = EN == EN_POLARITY; +wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; +wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; + +genvar i; +generate + for (i = 0; i < WIDTH; i = i+1) begin:bit + always @* + if (pos_clr[i]) + Q[i] <= 0; + else if (pos_set[i]) + Q[i] <= 1; + else if (pos_en) + Q[i] <= D[i]; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); parameter NAME = ""; -- cgit v1.2.3 From e24797add0ceb0e8c3571cec9351a2b0120e9b19 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 2 Apr 2014 21:06:55 +0200 Subject: Added SIMLIB_NOSR to simlib.v --- techlibs/common/simlib.v | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 908314f84..16e6a1b21 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -977,6 +977,7 @@ end endmodule // -------------------------------------------------------- +`ifndef SIMLIB_NOSR module \$sr (SET, CLR, Q); @@ -1003,6 +1004,7 @@ endgenerate endmodule +`endif // -------------------------------------------------------- module \$dff (CLK, D, Q); @@ -1022,6 +1024,7 @@ end endmodule // -------------------------------------------------------- +`ifndef SIMLIB_NOSR module \$dffsr (CLK, SET, CLR, D, Q); @@ -1053,6 +1056,7 @@ endgenerate endmodule +`endif // -------------------------------------------------------- module \$adff (CLK, ARST, D, Q); @@ -1096,6 +1100,7 @@ end endmodule // -------------------------------------------------------- +`ifndef SIMLIB_NOSR module \$dlatchsr (EN, SET, CLR, D, Q); @@ -1127,6 +1132,7 @@ endgenerate endmodule +`endif // -------------------------------------------------------- module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); -- cgit v1.2.3 From 7370ae01e978f0552f1565b88c0f44b402d09f4e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 2 Apr 2014 21:28:33 +0200 Subject: Added SIMLIB_NOLUT to simlib.v --- techlibs/common/simlib.v | 2 ++ 1 file changed, 2 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 16e6a1b21..be9d24f18 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -927,6 +927,7 @@ end endmodule // -------------------------------------------------------- +`ifndef SIMLIB_NOLUT module \$lut (I, O); @@ -961,6 +962,7 @@ endgenerate endmodule +`endif // -------------------------------------------------------- module \$assert (A, EN); -- cgit v1.2.3 From dcdd5c11b4ebbf983f3ab7fc5304d980cc47302d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 16 Jul 2014 11:46:40 +0200 Subject: Updated simlib to new $mem/$memwr interface --- techlibs/common/simlib.v | 85 +++++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 30 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index be9d24f18..9c774deac 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1264,7 +1264,8 @@ parameter WIDTH = 8; parameter CLK_ENABLE = 0; parameter CLK_POLARITY = 0; -input CLK, EN; +input CLK; +input [WIDTH-1:0] EN; input [ABITS-1:0] ADDR; input [WIDTH-1:0] DATA; @@ -1300,7 +1301,8 @@ input [RD_PORTS-1:0] RD_CLK; input [RD_PORTS*ABITS-1:0] RD_ADDR; output reg [RD_PORTS*WIDTH-1:0] RD_DATA; -input [WR_PORTS-1:0] WR_CLK, WR_EN; +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; @@ -1338,46 +1340,69 @@ generate end for (i = 0; i < WR_PORTS; i = i+1) begin:wr - integer k; - reg found_collision; + integer k, n; + reg found_collision, run_update; if (WR_CLK_ENABLE[i] == 0) begin:wr_noclk always @(WR_ADDR or WR_DATA or WR_EN) begin - if (WR_EN[i]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) - found_collision = 1; - if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ] <= WR_DATA[ i*WIDTH +: WIDTH ]; - update_async_rd <= 1; update_async_rd <= 0; + run_update = 0; + for (n = 0; n < WIDTH; n = n+1) begin + if (WR_EN[i][n]) begin + found_collision = 0; + for (k = i+1; k < WR_PORTS; k = k+1) + if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + found_collision = 1; + if (!found_collision) begin + data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + run_update = 1; + end end end + if (run_update) begin + update_async_rd <= 1; + update_async_rd <= 0; + end end end else if (WR_CLK_POLARITY[i] == 1) begin:rd_posclk - always @(posedge WR_CLK[i]) - if (WR_EN[i]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) - found_collision = 1; - if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ] <= WR_DATA[ i*WIDTH +: WIDTH ]; - update_async_rd <= 1; update_async_rd <= 0; + always @(posedge WR_CLK[i]) begin + run_update = 0; + for (n = 0; n < WIDTH; n = n+1) begin + if (WR_EN[i][n]) begin + found_collision = 0; + for (k = i+1; k < WR_PORTS; k = k+1) + if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + found_collision = 1; + if (!found_collision) begin + data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + run_update = 1; + end end end + if (run_update) begin + update_async_rd <= 1; + update_async_rd <= 0; + end + end end else begin:rd_negclk - always @(negedge WR_CLK[i]) - if (WR_EN[i]) begin - found_collision = 0; - for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) - found_collision = 1; - if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ] <= WR_DATA[ i*WIDTH +: WIDTH ]; - update_async_rd <= 1; update_async_rd <= 0; + always @(negedge WR_CLK[i]) begin + run_update = 0; + for (n = 0; n < WIDTH; n = n+1) begin + if (WR_EN[i][n]) begin + found_collision = 0; + for (k = i+1; k < WR_PORTS; k = k+1) + if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + found_collision = 1; + if (!found_collision) begin + data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + run_update = 1; + end end end + if (run_update) begin + update_async_rd <= 1; + update_async_rd <= 0; + end + end end end -- cgit v1.2.3 From f1ca93a0a37a4e5f7188af21d2696219329fadfd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 17 Jul 2014 16:48:36 +0200 Subject: Fixed simlib.v model for $mem --- techlibs/common/simlib.v | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 9c774deac..1b50959c9 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -1315,26 +1315,26 @@ generate for (i = 0; i < RD_PORTS; i = i+1) begin:rd if (RD_CLK_ENABLE[i] == 0) begin:rd_noclk always @(RD_ADDR or update_async_rd) - RD_DATA[ i*WIDTH +: WIDTH ] <= data[ RD_ADDR[ i*ABITS +: ABITS ] - OFFSET ]; + RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; end else if (RD_TRANSPARENT[i] == 1) begin:rd_transparent reg [ABITS-1:0] addr_buf; if (RD_CLK_POLARITY[i] == 1) begin:rd_trans_posclk always @(posedge RD_CLK[i]) - addr_buf <= RD_ADDR[ i*ABITS +: ABITS ]; + addr_buf <= RD_ADDR[i*ABITS +: ABITS]; end else begin:rd_trans_negclk always @(negedge RD_CLK[i]) - addr_buf <= RD_ADDR[ i*ABITS +: ABITS ]; + addr_buf <= RD_ADDR[i*ABITS +: ABITS]; end always @(addr_buf or update_async_rd) - RD_DATA[ i*WIDTH +: WIDTH ] <= data[ addr_buf - OFFSET ]; + RD_DATA[i*WIDTH +: WIDTH] <= data[addr_buf - OFFSET]; end else begin:rd_notransparent if (RD_CLK_POLARITY[i] == 1) begin:rd_notrans_posclk always @(posedge RD_CLK[i]) - RD_DATA[ i*WIDTH +: WIDTH ] <= data[ RD_ADDR[ i*ABITS +: ABITS ] - OFFSET ]; + RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; end else begin:rd_notrans_negclk always @(negedge RD_CLK[i]) - RD_DATA[ i*WIDTH +: WIDTH ] <= data[ RD_ADDR[ i*ABITS +: ABITS ] - OFFSET ]; + RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; end end end @@ -1346,13 +1346,13 @@ generate always @(WR_ADDR or WR_DATA or WR_EN) begin run_update = 0; for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i][n]) begin + if (WR_EN[i*WIDTH + n]) begin found_collision = 0; for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) found_collision = 1; if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; run_update = 1; end end @@ -1367,13 +1367,13 @@ generate always @(posedge WR_CLK[i]) begin run_update = 0; for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i][n]) begin + if (WR_EN[i*WIDTH + n]) begin found_collision = 0; for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) found_collision = 1; if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; run_update = 1; end end @@ -1387,13 +1387,13 @@ generate always @(negedge WR_CLK[i]) begin run_update = 0; for (n = 0; n < WIDTH; n = n+1) begin - if (WR_EN[i][n]) begin + if (WR_EN[i*WIDTH + n]) begin found_collision = 0; for (k = i+1; k < WR_PORTS; k = k+1) - if (WR_EN[k][n] && WR_ADDR[ i*ABITS +: ABITS ] == WR_ADDR[ k*ABITS +: ABITS ]) + if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS]) found_collision = 1; if (!found_collision) begin - data[ WR_ADDR[ i*ABITS +: ABITS ] - OFFSET ][n] <= WR_DATA[ i*WIDTH +: WIDTH ][n]; + data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n]; run_update = 1; end end -- cgit v1.2.3 From b17d6531c833f9064c5888c694aa24e8a395b72a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 24 Jul 2014 17:15:01 +0200 Subject: Added "make PRETTY=1" --- techlibs/common/Makefile.inc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index c68b13f6c..a76d1a079 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -2,24 +2,24 @@ EXTRA_TARGETS += techlibs/common/blackbox.v techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib.v techlibs/common/simcells.v - cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new - mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v + $(P) cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new + $(Q) mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v EXTRA_TARGETS += share/simlib.v share/simcells.v share/blackbox.v share/pmux2mux.v share/simlib.v: techlibs/common/simlib.v - mkdir -p share - cp techlibs/common/simlib.v share/simlib.v + $(P) mkdir -p share + $(Q) cp techlibs/common/simlib.v share/simlib.v share/simcells.v: techlibs/common/simcells.v - mkdir -p share - cp techlibs/common/simcells.v share/simcells.v + $(P) mkdir -p share + $(Q) cp techlibs/common/simcells.v share/simcells.v share/blackbox.v: techlibs/common/blackbox.v - mkdir -p share - cp techlibs/common/blackbox.v share/blackbox.v + $(P) mkdir -p share + $(Q) cp techlibs/common/blackbox.v share/blackbox.v share/pmux2mux.v: techlibs/common/pmux2mux.v - mkdir -p share - cp techlibs/common/pmux2mux.v share/pmux2mux.v + $(P) mkdir -p share + $(Q) cp techlibs/common/pmux2mux.v share/pmux2mux.v -- cgit v1.2.3 From 397b00252dc0c4af725614bd12fc299147ba8efa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 29 Jul 2014 14:42:33 +0200 Subject: Added $shift and $shiftx cell types (needed for correct part select behavior) --- techlibs/common/simlib.v | 48 +++++++++++++++++++++++++++++++ techlibs/common/stdcells.v | 72 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 8 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 1b50959c9..76aa4a52d 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -418,6 +418,54 @@ endmodule // -------------------------------------------------------- +module \$shift (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = $signed(B) < 0 ? A << -B : A >> B; + end else begin:BLOCK2 + assign Y = A >> B; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + +module \$shiftx (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = A[$signed(B) +: Y_WIDTH]; + end else begin:BLOCK2 + assign Y = A[B +: Y_WIDTH]; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + module \$lt (A, B, Y); parameter A_SIGNED = 0; diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index a05ea2786..ee59048c3 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -129,12 +129,12 @@ endmodule // -------------------------------------------------------- -module \$__shift (X, A, Y); +module \$__shift (XL, XR, A, Y); parameter WIDTH = 1; parameter SHIFT = 0; -input X; +input XL, XR; input [WIDTH-1:0] A; output [WIDTH-1:0] Y; @@ -142,12 +142,12 @@ genvar i; generate for (i = 0; i < WIDTH; i = i + 1) begin:V if (i+SHIFT < 0) begin - assign Y[i] = 0; + assign Y[i] = XR; end else if (i+SHIFT < WIDTH) begin assign Y[i] = A[i+SHIFT]; end else begin - assign Y[i] = X; + assign Y[i] = XL; end end endgenerate @@ -196,7 +196,8 @@ generate .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -255,7 +256,8 @@ generate .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -314,7 +316,8 @@ generate .WIDTH(WIDTH), .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) ) sh ( - .X(0), + .XL(1'b0), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -382,7 +385,8 @@ generate .WIDTH(WIDTH), .SHIFT(2 ** (i > 30 ? 30 : i)) ) sh ( - .X(A_SIGNED && A[A_WIDTH-1]), + .XL(A_SIGNED && A[A_WIDTH-1]), + .XR(1'b0), .A(unshifted), .Y(shifted) ); @@ -401,6 +405,58 @@ endmodule // -------------------------------------------------------- +module \$shift (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +generate + if (B_SIGNED) begin:BLOCK1 + assign Y = $signed(B) < 0 ? A << -B : A >> B; + end else begin:BLOCK2 + assign Y = A >> B; + end +endgenerate + +endmodule + +// -------------------------------------------------------- + +module \$shiftx (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +\$shift #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH), +) sh ( + .A(A), + .B(B), + .Y(Y) +); + +endmodule + +// -------------------------------------------------------- + module \$__fulladd (A, B, C, X, Y); // {X, Y} = A + B + C -- cgit v1.2.3 From 2145e57ef08784484e875e64cb43b6d1f4dbe50c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 29 Jul 2014 19:23:31 +0200 Subject: Bugfix in simlib.v for iverilog --- techlibs/common/simlib.v | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 76aa4a52d..c2f6cb278 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -455,11 +455,12 @@ input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; generate - if (B_SIGNED) begin:BLOCK1 - assign Y = A[$signed(B) +: Y_WIDTH]; - end else begin:BLOCK2 - assign Y = A[B +: Y_WIDTH]; - end + if (Y_WIDTH > 0) + if (B_SIGNED) begin:BLOCK1 + assign Y = A[$signed(B) +: Y_WIDTH]; + end else begin:BLOCK2 + assign Y = A[B +: Y_WIDTH]; + end endgenerate endmodule -- cgit v1.2.3 From 6c05badc43f7c1691932d1c38869492311f9bd44 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 30 Jul 2014 15:59:05 +0200 Subject: New techmap default rules for $shr $sshr $shl $sshl --- techlibs/common/stdcells.v | 344 ++++++++------------------------------------- 1 file changed, 62 insertions(+), 282 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index ee59048c3..a2fce1313 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -30,6 +30,9 @@ * */ +`define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +`define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) + // -------------------------------------------------------- (* techmap_simplemap *) @@ -65,7 +68,7 @@ output [Y_WIDTH-1:0] Y; .A_WIDTH(1), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH) -) sub ( +) _TECHMAP_REPLACE_ ( .A(1'b0), .B(A), .Y(Y) @@ -129,34 +132,8 @@ endmodule // -------------------------------------------------------- -module \$__shift (XL, XR, A, Y); - -parameter WIDTH = 1; -parameter SHIFT = 0; - -input XL, XR; -input [WIDTH-1:0] A; -output [WIDTH-1:0] Y; - -genvar i; -generate - for (i = 0; i < WIDTH; i = i + 1) begin:V - if (i+SHIFT < 0) begin - assign Y[i] = XR; - end else - if (i+SHIFT < WIDTH) begin - assign Y[i] = A[i+SHIFT]; - end else begin - assign Y[i] = XL; - end - end -endgenerate - -endmodule - -// -------------------------------------------------------- - -module \$shl (A, B, Y); +(* techmap_celltype = "$shr $shl $sshl $sshr" *) +module shift_ops_shr_shl_sshl_sshr (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -164,119 +141,46 @@ parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; -parameter WIDTH = Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; +parameter _TECHMAP_CELLTYPE_ = ""; +localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; +localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; -genvar i; -generate - wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$bu0 #( - .A_SIGNED(A_SIGNED), - .A_WIDTH(A_WIDTH), - .Y_WIDTH(WIDTH) - ) expand ( - .A(A), - .Y(chain[WIDTH-1:0]) - ); - assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; - for (i = 0; i < BB_WIDTH; i = i + 1) begin:V - wire [WIDTH-1:0] unshifted, shifted, result; - assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; - assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; - wire BBIT; - if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) - assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; - else - assign BBIT = B[i]; - \$__shift #( - .WIDTH(WIDTH), - .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) - ) sh ( - .XL(1'b0), - .XR(1'b0), - .A(unshifted), - .Y(shifted) - ); - \$mux #( - .WIDTH(WIDTH) - ) mux ( - .A(unshifted), - .B(shifted), - .Y(result), - .S(BBIT) - ); - end -endgenerate - -endmodule - -// -------------------------------------------------------- +localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); +localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); -module \$shr (A, B, Y); +wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; +integer i; +reg [WIDTH-1:0] buffer; +reg overflow; -localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; +always @* begin + overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0; + buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; + for (i = 0; i < BB_WIDTH; i = i+1) + if (B[i]) begin + if (shift_left) + buffer = {buffer, (2**i)'b0}; + else if (2**i < WIDTH) + buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}}; + end +end -genvar i; -generate - wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$bu0 #( - .A_SIGNED(A_SIGNED), - .A_WIDTH(A_WIDTH), - .Y_WIDTH(WIDTH) - ) expand ( - .A(A), - .Y(chain[WIDTH-1:0]) - ); - assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; - for (i = 0; i < BB_WIDTH; i = i + 1) begin:V - wire [WIDTH-1:0] unshifted, shifted, result; - assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; - assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; - wire BBIT; - if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) - assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; - else - assign BBIT = B[i]; - \$__shift #( - .WIDTH(WIDTH), - .SHIFT(2 ** (i > 30 ? 30 : i)) - ) sh ( - .XL(1'b0), - .XR(1'b0), - .A(unshifted), - .Y(shifted) - ); - \$mux #( - .WIDTH(WIDTH) - ) mux ( - .A(unshifted), - .B(shifted), - .Y(result), - .S(BBIT) - ); - end -endgenerate +assign Y = buffer; endmodule // -------------------------------------------------------- -module \$sshl (A, B, Y); +(* techmap_celltype = "$shift $shiftx" *) +module shift_shiftx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -284,174 +188,50 @@ parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; -localparam WIDTH = Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; - input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; -genvar i; -generate - wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$bu0 #( - .A_SIGNED(A_SIGNED), - .A_WIDTH(A_WIDTH), - .Y_WIDTH(WIDTH) - ) expand ( - .A(A), - .Y(chain[WIDTH-1:0]) - ); - assign Y = chain[WIDTH*(BB_WIDTH+1)-1 : WIDTH*BB_WIDTH]; - for (i = 0; i < BB_WIDTH; i = i + 1) begin:V - wire [WIDTH-1:0] unshifted, shifted, result; - assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; - assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; - wire BBIT; - if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) - assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; - else - assign BBIT = B[i]; - \$__shift #( - .WIDTH(WIDTH), - .SHIFT(0 - (2 ** (i > 30 ? 30 : i))) - ) sh ( - .XL(1'b0), - .XR(1'b0), - .A(unshifted), - .Y(shifted) - ); - \$mux #( - .WIDTH(WIDTH) - ) mux ( - .A(unshifted), - .B(shifted), - .Y(result), - .S(BBIT) - ); - end -endgenerate - -endmodule +localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); +localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); -// -------------------------------------------------------- - -module \$sshr (A, B, Y); +parameter _TECHMAP_CELLTYPE_ = ""; +localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; +wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; -localparam WIDTH = A_WIDTH > Y_WIDTH ? A_WIDTH : Y_WIDTH; -localparam BB_WIDTH = $clog2(WIDTH) + 2 < B_WIDTH ? $clog2(WIDTH) + 2 : B_WIDTH; +integer i; +reg [WIDTH-1:0] buffer; +reg overflow; -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; +always @* begin + overflow = 0; + buffer = {WIDTH{extbit}}; + buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; -genvar i; -generate - wire [WIDTH*(BB_WIDTH+1)-1:0] chain; - \$bu0 #( - .A_SIGNED(A_SIGNED), - .A_WIDTH(A_WIDTH), - .Y_WIDTH(WIDTH) - ) expand ( - .A(A), - .Y(chain[WIDTH-1:0]) - ); - for (i = 0; i < Y_WIDTH; i = i + 1) begin:Y - if (i < WIDTH) begin - assign Y[i] = chain[WIDTH*BB_WIDTH + i]; + if (B_WIDTH > BB_WIDTH) begin + if (B_SIGNED) begin + for (i = BB_WIDTH; i < B_WIDTH; i = i+1) + if (B[i] != B[BB_WIDTH-1]) + overflow = 1; end else - if (A_SIGNED) begin - assign Y[i] = chain[WIDTH*BB_WIDTH + WIDTH-1]; - end else begin - assign Y[i] = 0; - end - end - for (i = 0; i < BB_WIDTH; i = i + 1) begin:V - wire [WIDTH-1:0] unshifted, shifted, result; - assign unshifted = chain[WIDTH*i + WIDTH-1 : WIDTH*i]; - assign chain[WIDTH*(i+1) + WIDTH-1 : WIDTH*(i+1)] = result; - wire BBIT; - if (i == BB_WIDTH-1 && BB_WIDTH < B_WIDTH) - assign BBIT = |B[B_WIDTH-1:BB_WIDTH-1]; - else - assign BBIT = B[i]; - \$__shift #( - .WIDTH(WIDTH), - .SHIFT(2 ** (i > 30 ? 30 : i)) - ) sh ( - .XL(A_SIGNED && A[A_WIDTH-1]), - .XR(1'b0), - .A(unshifted), - .Y(shifted) - ); - \$mux #( - .WIDTH(WIDTH) - ) mux ( - .A(unshifted), - .B(shifted), - .Y(result), - .S(BBIT) - ); - end -endgenerate - -endmodule - -// -------------------------------------------------------- - -module \$shift (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -generate - if (B_SIGNED) begin:BLOCK1 - assign Y = $signed(B) < 0 ? A << -B : A >> B; - end else begin:BLOCK2 - assign Y = A >> B; + overflow = |B[B_WIDTH-1:BB_WIDTH]; + if (overflow) + buffer = {WIDTH{extbit}}; end -endgenerate - -endmodule - -// -------------------------------------------------------- - -module \$shiftx (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; + for (i = BB_WIDTH-1; i >= 0; i = i-1) + if (B[i]) begin + if (B_SIGNED && i == BB_WIDTH-1) + buffer = {buffer, {2**i{extbit}}}; + else if (2**i < WIDTH) + buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{extbit}}; + end +end -\$shift #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH), -) sh ( - .A(A), - .B(B), - .Y(Y) -); +assign Y = buffer; endmodule -- cgit v1.2.3 From 254148910556d057ec296e4f8c44e92bdb8c09a3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 30 Jul 2014 22:04:30 +0200 Subject: Added techmap CONSTMAP feature --- techlibs/common/stdcells.v | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index a2fce1313..7ee2771e6 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -152,7 +152,8 @@ output [Y_WIDTH-1:0] Y; localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); -wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; +wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; +wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; integer i; reg [WIDTH-1:0] buffer; @@ -198,7 +199,8 @@ localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); parameter _TECHMAP_CELLTYPE_ = ""; localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; -wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; +wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; +wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; integer i; reg [WIDTH-1:0] buffer; -- cgit v1.2.3 From 41555cde1026ecc269071ede4f99d86ff61f7078 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 31 Jul 2014 02:21:06 +0200 Subject: Reorganized stdcells.v (no actual code change, just moved and indented stuff) --- techlibs/common/stdcells.v | 1337 +++++++++++++++++++------------------------- 1 file changed, 590 insertions(+), 747 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index 7ee2771e6..54652868a 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -33,910 +33,753 @@ `define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) `define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$not ; -endmodule // -------------------------------------------------------- - -(* techmap_simplemap *) -module \$pos ; -endmodule - +// Use simplemap for trivial cell types // -------------------------------------------------------- (* techmap_simplemap *) -module \$bu0 ; +(* techmap_celltype = "$pos $bu0" *) +module simplemap_buffers; endmodule -// -------------------------------------------------------- - -module \$neg (A, Y); - -parameter A_SIGNED = 0; -parameter A_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -output [Y_WIDTH-1:0] Y; - -\$sub #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(1), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) -) _TECHMAP_REPLACE_ ( - .A(1'b0), - .B(A), - .Y(Y) -); - -endmodule - -// -------------------------------------------------------- - (* techmap_simplemap *) -module \$and ; +(* techmap_celltype = "$not $and $or $xor $xnor" *) +module simplemap_bool_ops; endmodule -// -------------------------------------------------------- - (* techmap_simplemap *) -module \$or ; +(* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *) +module simplemap_reduce_ops; endmodule -// -------------------------------------------------------- - (* techmap_simplemap *) -module \$xor ; +(* techmap_celltype = "$logic_not $logic_and $logic_or" *) +module simplemap_logic_ops; endmodule -// -------------------------------------------------------- - (* techmap_simplemap *) -module \$xnor ; +(* techmap_celltype = "$slice $concat $mux" *) +module simplemap_various; endmodule -// -------------------------------------------------------- - (* techmap_simplemap *) -module \$reduce_and ; +(* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *) +module simplemap_registers; endmodule -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$reduce_or ; -endmodule +// -------------------------------------------------------- +// Trivial substitutions // -------------------------------------------------------- -(* techmap_simplemap *) -module \$reduce_xor ; +module \$neg (A, Y); + parameter A_SIGNED = 0; + parameter A_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + output [Y_WIDTH-1:0] Y; + + \$sub #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(A_SIGNED), + .A_WIDTH(1), + .B_WIDTH(A_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(1'b0), + .B(A), + .Y(Y) + ); endmodule -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$reduce_xnor ; +module \$ge (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$le #( + .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) + ); endmodule -// -------------------------------------------------------- +module \$gt (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -(* techmap_simplemap *) -module \$reduce_bool ; + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$lt #( + .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) + ); endmodule + +// -------------------------------------------------------- +// Shift operators // -------------------------------------------------------- (* techmap_celltype = "$shr $shl $sshl $sshr" *) module shift_ops_shr_shl_sshl_sshr (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + parameter _TECHMAP_CELLTYPE_ = ""; + localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; + localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); + localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); + + wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; + + integer i; + reg [WIDTH-1:0] buffer; + reg overflow; + + always @* begin + overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0; + buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; + + for (i = 0; i < BB_WIDTH; i = i+1) + if (B[i]) begin + if (shift_left) + buffer = {buffer, (2**i)'b0}; + else if (2**i < WIDTH) + buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}}; + end + end -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -parameter _TECHMAP_CELLTYPE_ = ""; -localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; -localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); -localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); - -wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; -wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; - -integer i; -reg [WIDTH-1:0] buffer; -reg overflow; - -always @* begin - overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0; - buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; - - for (i = 0; i < BB_WIDTH; i = i+1) - if (B[i]) begin - if (shift_left) - buffer = {buffer, (2**i)'b0}; - else if (2**i < WIDTH) - buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]}; - else - buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}}; - end -end - -assign Y = buffer; - + assign Y = buffer; endmodule -// -------------------------------------------------------- - (* techmap_celltype = "$shift $shiftx" *) module shift_shiftx (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); -localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); - -parameter _TECHMAP_CELLTYPE_ = ""; -localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; - -wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; -wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; - -integer i; -reg [WIDTH-1:0] buffer; -reg overflow; - -always @* begin - overflow = 0; - buffer = {WIDTH{extbit}}; - buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; - - if (B_WIDTH > BB_WIDTH) begin - if (B_SIGNED) begin - for (i = BB_WIDTH; i < B_WIDTH; i = i+1) - if (B[i] != B[BB_WIDTH-1]) - overflow = 1; - end else - overflow = |B[B_WIDTH-1:BB_WIDTH]; - if (overflow) - buffer = {WIDTH{extbit}}; - end - - for (i = BB_WIDTH-1; i >= 0; i = i-1) - if (B[i]) begin - if (B_SIGNED && i == BB_WIDTH-1) - buffer = {buffer, {2**i{extbit}}}; - else if (2**i < WIDTH) - buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; - else + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); + localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); + + parameter _TECHMAP_CELLTYPE_ = ""; + localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; + + wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; + + integer i; + reg [WIDTH-1:0] buffer; + reg overflow; + + always @* begin + overflow = 0; + buffer = {WIDTH{extbit}}; + buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; + + if (B_WIDTH > BB_WIDTH) begin + if (B_SIGNED) begin + for (i = BB_WIDTH; i < B_WIDTH; i = i+1) + if (B[i] != B[BB_WIDTH-1]) + overflow = 1; + end else + overflow = |B[B_WIDTH-1:BB_WIDTH]; + if (overflow) buffer = {WIDTH{extbit}}; end -end -assign Y = buffer; + for (i = BB_WIDTH-1; i >= 0; i = i-1) + if (B[i]) begin + if (B_SIGNED && i == BB_WIDTH-1) + buffer = {buffer, {2**i{extbit}}}; + else if (2**i < WIDTH) + buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{extbit}}; + end + end + assign Y = buffer; endmodule + +// -------------------------------------------------------- +// ALU Infrastructure // -------------------------------------------------------- module \$__fulladd (A, B, C, X, Y); + // {X, Y} = A + B + C + input A, B, C; + output X, Y; -// {X, Y} = A + B + C -input A, B, C; -output X, Y; - -// {t1, t2} = A + B -wire t1, t2, t3; - -\$_AND_ gate1 ( .A(A), .B(B), .Y(t1) ); -\$_XOR_ gate2 ( .A(A), .B(B), .Y(t2) ); -\$_AND_ gate3 ( .A(t2), .B(C), .Y(t3) ); -\$_XOR_ gate4 ( .A(t2), .B(C), .Y(Y) ); -\$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); + // {t1, t2} = A + B + wire t1, t2, t3; + \$_AND_ gate1 ( .A(A), .B(B), .Y(t1) ); + \$_XOR_ gate2 ( .A(A), .B(B), .Y(t2) ); + \$_AND_ gate3 ( .A(t2), .B(C), .Y(t3) ); + \$_XOR_ gate4 ( .A(t2), .B(C), .Y(Y) ); + \$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); endmodule - -// -------------------------------------------------------- - module \$__alu (A, B, Cin, Y, Cout, Csign); - -parameter WIDTH = 1; - -input [WIDTH-1:0] A, B; -input Cin; - -output [WIDTH-1:0] Y; -output Cout, Csign; - -wire [WIDTH:0] carry; -assign carry[0] = Cin; -assign Cout = carry[WIDTH]; -assign Csign = carry[WIDTH-1]; - -genvar i; -generate - for (i = 0; i < WIDTH; i = i + 1) begin:V - \$__fulladd adder ( - .A(A[i]), - .B(B[i]), - .C(carry[i]), - .X(carry[i+1]), - .Y(Y[i]) - ); - end -endgenerate - + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B; + input Cin; + + output [WIDTH-1:0] Y; + output Cout, Csign; + + wire [WIDTH:0] carry; + assign carry[0] = Cin; + assign Cout = carry[WIDTH]; + assign Csign = carry[WIDTH-1]; + + genvar i; + generate + for (i = 0; i < WIDTH; i = i + 1) begin:V + \$__fulladd adder ( + .A(A[i]), + .B(B[i]), + .C(carry[i]), + .X(carry[i+1]), + .Y(Y[i]) + ); + end + endgenerate endmodule + +// -------------------------------------------------------- +// Compare cells // -------------------------------------------------------- module \$lt (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf, Y_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -\$__alu #( - .WIDTH(WIDTH) -) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) -); - -// ALU flags -wire cf, of, zf, sf; -assign cf = !carry; -assign of = carry ^ carry_sign; -assign zf = ~|Y_buf; -assign sf = Y_buf[WIDTH-1]; - -generate - if (A_SIGNED && B_SIGNED) begin - assign Y = of != sf; - end else begin - assign Y = cf; - end -endgenerate - + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf, Y_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y_buf), + .Cout(carry), + .Csign(carry_sign) + ); + + // ALU flags + wire cf, of, zf, sf; + assign cf = !carry; + assign of = carry ^ carry_sign; + assign zf = ~|Y_buf; + assign sf = Y_buf[WIDTH-1]; + + generate + if (A_SIGNED && B_SIGNED) begin + assign Y = of != sf; + end else begin + assign Y = cf; + end + endgenerate endmodule -// -------------------------------------------------------- - module \$le (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf, Y_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -\$__alu #( - .WIDTH(WIDTH) -) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) -); - -// ALU flags -wire cf, of, zf, sf; -assign cf = !carry; -assign of = carry ^ carry_sign; -assign zf = ~|Y_buf; -assign sf = Y_buf[WIDTH-1]; - -generate - if (A_SIGNED && B_SIGNED) begin - assign Y = zf || (of != sf); - end else begin - assign Y = zf || cf; - end -endgenerate - + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf, Y_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y_buf), + .Cout(carry), + .Csign(carry_sign) + ); + + // ALU flags + wire cf, of, zf, sf; + assign cf = !carry; + assign of = carry ^ carry_sign; + assign zf = ~|Y_buf; + assign sf = Y_buf[WIDTH-1]; + + generate + if (A_SIGNED && B_SIGNED) begin + assign Y = zf || (of != sf); + end else begin + assign Y = zf || cf; + end + endgenerate endmodule -// -------------------------------------------------------- - -module \$eq (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf; -\$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -assign Y = ~|(A_buf ^ B_buf); - -endmodule // -------------------------------------------------------- - -module \$ne (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf; -\$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -assign Y = |(A_buf ^ B_buf); - -endmodule - +// Add and Subtract // -------------------------------------------------------- -module \$eqx (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -assign Y = ~|(A_buf ^ B_buf); - -endmodule - -// -------------------------------------------------------- - -module \$nex (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire carry, carry_sign; -wire [WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - -assign Y = |(A_buf ^ B_buf); - -endmodule - -// -------------------------------------------------------- - -module \$ge (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -\$le #( - .A_SIGNED(B_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(B_WIDTH), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) -) ge_via_le ( - .A(B), - .B(A), - .Y(Y) -); - +module \$add (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(Y_WIDTH) + ) alu ( + .A(A_buf), + .B(B_buf), + .Cin(1'b0), + .Y(Y) + ); endmodule -// -------------------------------------------------------- +module \$sub (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -module \$gt (A, B, Y); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -\$lt #( - .A_SIGNED(B_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(B_WIDTH), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) -) gt_via_lt ( - .A(B), - .B(A), - .Y(Y) -); + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + \$__alu #( + .WIDTH(Y_WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y) + ); endmodule -// -------------------------------------------------------- - -module \$add (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire [Y_WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - -\$__alu #( - .WIDTH(Y_WIDTH) -) alu ( - .A(A_buf), - .B(B_buf), - .Cin(1'b0), - .Y(Y) -); - -endmodule // -------------------------------------------------------- - -module \$sub (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire [Y_WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - -\$__alu #( - .WIDTH(Y_WIDTH) -) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y) -); - -endmodule - +// Multiply // -------------------------------------------------------- module \$__arraymul (A, B, Y); + parameter WIDTH = 8; + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y; -parameter WIDTH = 8; -input [WIDTH-1:0] A, B; -output [WIDTH-1:0] Y; - -wire [WIDTH*WIDTH-1:0] partials; - -genvar i; -assign partials[WIDTH-1 : 0] = A[0] ? B : 0; -generate for (i = 1; i < WIDTH; i = i+1) begin:gen - assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)]; -end endgenerate + wire [WIDTH*WIDTH-1:0] partials; -assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)]; + genvar i; + assign partials[WIDTH-1 : 0] = A[0] ? B : 0; + generate for (i = 1; i < WIDTH; i = i+1) begin:gen + assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)]; + end endgenerate + assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)]; endmodule -// -------------------------------------------------------- - module \$mul (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -wire [Y_WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - -\$__arraymul #( - .WIDTH(Y_WIDTH) -) arraymul ( - .A(A_buf), - .B(B_buf), - .Y(Y) -); + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + \$__arraymul #( + .WIDTH(Y_WIDTH) + ) arraymul ( + .A(A_buf), + .B(B_buf), + .Y(Y) + ); endmodule + +// -------------------------------------------------------- +// Divide and Modulo // -------------------------------------------------------- module \$__div_mod_u (A, B, Y, R); + parameter WIDTH = 1; -parameter WIDTH = 1; + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y, R; -input [WIDTH-1:0] A, B; -output [WIDTH-1:0] Y, R; + wire [WIDTH*WIDTH-1:0] chaindata; + assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; -wire [WIDTH*WIDTH-1:0] chaindata; -assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; + genvar i; + generate begin + for (i = 0; i < WIDTH; i=i+1) begin:stage + wire [WIDTH-1:0] stage_in; -genvar i; -generate begin - for (i = 0; i < WIDTH; i=i+1) begin:stage - wire [WIDTH-1:0] stage_in; + if (i == 0) begin:cp + assign stage_in = A; + end else begin:cp + assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH]; + end - if (i == 0) begin:cp - assign stage_in = A; - end else begin:cp - assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH]; + assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}}; + assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in; end - - assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}}; - assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in; - end -end endgenerate - + end endgenerate endmodule -// -------------------------------------------------------- - module \$__div_mod (A, B, Y, R); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -localparam WIDTH = - A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : - B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y, R; + localparam WIDTH = + A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : + B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; -wire [WIDTH-1:0] A_buf, B_buf; -\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); -\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y, R; -wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; -assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; -assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); -\$__div_mod_u #( - .WIDTH(WIDTH) -) div_mod_u ( - .A(A_buf_u), - .B(B_buf_u), - .Y(Y_u), - .R(R_u) -); + wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; + assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; + assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; -assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u; -assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; + \$__div_mod_u #( + .WIDTH(WIDTH) + ) div_mod_u ( + .A(A_buf_u), + .B(B_buf_u), + .Y(Y_u), + .R(R_u) + ); + assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u; + assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; endmodule -// -------------------------------------------------------- - module \$div (A, B, Y); - -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -\$__div_mod #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) -) div_mod ( - .A(A), - .B(B), - .Y(Y) -); - + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$__div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .Y(Y) + ); endmodule -// -------------------------------------------------------- - module \$mod (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -\$__div_mod #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) -) div_mod ( - .A(A), - .B(B), - .R(Y) -); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + \$__div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .R(Y) + ); endmodule -/**** + +// -------------------------------------------------------- +// Power // -------------------------------------------------------- module \$pow (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -parameter A_SIGNED = 0; -parameter B_SIGNED = 0; -parameter A_WIDTH = 1; -parameter B_WIDTH = 1; -parameter Y_WIDTH = 1; - -input [A_WIDTH-1:0] A; -input [B_WIDTH-1:0] B; -output [Y_WIDTH-1:0] Y; - -wire signed [A_WIDTH:0] buffer_a = A_SIGNED ? $signed(A) : A; -wire signed [B_WIDTH:0] buffer_b = B_SIGNED ? $signed(B) : B; - -assign Y = buffer_a ** buffer_b; + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + wire _TECHMAP_FAIL_ = 1; endmodule -// -------------------------------------------------------- -****/ - -(* techmap_simplemap *) -module \$logic_not ; -endmodule // -------------------------------------------------------- - -(* techmap_simplemap *) -module \$logic_and ; -endmodule - +// Equal and Not-Equal // -------------------------------------------------------- -(* techmap_simplemap *) -module \$logic_or ; -endmodule +module \$eq (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -// -------------------------------------------------------- + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; -(* techmap_simplemap *) -module \$slice ; -endmodule + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -// -------------------------------------------------------- + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); -(* techmap_simplemap *) -module \$concat ; + assign Y = ~|(A_buf ^ B_buf); endmodule -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$mux ; -endmodule +module \$ne (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -// -------------------------------------------------------- + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; -module \$pmux (A, B, S, Y); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -parameter WIDTH = 1; -parameter S_WIDTH = 1; - -input [WIDTH-1:0] A; -input [WIDTH*S_WIDTH-1:0] B; -input [S_WIDTH-1:0] S; -output [WIDTH-1:0] Y; - -wire [WIDTH-1:0] Y_B; - -genvar i, j; -generate - wire [WIDTH*S_WIDTH-1:0] B_AND_S; - for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND - assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; - end:B_AND - for (i = 0; i < WIDTH; i = i + 1) begin:B_OR - wire [S_WIDTH-1:0] B_AND_BITS; - for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT - assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; - end:B_AND_BITS_COLLECT - assign Y_B[i] = |B_AND_BITS; - end:B_OR -endgenerate - -assign Y = |S ? Y_B : A; + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + assign Y = |(A_buf ^ B_buf); endmodule -// -------------------------------------------------------- +module \$eqx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -module \$safe_pmux (A, B, S, Y); + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; -parameter WIDTH = 1; -parameter S_WIDTH = 1; - -input [WIDTH-1:0] A; -input [WIDTH*S_WIDTH-1:0] B; -input [S_WIDTH-1:0] S; -output [WIDTH-1:0] Y; - -wire [S_WIDTH-1:0] status_found_first; -wire [S_WIDTH-1:0] status_found_second; - -genvar i; -generate - for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1 - wire pre_first; - if (i > 0) begin:GEN2 - assign pre_first = status_found_first[i-1]; - end:GEN2 else begin:GEN3 - assign pre_first = 0; - end:GEN3 - assign status_found_first[i] = pre_first | S[i]; - assign status_found_second[i] = pre_first & S[i]; - end:GEN1 -endgenerate - -\$pmux #( - .WIDTH(WIDTH), - .S_WIDTH(S_WIDTH) -) pmux_cell ( - .A(A), - .B(B), - .S(S & {S_WIDTH{~|status_found_second}}), - .Y(Y) -); + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -endmodule + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$sr ; + assign Y = ~|(A_buf ^ B_buf); endmodule -// -------------------------------------------------------- - -(* techmap_simplemap *) -module \$dff ; -endmodule +module \$nex (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; -// -------------------------------------------------------- + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; -(* techmap_simplemap *) -module \$adff ; -endmodule + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; -// -------------------------------------------------------- + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); -(* techmap_simplemap *) -module \$dffsr ; + assign Y = |(A_buf ^ B_buf); endmodule + +// -------------------------------------------------------- +// Parallel Multiplexers // -------------------------------------------------------- -(* techmap_simplemap *) -module \$dlatch ; +module \$pmux (A, B, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + input [WIDTH-1:0] A; + input [WIDTH*S_WIDTH-1:0] B; + input [S_WIDTH-1:0] S; + output [WIDTH-1:0] Y; + + wire [WIDTH-1:0] Y_B; + + genvar i, j; + generate + wire [WIDTH*S_WIDTH-1:0] B_AND_S; + for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND + assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; + end:B_AND + for (i = 0; i < WIDTH; i = i + 1) begin:B_OR + wire [S_WIDTH-1:0] B_AND_BITS; + for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT + assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; + end:B_AND_BITS_COLLECT + assign Y_B[i] = |B_AND_BITS; + end:B_OR + endgenerate + + assign Y = |S ? Y_B : A; endmodule -// -------------------------------------------------------- +module \$safe_pmux (A, B, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + input [WIDTH-1:0] A; + input [WIDTH*S_WIDTH-1:0] B; + input [S_WIDTH-1:0] S; + output [WIDTH-1:0] Y; + + wire [S_WIDTH-1:0] status_found_first; + wire [S_WIDTH-1:0] status_found_second; + + genvar i; + generate + for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1 + wire pre_first; + if (i > 0) begin:GEN2 + assign pre_first = status_found_first[i-1]; + end:GEN2 else begin:GEN3 + assign pre_first = 0; + end:GEN3 + assign status_found_first[i] = pre_first | S[i]; + assign status_found_second[i] = pre_first & S[i]; + end:GEN1 + endgenerate + + \$pmux #( + .WIDTH(WIDTH), + .S_WIDTH(S_WIDTH) + ) pmux_cell ( + .A(A), + .B(B), + .S(S & {S_WIDTH{~|status_found_second}}), + .Y(Y) + ); +endmodule -- cgit v1.2.3 From 1202f7aa4bb0f9afde157ebc4701d64e7e38abd8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 31 Jul 2014 02:32:00 +0200 Subject: Renamed "stdcells.v" to "techmap.v" --- techlibs/common/Makefile.inc | 6 +- techlibs/common/simcells.v | 2 +- techlibs/common/stdcells.v | 785 ------------------------------------------- techlibs/common/techmap.v | 785 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 791 insertions(+), 787 deletions(-) delete mode 100644 techlibs/common/stdcells.v create mode 100644 techlibs/common/techmap.v (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index a76d1a079..2be27b920 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -5,7 +5,7 @@ techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib. $(P) cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new $(Q) mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v -EXTRA_TARGETS += share/simlib.v share/simcells.v share/blackbox.v share/pmux2mux.v +EXTRA_TARGETS += share/simlib.v share/simcells.v share/techmap.v share/blackbox.v share/pmux2mux.v share/simlib.v: techlibs/common/simlib.v $(P) mkdir -p share @@ -15,6 +15,10 @@ share/simcells.v: techlibs/common/simcells.v $(P) mkdir -p share $(Q) cp techlibs/common/simcells.v share/simcells.v +share/techmap.v: techlibs/common/techmap.v + $(P) mkdir -p share + $(Q) cp techlibs/common/techmap.v share/techmap.v + share/blackbox.v: techlibs/common/blackbox.v $(P) mkdir -p share $(Q) cp techlibs/common/blackbox.v share/blackbox.v diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 5ecec7891..d492c2f15 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -21,7 +21,7 @@ * * This verilog library contains simple simulation models for the internal * logic cells ($_INV_ , $_AND_ , ...) that are generated by the default technology - * mapper (see "stdcells.v" in this directory) and expected by the "abc" pass. + * mapper (see "techmap.v" in this directory) and expected by the "abc" pass. * */ diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v deleted file mode 100644 index 54652868a..000000000 --- a/techlibs/common/stdcells.v +++ /dev/null @@ -1,785 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford 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 - * 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. - * - * --- - * - * The internal logic cell technology mapper. - * - * This verilog library contains the mapping of internal cells (e.g. $not with - * variable bit width) to the internal logic cells (such as the single bit $_INV_ - * gate). Usually this logic network is then mapped to the actual technology - * using e.g. the "abc" pass. - * - * Note that this library does not map $mem cells. They must be mapped to logic - * and $dff cells using the "memory_map" pass first. (Or map it to custom cells, - * which is of course highly recommended for larger memories.) - * - */ - -`define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) -`define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) - - -// -------------------------------------------------------- -// Use simplemap for trivial cell types -// -------------------------------------------------------- - -(* techmap_simplemap *) -(* techmap_celltype = "$pos $bu0" *) -module simplemap_buffers; -endmodule - -(* techmap_simplemap *) -(* techmap_celltype = "$not $and $or $xor $xnor" *) -module simplemap_bool_ops; -endmodule - -(* techmap_simplemap *) -(* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *) -module simplemap_reduce_ops; -endmodule - -(* techmap_simplemap *) -(* techmap_celltype = "$logic_not $logic_and $logic_or" *) -module simplemap_logic_ops; -endmodule - -(* techmap_simplemap *) -(* techmap_celltype = "$slice $concat $mux" *) -module simplemap_various; -endmodule - -(* techmap_simplemap *) -(* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *) -module simplemap_registers; -endmodule - - -// -------------------------------------------------------- -// Trivial substitutions -// -------------------------------------------------------- - -module \$neg (A, Y); - parameter A_SIGNED = 0; - parameter A_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - output [Y_WIDTH-1:0] Y; - - \$sub #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(1), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(1'b0), - .B(A), - .Y(Y) - ); -endmodule - -module \$ge (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$le #( - .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) - ); -endmodule - -module \$gt (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$lt #( - .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) - ); -endmodule - - -// -------------------------------------------------------- -// Shift operators -// -------------------------------------------------------- - -(* techmap_celltype = "$shr $shl $sshl $sshr" *) -module shift_ops_shr_shl_sshl_sshr (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - parameter _TECHMAP_CELLTYPE_ = ""; - localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; - localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); - localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); - - wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; - wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; - - integer i; - reg [WIDTH-1:0] buffer; - reg overflow; - - always @* begin - overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0; - buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; - - for (i = 0; i < BB_WIDTH; i = i+1) - if (B[i]) begin - if (shift_left) - buffer = {buffer, (2**i)'b0}; - else if (2**i < WIDTH) - buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]}; - else - buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}}; - end - end - - assign Y = buffer; -endmodule - -(* techmap_celltype = "$shift $shiftx" *) -module shift_shiftx (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); - localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); - - parameter _TECHMAP_CELLTYPE_ = ""; - localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; - - wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; - wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; - - integer i; - reg [WIDTH-1:0] buffer; - reg overflow; - - always @* begin - overflow = 0; - buffer = {WIDTH{extbit}}; - buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; - - if (B_WIDTH > BB_WIDTH) begin - if (B_SIGNED) begin - for (i = BB_WIDTH; i < B_WIDTH; i = i+1) - if (B[i] != B[BB_WIDTH-1]) - overflow = 1; - end else - overflow = |B[B_WIDTH-1:BB_WIDTH]; - if (overflow) - buffer = {WIDTH{extbit}}; - end - - for (i = BB_WIDTH-1; i >= 0; i = i-1) - if (B[i]) begin - if (B_SIGNED && i == BB_WIDTH-1) - buffer = {buffer, {2**i{extbit}}}; - else if (2**i < WIDTH) - buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; - else - buffer = {WIDTH{extbit}}; - end - end - - assign Y = buffer; -endmodule - - -// -------------------------------------------------------- -// ALU Infrastructure -// -------------------------------------------------------- - -module \$__fulladd (A, B, C, X, Y); - // {X, Y} = A + B + C - input A, B, C; - output X, Y; - - // {t1, t2} = A + B - wire t1, t2, t3; - - \$_AND_ gate1 ( .A(A), .B(B), .Y(t1) ); - \$_XOR_ gate2 ( .A(A), .B(B), .Y(t2) ); - \$_AND_ gate3 ( .A(t2), .B(C), .Y(t3) ); - \$_XOR_ gate4 ( .A(t2), .B(C), .Y(Y) ); - \$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); -endmodule - -module \$__alu (A, B, Cin, Y, Cout, Csign); - parameter WIDTH = 1; - - input [WIDTH-1:0] A, B; - input Cin; - - output [WIDTH-1:0] Y; - output Cout, Csign; - - wire [WIDTH:0] carry; - assign carry[0] = Cin; - assign Cout = carry[WIDTH]; - assign Csign = carry[WIDTH-1]; - - genvar i; - generate - for (i = 0; i < WIDTH; i = i + 1) begin:V - \$__fulladd adder ( - .A(A[i]), - .B(B[i]), - .C(carry[i]), - .X(carry[i+1]), - .Y(Y[i]) - ); - end - endgenerate -endmodule - - -// -------------------------------------------------------- -// Compare cells -// -------------------------------------------------------- - -module \$lt (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf, Y_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(WIDTH) - ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) - ); - - // ALU flags - wire cf, of, zf, sf; - assign cf = !carry; - assign of = carry ^ carry_sign; - assign zf = ~|Y_buf; - assign sf = Y_buf[WIDTH-1]; - - generate - if (A_SIGNED && B_SIGNED) begin - assign Y = of != sf; - end else begin - assign Y = cf; - end - endgenerate -endmodule - -module \$le (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf, Y_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(WIDTH) - ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) - ); - - // ALU flags - wire cf, of, zf, sf; - assign cf = !carry; - assign of = carry ^ carry_sign; - assign zf = ~|Y_buf; - assign sf = Y_buf[WIDTH-1]; - - generate - if (A_SIGNED && B_SIGNED) begin - assign Y = zf || (of != sf); - end else begin - assign Y = zf || cf; - end - endgenerate -endmodule - - -// -------------------------------------------------------- -// Add and Subtract -// -------------------------------------------------------- - -module \$add (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(Y_WIDTH) - ) alu ( - .A(A_buf), - .B(B_buf), - .Cin(1'b0), - .Y(Y) - ); -endmodule - -module \$sub (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(Y_WIDTH) - ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y) - ); -endmodule - - -// -------------------------------------------------------- -// Multiply -// -------------------------------------------------------- - -module \$__arraymul (A, B, Y); - parameter WIDTH = 8; - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y; - - wire [WIDTH*WIDTH-1:0] partials; - - genvar i; - assign partials[WIDTH-1 : 0] = A[0] ? B : 0; - generate for (i = 1; i < WIDTH; i = i+1) begin:gen - assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)]; - end endgenerate - - assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)]; -endmodule - -module \$mul (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__arraymul #( - .WIDTH(Y_WIDTH) - ) arraymul ( - .A(A_buf), - .B(B_buf), - .Y(Y) - ); -endmodule - - -// -------------------------------------------------------- -// Divide and Modulo -// -------------------------------------------------------- - -module \$__div_mod_u (A, B, Y, R); - parameter WIDTH = 1; - - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y, R; - - wire [WIDTH*WIDTH-1:0] chaindata; - assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; - - genvar i; - generate begin - for (i = 0; i < WIDTH; i=i+1) begin:stage - wire [WIDTH-1:0] stage_in; - - if (i == 0) begin:cp - assign stage_in = A; - end else begin:cp - assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH]; - end - - assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}}; - assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in; - end - end endgenerate -endmodule - -module \$__div_mod (A, B, Y, R); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = - A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : - B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y, R; - - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; - assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; - assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; - - \$__div_mod_u #( - .WIDTH(WIDTH) - ) div_mod_u ( - .A(A_buf_u), - .B(B_buf_u), - .Y(Y_u), - .R(R_u) - ); - - assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u; - assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; -endmodule - -module \$div (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$__div_mod #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) div_mod ( - .A(A), - .B(B), - .Y(Y) - ); -endmodule - -module \$mod (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$__div_mod #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) div_mod ( - .A(A), - .B(B), - .R(Y) - ); -endmodule - - -// -------------------------------------------------------- -// Power -// -------------------------------------------------------- - -module \$pow (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire _TECHMAP_FAIL_ = 1; -endmodule - - -// -------------------------------------------------------- -// Equal and Not-Equal -// -------------------------------------------------------- - -module \$eq (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = ~|(A_buf ^ B_buf); -endmodule - -module \$ne (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = |(A_buf ^ B_buf); -endmodule - -module \$eqx (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = ~|(A_buf ^ B_buf); -endmodule - -module \$nex (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = |(A_buf ^ B_buf); -endmodule - - -// -------------------------------------------------------- -// Parallel Multiplexers -// -------------------------------------------------------- - -module \$pmux (A, B, S, Y); - parameter WIDTH = 1; - parameter S_WIDTH = 1; - - input [WIDTH-1:0] A; - input [WIDTH*S_WIDTH-1:0] B; - input [S_WIDTH-1:0] S; - output [WIDTH-1:0] Y; - - wire [WIDTH-1:0] Y_B; - - genvar i, j; - generate - wire [WIDTH*S_WIDTH-1:0] B_AND_S; - for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND - assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; - end:B_AND - for (i = 0; i < WIDTH; i = i + 1) begin:B_OR - wire [S_WIDTH-1:0] B_AND_BITS; - for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT - assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; - end:B_AND_BITS_COLLECT - assign Y_B[i] = |B_AND_BITS; - end:B_OR - endgenerate - - assign Y = |S ? Y_B : A; -endmodule - -module \$safe_pmux (A, B, S, Y); - parameter WIDTH = 1; - parameter S_WIDTH = 1; - - input [WIDTH-1:0] A; - input [WIDTH*S_WIDTH-1:0] B; - input [S_WIDTH-1:0] S; - output [WIDTH-1:0] Y; - - wire [S_WIDTH-1:0] status_found_first; - wire [S_WIDTH-1:0] status_found_second; - - genvar i; - generate - for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1 - wire pre_first; - if (i > 0) begin:GEN2 - assign pre_first = status_found_first[i-1]; - end:GEN2 else begin:GEN3 - assign pre_first = 0; - end:GEN3 - assign status_found_first[i] = pre_first | S[i]; - assign status_found_second[i] = pre_first & S[i]; - end:GEN1 - endgenerate - - \$pmux #( - .WIDTH(WIDTH), - .S_WIDTH(S_WIDTH) - ) pmux_cell ( - .A(A), - .B(B), - .S(S & {S_WIDTH{~|status_found_second}}), - .Y(Y) - ); -endmodule - diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v new file mode 100644 index 000000000..54652868a --- /dev/null +++ b/techlibs/common/techmap.v @@ -0,0 +1,785 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford 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 + * 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. + * + * --- + * + * The internal logic cell technology mapper. + * + * This verilog library contains the mapping of internal cells (e.g. $not with + * variable bit width) to the internal logic cells (such as the single bit $_INV_ + * gate). Usually this logic network is then mapped to the actual technology + * using e.g. the "abc" pass. + * + * Note that this library does not map $mem cells. They must be mapped to logic + * and $dff cells using the "memory_map" pass first. (Or map it to custom cells, + * which is of course highly recommended for larger memories.) + * + */ + +`define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +`define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) + + +// -------------------------------------------------------- +// Use simplemap for trivial cell types +// -------------------------------------------------------- + +(* techmap_simplemap *) +(* techmap_celltype = "$pos $bu0" *) +module simplemap_buffers; +endmodule + +(* techmap_simplemap *) +(* techmap_celltype = "$not $and $or $xor $xnor" *) +module simplemap_bool_ops; +endmodule + +(* techmap_simplemap *) +(* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *) +module simplemap_reduce_ops; +endmodule + +(* techmap_simplemap *) +(* techmap_celltype = "$logic_not $logic_and $logic_or" *) +module simplemap_logic_ops; +endmodule + +(* techmap_simplemap *) +(* techmap_celltype = "$slice $concat $mux" *) +module simplemap_various; +endmodule + +(* techmap_simplemap *) +(* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *) +module simplemap_registers; +endmodule + + +// -------------------------------------------------------- +// Trivial substitutions +// -------------------------------------------------------- + +module \$neg (A, Y); + parameter A_SIGNED = 0; + parameter A_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + output [Y_WIDTH-1:0] Y; + + \$sub #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(A_SIGNED), + .A_WIDTH(1), + .B_WIDTH(A_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) _TECHMAP_REPLACE_ ( + .A(1'b0), + .B(A), + .Y(Y) + ); +endmodule + +module \$ge (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$le #( + .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) + ); +endmodule + +module \$gt (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$lt #( + .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) + ); +endmodule + + +// -------------------------------------------------------- +// Shift operators +// -------------------------------------------------------- + +(* techmap_celltype = "$shr $shl $sshl $sshr" *) +module shift_ops_shr_shl_sshl_sshr (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + parameter _TECHMAP_CELLTYPE_ = ""; + localparam shift_left = _TECHMAP_CELLTYPE_ == "$shl" || _TECHMAP_CELLTYPE_ == "$sshl"; + localparam sign_extend = A_SIGNED && _TECHMAP_CELLTYPE_ == "$sshr"; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); + localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); + + wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; + + integer i; + reg [WIDTH-1:0] buffer; + reg overflow; + + always @* begin + overflow = B_WIDTH > BB_WIDTH ? |B[B_WIDTH-1:BB_WIDTH] : 1'b0; + buffer = overflow ? {WIDTH{sign_extend ? A[A_WIDTH-1] : 1'b0}} : {{WIDTH-A_WIDTH{A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; + + for (i = 0; i < BB_WIDTH; i = i+1) + if (B[i]) begin + if (shift_left) + buffer = {buffer, (2**i)'b0}; + else if (2**i < WIDTH) + buffer = {{2**i{sign_extend ? buffer[WIDTH-1] : 1'b0}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{sign_extend ? buffer[WIDTH-1] : 1'b0}}; + end + end + + assign Y = buffer; +endmodule + +(* techmap_celltype = "$shift $shiftx" *) +module shift_shiftx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + localparam BB_WIDTH = `MIN($clog2(`MAX(A_WIDTH, Y_WIDTH)) + (B_SIGNED ? 2 : 1), B_WIDTH); + localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); + + parameter _TECHMAP_CELLTYPE_ = ""; + localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; + + wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; + + integer i; + reg [WIDTH-1:0] buffer; + reg overflow; + + always @* begin + overflow = 0; + buffer = {WIDTH{extbit}}; + buffer[`MAX(A_WIDTH, Y_WIDTH)-1:0] = A; + + if (B_WIDTH > BB_WIDTH) begin + if (B_SIGNED) begin + for (i = BB_WIDTH; i < B_WIDTH; i = i+1) + if (B[i] != B[BB_WIDTH-1]) + overflow = 1; + end else + overflow = |B[B_WIDTH-1:BB_WIDTH]; + if (overflow) + buffer = {WIDTH{extbit}}; + end + + for (i = BB_WIDTH-1; i >= 0; i = i-1) + if (B[i]) begin + if (B_SIGNED && i == BB_WIDTH-1) + buffer = {buffer, {2**i{extbit}}}; + else if (2**i < WIDTH) + buffer = {{2**i{extbit}}, buffer[WIDTH-1 : 2**i]}; + else + buffer = {WIDTH{extbit}}; + end + end + + assign Y = buffer; +endmodule + + +// -------------------------------------------------------- +// ALU Infrastructure +// -------------------------------------------------------- + +module \$__fulladd (A, B, C, X, Y); + // {X, Y} = A + B + C + input A, B, C; + output X, Y; + + // {t1, t2} = A + B + wire t1, t2, t3; + + \$_AND_ gate1 ( .A(A), .B(B), .Y(t1) ); + \$_XOR_ gate2 ( .A(A), .B(B), .Y(t2) ); + \$_AND_ gate3 ( .A(t2), .B(C), .Y(t3) ); + \$_XOR_ gate4 ( .A(t2), .B(C), .Y(Y) ); + \$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); +endmodule + +module \$__alu (A, B, Cin, Y, Cout, Csign); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B; + input Cin; + + output [WIDTH-1:0] Y; + output Cout, Csign; + + wire [WIDTH:0] carry; + assign carry[0] = Cin; + assign Cout = carry[WIDTH]; + assign Csign = carry[WIDTH-1]; + + genvar i; + generate + for (i = 0; i < WIDTH; i = i + 1) begin:V + \$__fulladd adder ( + .A(A[i]), + .B(B[i]), + .C(carry[i]), + .X(carry[i+1]), + .Y(Y[i]) + ); + end + endgenerate +endmodule + + +// -------------------------------------------------------- +// Compare cells +// -------------------------------------------------------- + +module \$lt (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf, Y_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y_buf), + .Cout(carry), + .Csign(carry_sign) + ); + + // ALU flags + wire cf, of, zf, sf; + assign cf = !carry; + assign of = carry ^ carry_sign; + assign zf = ~|Y_buf; + assign sf = Y_buf[WIDTH-1]; + + generate + if (A_SIGNED && B_SIGNED) begin + assign Y = of != sf; + end else begin + assign Y = cf; + end + endgenerate +endmodule + +module \$le (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf, Y_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y_buf), + .Cout(carry), + .Csign(carry_sign) + ); + + // ALU flags + wire cf, of, zf, sf; + assign cf = !carry; + assign of = carry ^ carry_sign; + assign zf = ~|Y_buf; + assign sf = Y_buf[WIDTH-1]; + + generate + if (A_SIGNED && B_SIGNED) begin + assign Y = zf || (of != sf); + end else begin + assign Y = zf || cf; + end + endgenerate +endmodule + + +// -------------------------------------------------------- +// Add and Subtract +// -------------------------------------------------------- + +module \$add (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(Y_WIDTH) + ) alu ( + .A(A_buf), + .B(B_buf), + .Cin(1'b0), + .Y(Y) + ); +endmodule + +module \$sub (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__alu #( + .WIDTH(Y_WIDTH) + ) alu ( + .A(A_buf), + .B(~B_buf), + .Cin(1'b1), + .Y(Y) + ); +endmodule + + +// -------------------------------------------------------- +// Multiply +// -------------------------------------------------------- + +module \$__arraymul (A, B, Y); + parameter WIDTH = 8; + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y; + + wire [WIDTH*WIDTH-1:0] partials; + + genvar i; + assign partials[WIDTH-1 : 0] = A[0] ? B : 0; + generate for (i = 1; i < WIDTH; i = i+1) begin:gen + assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)]; + end endgenerate + + assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)]; +endmodule + +module \$mul (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + + \$__arraymul #( + .WIDTH(Y_WIDTH) + ) arraymul ( + .A(A_buf), + .B(B_buf), + .Y(Y) + ); +endmodule + + +// -------------------------------------------------------- +// Divide and Modulo +// -------------------------------------------------------- + +module \$__div_mod_u (A, B, Y, R); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y, R; + + wire [WIDTH*WIDTH-1:0] chaindata; + assign R = chaindata[WIDTH*WIDTH-1:WIDTH*(WIDTH-1)]; + + genvar i; + generate begin + for (i = 0; i < WIDTH; i=i+1) begin:stage + wire [WIDTH-1:0] stage_in; + + if (i == 0) begin:cp + assign stage_in = A; + end else begin:cp + assign stage_in = chaindata[i*WIDTH-1:(i-1)*WIDTH]; + end + + assign Y[WIDTH-(i+1)] = stage_in >= {B, {WIDTH-(i+1){1'b0}}}; + assign chaindata[(i+1)*WIDTH-1:i*WIDTH] = Y[WIDTH-(i+1)] ? stage_in - {B, {WIDTH-(i+1){1'b0}}} : stage_in; + end + end endgenerate +endmodule + +module \$__div_mod (A, B, Y, R); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = + A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : + B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y, R; + + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + wire [WIDTH-1:0] A_buf_u, B_buf_u, Y_u, R_u; + assign A_buf_u = A_SIGNED && A_buf[WIDTH-1] ? -A_buf : A_buf; + assign B_buf_u = B_SIGNED && B_buf[WIDTH-1] ? -B_buf : B_buf; + + \$__div_mod_u #( + .WIDTH(WIDTH) + ) div_mod_u ( + .A(A_buf_u), + .B(B_buf_u), + .Y(Y_u), + .R(R_u) + ); + + assign Y = A_SIGNED && B_SIGNED && (A_buf[WIDTH-1] != B_buf[WIDTH-1]) ? -Y_u : Y_u; + assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; +endmodule + +module \$div (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$__div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .Y(Y) + ); +endmodule + +module \$mod (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + \$__div_mod #( + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(Y_WIDTH) + ) div_mod ( + .A(A), + .B(B), + .R(Y) + ); +endmodule + + +// -------------------------------------------------------- +// Power +// -------------------------------------------------------- + +module \$pow (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire _TECHMAP_FAIL_ = 1; +endmodule + + +// -------------------------------------------------------- +// Equal and Not-Equal +// -------------------------------------------------------- + +module \$eq (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + assign Y = ~|(A_buf ^ B_buf); +endmodule + +module \$ne (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + assign Y = |(A_buf ^ B_buf); +endmodule + +module \$eqx (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + assign Y = ~|(A_buf ^ B_buf); +endmodule + +module \$nex (A, B, Y); + parameter A_SIGNED = 0; + parameter B_SIGNED = 0; + parameter A_WIDTH = 1; + parameter B_WIDTH = 1; + parameter Y_WIDTH = 1; + + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output [Y_WIDTH-1:0] Y; + + wire carry, carry_sign; + wire [WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + + assign Y = |(A_buf ^ B_buf); +endmodule + + +// -------------------------------------------------------- +// Parallel Multiplexers +// -------------------------------------------------------- + +module \$pmux (A, B, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + input [WIDTH-1:0] A; + input [WIDTH*S_WIDTH-1:0] B; + input [S_WIDTH-1:0] S; + output [WIDTH-1:0] Y; + + wire [WIDTH-1:0] Y_B; + + genvar i, j; + generate + wire [WIDTH*S_WIDTH-1:0] B_AND_S; + for (i = 0; i < S_WIDTH; i = i + 1) begin:B_AND + assign B_AND_S[WIDTH*(i+1)-1:WIDTH*i] = B[WIDTH*(i+1)-1:WIDTH*i] & {WIDTH{S[i]}}; + end:B_AND + for (i = 0; i < WIDTH; i = i + 1) begin:B_OR + wire [S_WIDTH-1:0] B_AND_BITS; + for (j = 0; j < S_WIDTH; j = j + 1) begin:B_AND_BITS_COLLECT + assign B_AND_BITS[j] = B_AND_S[WIDTH*j+i]; + end:B_AND_BITS_COLLECT + assign Y_B[i] = |B_AND_BITS; + end:B_OR + endgenerate + + assign Y = |S ? Y_B : A; +endmodule + +module \$safe_pmux (A, B, S, Y); + parameter WIDTH = 1; + parameter S_WIDTH = 1; + + input [WIDTH-1:0] A; + input [WIDTH*S_WIDTH-1:0] B; + input [S_WIDTH-1:0] S; + output [WIDTH-1:0] Y; + + wire [S_WIDTH-1:0] status_found_first; + wire [S_WIDTH-1:0] status_found_second; + + genvar i; + generate + for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1 + wire pre_first; + if (i > 0) begin:GEN2 + assign pre_first = status_found_first[i-1]; + end:GEN2 else begin:GEN3 + assign pre_first = 0; + end:GEN3 + assign status_found_first[i] = pre_first | S[i]; + assign status_found_second[i] = pre_first & S[i]; + end:GEN1 + endgenerate + + \$pmux #( + .WIDTH(WIDTH), + .S_WIDTH(S_WIDTH) + ) pmux_cell ( + .A(A), + .B(B), + .S(S & {S_WIDTH{~|status_found_second}}), + .Y(Y) + ); +endmodule + -- cgit v1.2.3 From 014a41fcf3463fae881413b4b366c2c2a6fb20de Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 3 Aug 2014 12:40:43 +0200 Subject: Implemented recursive techmap --- 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 54652868a..7f3855ce8 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -167,7 +167,7 @@ module shift_ops_shr_shl_sshl_sshr (A, B, Y); localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; - wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_01_ = "RECURSION; CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; integer i; reg [WIDTH-1:0] buffer; -- cgit v1.2.3 From 312ee00c9e279a91f336acef26dd064c25f42ed5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 7 Aug 2014 16:14:38 +0200 Subject: Added adff2dff.v (for techmap -share_map) --- techlibs/common/Makefile.inc | 6 +++++- techlibs/common/adff2dff.v | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 techlibs/common/adff2dff.v (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 2be27b920..461c1cb44 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -5,7 +5,7 @@ techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib. $(P) cat techlibs/common/simlib.v techlibs/common/simcells.v | $(SED) -rf techlibs/common/blackbox.sed > techlibs/common/blackbox.v.new $(Q) mv techlibs/common/blackbox.v.new techlibs/common/blackbox.v -EXTRA_TARGETS += share/simlib.v share/simcells.v share/techmap.v share/blackbox.v share/pmux2mux.v +EXTRA_TARGETS += share/simlib.v share/simcells.v share/techmap.v share/blackbox.v share/pmux2mux.v share/adff2dff.v share/simlib.v: techlibs/common/simlib.v $(P) mkdir -p share @@ -27,3 +27,7 @@ share/pmux2mux.v: techlibs/common/pmux2mux.v $(P) mkdir -p share $(Q) cp techlibs/common/pmux2mux.v share/pmux2mux.v +share/adff2dff.v: techlibs/common/adff2dff.v + $(P) mkdir -p share + $(Q) cp techlibs/common/adff2dff.v share/adff2dff.v + diff --git a/techlibs/common/adff2dff.v b/techlibs/common/adff2dff.v new file mode 100644 index 000000000..86744d415 --- /dev/null +++ b/techlibs/common/adff2dff.v @@ -0,0 +1,27 @@ +(* techmap_celltype = "$adff" *) +module adff2dff (CLK, ARST, D, Q); + parameter WIDTH = 1; + parameter CLK_POLARITY = 1; + parameter ARST_POLARITY = 1; + parameter ARST_VALUE = 0; + + input CLK, ARST; + input [WIDTH-1:0] D; + output reg [WIDTH-1:0] Q; + wire reg [WIDTH-1:0] NEXT_Q; + + wire [1023:0] _TECHMAP_DO_ = "proc;;"; + + always @* + if (ARST == ARST_POLARITY) + NEXT_Q <= ARST_VALUE; + else + NEXT_Q <= D; + + if (CLK_POLARITY) + always @(posedge CLK) + Q <= NEXT_Q; + else + always @(negedge CLK) + Q <= NEXT_Q; +endmodule -- cgit v1.2.3 From c27120fcbc69f7b942788d72677f34e4a96ab48a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Aug 2014 13:04:28 +0200 Subject: New interface for $__alu in techmap.v --- techlibs/common/techmap.v | 191 +++++++++++++++------------------------------- 1 file changed, 62 insertions(+), 129 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 7f3855ce8..a03ff8ebe 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -266,127 +266,98 @@ module \$__fulladd (A, B, C, X, Y); \$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); endmodule -module \$__alu (A, B, Cin, Y, Cout, Csign); - parameter WIDTH = 1; - - input [WIDTH-1:0] A, B; - input Cin; - - output [WIDTH-1:0] Y; - output Cout, Csign; - - wire [WIDTH:0] carry; - assign carry[0] = Cin; - assign Cout = carry[WIDTH]; - assign Csign = carry[WIDTH-1]; - - genvar i; - generate - for (i = 0; i < WIDTH; i = i + 1) begin:V - \$__fulladd adder ( - .A(A[i]), - .B(B[i]), - .C(carry[i]), - .X(carry[i+1]), - .Y(Y[i]) - ); - end - endgenerate -endmodule - - -// -------------------------------------------------------- -// Compare cells -// -------------------------------------------------------- - -module \$lt (A, B, Y); +module \$__alu (A, B, CI, S, Y, CO, CS); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf, Y_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + // carry in, sub, carry out, carry sign + input CI, S; + output CO, CS; - \$__alu #( - .WIDTH(WIDTH) - ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) - ); + wire [Y_WIDTH-1:0] A_buf, B_buf; + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - // ALU flags - wire cf, of, zf, sf; - assign cf = !carry; - assign of = carry ^ carry_sign; - assign zf = ~|Y_buf; - assign sf = Y_buf[WIDTH-1]; + wire [Y_WIDTH:0] carry; + assign carry[0] = CI; + assign CO = carry[Y_WIDTH]; + assign CS = carry[Y_WIDTH-1]; + genvar i; generate - if (A_SIGNED && B_SIGNED) begin - assign Y = of != sf; - end else begin - assign Y = cf; + for (i = 0; i < Y_WIDTH; i = i + 1) begin:V + \$__fulladd adder ( + .A(A_buf[i]), + .B(S ? !B_buf[i] : B_buf[i]), + .C(carry[i]), + .X(carry[i+1]), + .Y(Y[i]) + ); end endgenerate endmodule -module \$le (A, B, Y); +`define ALU_COMMONS(_width, _ci, _s) """ parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; parameter B_WIDTH = 1; parameter Y_WIDTH = 1; - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + localparam WIDTH = _width; input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf, Y_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + wire alu_co, alu_cs; + wire [WIDTH-1:0] alu_y; \$__alu #( - .WIDTH(WIDTH) + .A_SIGNED(A_SIGNED), + .B_SIGNED(B_SIGNED), + .A_WIDTH(A_WIDTH), + .B_WIDTH(B_WIDTH), + .Y_WIDTH(WIDTH) ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y_buf), - .Cout(carry), - .Csign(carry_sign) + .A(A), + .B(B), + .CI(_ci), + .S(_s), + .Y(alu_y), + .CO(alu_co), + .CS(alu_cs) ); - // ALU flags wire cf, of, zf, sf; - assign cf = !carry; - assign of = carry ^ carry_sign; - assign zf = ~|Y_buf; - assign sf = Y_buf[WIDTH-1]; + assign cf = !alu_co; + assign of = alu_co ^ alu_cs; + assign zf = ~|alu_y; + assign sf = alu_y[WIDTH-1]; +""" - generate - if (A_SIGNED && B_SIGNED) begin - assign Y = zf || (of != sf); - end else begin - assign Y = zf || cf; - end - endgenerate + +// -------------------------------------------------------- +// Compare cells +// -------------------------------------------------------- + +module \$lt (A, B, Y); + wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) + assign Y = A_SIGNED && B_SIGNED ? of != sf : cf; +endmodule + +module \$le (A, B, Y); + wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) + assign Y = zf || (A_SIGNED && B_SIGNED ? of != sf : cf); endmodule @@ -395,53 +366,15 @@ endmodule // -------------------------------------------------------- module \$add (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(Y_WIDTH) - ) alu ( - .A(A_buf), - .B(B_buf), - .Cin(1'b0), - .Y(Y) - ); + wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + `ALU_COMMONS(Y_WIDTH, 0, 0) + assign Y = alu_y; endmodule module \$sub (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__alu #( - .WIDTH(Y_WIDTH) - ) alu ( - .A(A_buf), - .B(~B_buf), - .Cin(1'b1), - .Y(Y) - ); + wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + `ALU_COMMONS(Y_WIDTH, 1, 1) + assign Y = alu_y; endmodule -- cgit v1.2.3 From 9a065509acd53d4fdbfe2e98ab0aba5e6851d8e8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Aug 2014 16:36:30 +0200 Subject: Preparations for lookahead ALU support in techmap.v --- techlibs/common/techmap.v | 120 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 28 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index a03ff8ebe..59f91bc53 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -251,19 +251,91 @@ endmodule // ALU Infrastructure // -------------------------------------------------------- -module \$__fulladd (A, B, C, X, Y); - // {X, Y} = A + B + C - input A, B, C; - output X, Y; +module \$__alu_ripple (A, B, CI, Y, CO, CS); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y; + + input CI; + output CO, CS; + + wire [WIDTH:0] carry; + assign carry[0] = CI; + assign CO = carry[WIDTH]; + assign CS = carry[WIDTH-1]; + + genvar i; + generate + for (i = 0; i < WIDTH; i = i + 1) + begin:V + // {x, y} = a + b + c + wire a, b, c, x, y; + wire t1, t2, t3; + + \$_AND_ gate1 ( .A(a), .B(b), .Y(t1) ); + \$_XOR_ gate2 ( .A(a), .B(b), .Y(t2) ); + \$_AND_ gate3 ( .A(t2), .B(c), .Y(t3) ); + \$_XOR_ gate4 ( .A(t2), .B(c), .Y(y) ); + \$_OR_ gate5 ( .A(t1), .B(t3), .Y(x) ); + + assign a = A[i], b = B[i], c = carry[i]; + assign carry[i+1] = x, Y[i] = y; + end + endgenerate +endmodule + +module \$__lcu (P, G, CI, CO, PG, GG); + parameter WIDTH = 1; + + input [WIDTH-1:0] P, G; + input CI; + + output [WIDTH:0] CO; + output PG, GG; + + assign CO[0] = CI; + assign PG = 'bx, GG = 'bx; + + genvar i; + generate + // TBD: Actually implement a LCU topology + for (i = 0; i < WIDTH; i = i + 1) + assign CO[i+1] = G[i] | (P[i] & CO[i]); + endgenerate +endmodule + +module \$__alu_lookahead (A, B, CI, Y, CO, CS); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B; + output [WIDTH-1:0] Y; - // {t1, t2} = A + B - wire t1, t2, t3; + input CI; + output CO, CS; + + wire [WIDTH-1:0] P, G; + wire [WIDTH:0] C; + + assign CO = C[WIDTH]; + assign CS = C[WIDTH-1]; + + genvar i; + generate + for (i = 0; i < WIDTH; i = i + 1) + begin:V + wire a, b, c, p, g, y; - \$_AND_ gate1 ( .A(A), .B(B), .Y(t1) ); - \$_XOR_ gate2 ( .A(A), .B(B), .Y(t2) ); - \$_AND_ gate3 ( .A(t2), .B(C), .Y(t3) ); - \$_XOR_ gate4 ( .A(t2), .B(C), .Y(Y) ); - \$_OR_ gate5 ( .A(t1), .B(t3), .Y(X) ); + \$_AND_ gate1 ( .A(a), .B(b), .Y(g) ); + \$_XOR_ gate2 ( .A(a), .B(b), .Y(p) ); + \$_XOR_ gate3 ( .A(p), .B(c), .Y(y) ); + + assign a = A[i], b = B[i], c = C[i]; + assign P[i] = p, G[i] = g, Y[i] = y; + end + endgenerate + + \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(C)); endmodule module \$__alu (A, B, CI, S, Y, CO, CS); @@ -285,23 +357,15 @@ module \$__alu (A, B, CI, S, Y, CO, CS); \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - wire [Y_WIDTH:0] carry; - assign carry[0] = CI; - assign CO = carry[Y_WIDTH]; - assign CS = carry[Y_WIDTH-1]; - - genvar i; - generate - for (i = 0; i < Y_WIDTH; i = i + 1) begin:V - \$__fulladd adder ( - .A(A_buf[i]), - .B(S ? !B_buf[i] : B_buf[i]), - .C(carry[i]), - .X(carry[i+1]), - .Y(Y[i]) - ); - end - endgenerate +`ifdef ALU_RIPPLE + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); +`else + if (Y_WIDTH <= 4) begin + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); + end else begin + \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); + end +`endif endmodule `define ALU_COMMONS(_width, _ci, _s) """ -- cgit v1.2.3 From 7e758d5fbba4769ba268229bece7b5c486c61223 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 13 Aug 2014 18:40:57 +0200 Subject: Added techmap support for actual lookahead carry unit --- techlibs/common/techmap.v | 95 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 22 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 59f91bc53..3670bd69f 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -267,7 +267,7 @@ module \$__alu_ripple (A, B, CI, Y, CO, CS); genvar i; generate - for (i = 0; i < WIDTH; i = i + 1) + for (i = 0; i < WIDTH; i = i+1) begin:V // {x, y} = a + b + c wire a, b, c, x, y; @@ -285,23 +285,79 @@ module \$__alu_ripple (A, B, CI, Y, CO, CS); endgenerate endmodule +module \$__lcu_simple (P, G, CI, CO, PG, GG); + parameter WIDTH = 1; + + input [WIDTH-1:0] P, G; + input CI; + + output reg [WIDTH:0] CO; + output reg PG, GG; + + wire [1023:0] _TECHMAP_DO_ = "proc;;"; + + integer i, j; + reg [WIDTH-1:0] tmp; + + always @* begin + PG = &P; + GG = 0; + for (i = 0; i < WIDTH; i = i+1) begin + tmp = ~0; + tmp[i] = G[i]; + for (j = i+1; j < WIDTH; j = j+1) + tmp[j] = P[j]; + GG = GG || &tmp[WIDTH-1:i]; + end + + CO[0] = CI; + for (i = 0; i < WIDTH; i = i+1) + CO[i+1] = G[i] | (P[i] & CO[i]); + end +endmodule + module \$__lcu (P, G, CI, CO, PG, GG); parameter WIDTH = 1; + function integer get_group_size; + begin + get_group_size = 4; + while (4 * get_group_size < WIDTH) + get_group_size = 4 * get_group_size; + end + endfunction + input [WIDTH-1:0] P, G; input CI; output [WIDTH:0] CO; output PG, GG; - assign CO[0] = CI; - assign PG = 'bx, GG = 'bx; - genvar i; generate - // TBD: Actually implement a LCU topology - for (i = 0; i < WIDTH; i = i + 1) - assign CO[i+1] = G[i] | (P[i] & CO[i]); + if (WIDTH <= 4) begin + \$__lcu_simple #(.WIDTH(WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO), .PG(PG), .GG(GG)); + end else begin + localparam GROUP_SIZE = get_group_size(); + localparam GROUPS_NUM = (WIDTH + GROUP_SIZE - 1) / GROUP_SIZE; + + wire [GROUPS_NUM-1:0] groups_p, groups_g; + wire [GROUPS_NUM:0] groups_ci; + + for (i = 0; i < GROUPS_NUM; i = i+1) begin:V + localparam g_size = `MIN(GROUP_SIZE, WIDTH - i*GROUP_SIZE); + localparam g_offset = i*GROUP_SIZE; + wire [g_size:0] g_co; + + \$__lcu #(.WIDTH(g_size)) g (.P(P[g_offset +: g_size]), .G(G[g_offset +: g_size]), + .CI(groups_ci[i]), .CO(g_co), .PG(groups_p[i]), .GG(groups_g[i])); + assign CO[g_offset+1 +: g_size] = g_co[1 +: g_size]; + end + + \$__lcu_simple #(.WIDTH(GROUPS_NUM)) super_lcu (.P(groups_p), .G(groups_g), .CI(CI), .CO(groups_ci), .PG(PG), .GG(GG)); + + assign CO[0] = CI; + end endgenerate endmodule @@ -322,7 +378,7 @@ module \$__alu_lookahead (A, B, CI, Y, CO, CS); genvar i; generate - for (i = 0; i < WIDTH; i = i + 1) + for (i = 0; i < WIDTH; i = i+1) begin:V wire a, b, c, p, g, y; @@ -368,6 +424,11 @@ module \$__alu (A, B, CI, S, Y, CO, CS); `endif endmodule + +// -------------------------------------------------------- +// ALU Cell Types: Compare, Add, Subtract +// -------------------------------------------------------- + `define ALU_COMMONS(_width, _ci, _s) """ parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -407,36 +468,26 @@ endmodule assign sf = alu_y[WIDTH-1]; """ - -// -------------------------------------------------------- -// Compare cells -// -------------------------------------------------------- - module \$lt (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) assign Y = A_SIGNED && B_SIGNED ? of != sf : cf; endmodule module \$le (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) assign Y = zf || (A_SIGNED && B_SIGNED ? of != sf : cf); endmodule - -// -------------------------------------------------------- -// Add and Subtract -// -------------------------------------------------------- - module \$add (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; `ALU_COMMONS(Y_WIDTH, 0, 0) assign Y = alu_y; endmodule module \$sub (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt_const -mux_undef -mux_bool -fine;;;"; + wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; `ALU_COMMONS(Y_WIDTH, 1, 1) assign Y = alu_y; endmodule -- cgit v1.2.3 From 13f2f36884fa3e4a8329dab2556af7000cb085df Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Aug 2014 11:39:46 +0200 Subject: RIP $safe_pmux --- techlibs/common/simlib.v | 31 ++++--------------------------- techlibs/common/techmap.v | 37 ------------------------------------- 2 files changed, 4 insertions(+), 64 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index c2f6cb278..4b3317a76 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -938,39 +938,16 @@ input [S_WIDTH-1:0] S; output reg [WIDTH-1:0] Y; integer i; +reg found_active_sel_bit; always @* begin Y = A; - for (i = 0; i < S_WIDTH; i = i+1) - if (S[i]) - Y = B >> (WIDTH*i); -end - -endmodule - -// -------------------------------------------------------- - -module \$safe_pmux (A, B, S, Y); - -parameter WIDTH = 0; -parameter S_WIDTH = 0; - -input [WIDTH-1:0] A; -input [WIDTH*S_WIDTH-1:0] B; -input [S_WIDTH-1:0] S; -output reg [WIDTH-1:0] Y; - -integer i, j; - -always @* begin - j = 0; + found_active_sel_bit = 0; for (i = 0; i < S_WIDTH; i = i+1) if (S[i]) begin - Y = B >> (WIDTH*i); - j = j + 1; + Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i); + found_active_sel_bit = 1; end - if (j != 1) - Y = A; end endmodule diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 3670bd69f..e1d5bd82f 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -794,40 +794,3 @@ module \$pmux (A, B, S, Y); assign Y = |S ? Y_B : A; endmodule -module \$safe_pmux (A, B, S, Y); - parameter WIDTH = 1; - parameter S_WIDTH = 1; - - input [WIDTH-1:0] A; - input [WIDTH*S_WIDTH-1:0] B; - input [S_WIDTH-1:0] S; - output [WIDTH-1:0] Y; - - wire [S_WIDTH-1:0] status_found_first; - wire [S_WIDTH-1:0] status_found_second; - - genvar i; - generate - for (i = 0; i < S_WIDTH; i = i + 1) begin:GEN1 - wire pre_first; - if (i > 0) begin:GEN2 - assign pre_first = status_found_first[i-1]; - end:GEN2 else begin:GEN3 - assign pre_first = 0; - end:GEN3 - assign status_found_first[i] = pre_first | S[i]; - assign status_found_second[i] = pre_first & S[i]; - end:GEN1 - endgenerate - - \$pmux #( - .WIDTH(WIDTH), - .S_WIDTH(S_WIDTH) - ) pmux_cell ( - .A(A), - .B(B), - .S(S & {S_WIDTH{~|status_found_second}}), - .Y(Y) - ); -endmodule - -- cgit v1.2.3 From 5602cbde9f9f86197511036d8873c0f8fb1ca5d7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Aug 2014 20:53:21 +0200 Subject: Simplified $__arraymul techmap rule --- techlibs/common/techmap.v | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index e1d5bd82f..7a4f6b272 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -502,15 +502,21 @@ module \$__arraymul (A, B, Y); input [WIDTH-1:0] A, B; output [WIDTH-1:0] Y; - wire [WIDTH*WIDTH-1:0] partials; + wire [1023:0] _TECHMAP_DO_ = "proc;;"; - genvar i; - assign partials[WIDTH-1 : 0] = A[0] ? B : 0; - generate for (i = 1; i < WIDTH; i = i+1) begin:gen - assign partials[WIDTH*(i+1)-1 : WIDTH*i] = (A[i] ? B << i : 0) + partials[WIDTH*i-1 : WIDTH*(i-1)]; - end endgenerate + integer i; + reg [WIDTH-1:0] x, y; + + always @* begin + x = B; + y = A[0] ? x : 0; + for (i = 1; i < WIDTH; i = i+1) begin + x = {x[WIDTH-2:0], 1'b0}; + y = y + (A[i] ? x : 0); + end + end - assign Y = partials[WIDTH*WIDTH-1 : WIDTH*(WIDTH-1)]; + assign Y = y; endmodule module \$mul (A, B, Y); -- cgit v1.2.3 From f092b5014895dc5dc62b8103fcedf94cfa9f85a8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 15 Aug 2014 14:11:40 +0200 Subject: Renamed $_INV_ cell type to $_NOT_ --- techlibs/common/simcells.v | 4 ++-- techlibs/common/techmap.v | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index d492c2f15..7c8a47ddd 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -20,12 +20,12 @@ * The internal logic cell simulation library. * * This verilog library contains simple simulation models for the internal - * logic cells ($_INV_ , $_AND_ , ...) that are generated by the default technology + * logic cells ($_NOT_ , $_AND_ , ...) that are generated by the default technology * mapper (see "techmap.v" in this directory) and expected by the "abc" pass. * */ -module \$_INV_ (A, Y); +module \$_NOT_ (A, Y); input A; output Y; assign Y = ~A; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 7a4f6b272..190002c01 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -20,7 +20,7 @@ * The internal logic cell technology mapper. * * This verilog library contains the mapping of internal cells (e.g. $not with - * variable bit width) to the internal logic cells (such as the single bit $_INV_ + * variable bit width) to the internal logic cells (such as the single bit $_NOT_ * gate). Usually this logic network is then mapped to the actual technology * using e.g. the "abc" pass. * -- cgit v1.2.3 From b64b38eea2e9a7de30d6045f069c86bf4446134f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 15 Aug 2014 14:18:40 +0200 Subject: Renamed $lut ports to follow A-Y naming scheme --- techlibs/common/simlib.v | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 4b3317a76..8c0a54e4e 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -955,13 +955,13 @@ endmodule // -------------------------------------------------------- `ifndef SIMLIB_NOLUT -module \$lut (I, O); +module \$lut (A, Y); parameter WIDTH = 0; parameter LUT = 0; -input [WIDTH-1:0] I; -output reg O; +input [WIDTH-1:0] A; +output reg Y; wire lut0_out, lut1_out; @@ -969,18 +969,18 @@ generate if (WIDTH <= 1) begin:simple assign {lut1_out, lut0_out} = LUT; end else begin:complex - \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .I(I[WIDTH-2:0]), .O(lut0_out) ); - \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .I(I[WIDTH-2:0]), .O(lut1_out) ); + \$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 ({I[WIDTH-1], lut0_out, lut1_out}) - 3'b?11: O = 1'b1; - 3'b?00: O = 1'b0; - 3'b0??: O = lut0_out; - 3'b1??: O = lut1_out; - default: O = 1'bx; + 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 -- cgit v1.2.3 From 1ddf150c35aa32f2f6eb35d678feb76b612d7c47 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 16 Aug 2014 16:01:58 +0200 Subject: Changes in techmap $__alu interface --- techlibs/common/techmap.v | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 190002c01..9b733c6f0 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -251,11 +251,11 @@ endmodule // ALU Infrastructure // -------------------------------------------------------- -module \$__alu_ripple (A, B, CI, Y, CO, CS); +module \$__alu_ripple (A, B, CI, X, Y, CO, CS); parameter WIDTH = 1; input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y; + output [WIDTH-1:0] X, Y; input CI; output CO, CS; @@ -280,7 +280,7 @@ module \$__alu_ripple (A, B, CI, Y, CO, CS); \$_OR_ gate5 ( .A(t1), .B(t3), .Y(x) ); assign a = A[i], b = B[i], c = carry[i]; - assign carry[i+1] = x, Y[i] = y; + assign carry[i+1] = x, X[i] = t2, Y[i] = y; end endgenerate endmodule @@ -361,11 +361,11 @@ module \$__lcu (P, G, CI, CO, PG, GG); endgenerate endmodule -module \$__alu_lookahead (A, B, CI, Y, CO, CS); +module \$__alu_lookahead (A, B, CI, X, Y, CO, CS); parameter WIDTH = 1; input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y; + output [WIDTH-1:0] X, Y; input CI; output CO, CS; @@ -387,14 +387,14 @@ module \$__alu_lookahead (A, B, CI, Y, CO, CS); \$_XOR_ gate3 ( .A(p), .B(c), .Y(y) ); assign a = A[i], b = B[i], c = C[i]; - assign P[i] = p, G[i] = g, Y[i] = y; + assign P[i] = p, G[i] = g, X[i] = p, Y[i] = y; end endgenerate \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(C)); endmodule -module \$__alu (A, B, CI, S, Y, CO, CS); +module \$__alu (A, B, CI, BI, X, Y, CO, CS); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -403,10 +403,10 @@ module \$__alu (A, B, CI, S, Y, CO, CS); input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; + output [Y_WIDTH-1:0] X, Y; // carry in, sub, carry out, carry sign - input CI, S; + input CI, BI; output CO, CS; wire [Y_WIDTH-1:0] A_buf, B_buf; @@ -414,12 +414,12 @@ module \$__alu (A, B, CI, S, Y, CO, CS); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); `ifdef ALU_RIPPLE - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); `else if (Y_WIDTH <= 4) begin - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); end else begin - \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(S ? ~B_buf : B_buf), .CI(CI), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); end `endif endmodule @@ -429,7 +429,7 @@ endmodule // ALU Cell Types: Compare, Add, Subtract // -------------------------------------------------------- -`define ALU_COMMONS(_width, _ci, _s) """ +`define ALU_COMMONS(_width, _ci, _bi) """ parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -443,7 +443,7 @@ endmodule output [Y_WIDTH-1:0] Y; wire alu_co, alu_cs; - wire [WIDTH-1:0] alu_y; + wire [WIDTH-1:0] alu_x, alu_y; \$__alu #( .A_SIGNED(A_SIGNED), @@ -455,7 +455,8 @@ endmodule .A(A), .B(B), .CI(_ci), - .S(_s), + .BI(_bi), + .X(alu_x), .Y(alu_y), .CO(alu_co), .CS(alu_cs) @@ -464,7 +465,6 @@ endmodule wire cf, of, zf, sf; assign cf = !alu_co; assign of = alu_co ^ alu_cs; - assign zf = ~|alu_y; assign sf = alu_y[WIDTH-1]; """ @@ -477,7 +477,7 @@ endmodule module \$le (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) - assign Y = zf || (A_SIGNED && B_SIGNED ? of != sf : cf); + assign Y = &alu_x || (A_SIGNED && B_SIGNED ? of != sf : cf); endmodule module \$add (A, B, Y); -- cgit v1.2.3 From 47c2637a961839f1eb1a0386f7e54d94be50bc10 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 16 Aug 2014 18:18:30 +0200 Subject: Added additional gate types: $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_ --- techlibs/common/simcells.v | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v index 7c8a47ddd..a2a377350 100644 --- a/techlibs/common/simcells.v +++ b/techlibs/common/simcells.v @@ -37,24 +37,66 @@ output Y; assign Y = A & B; endmodule +module \$_NAND_ (A, B, Y); +input A, B; +output Y; +assign Y = ~(A & B); +endmodule + module \$_OR_ (A, B, Y); input A, B; output Y; assign Y = A | B; endmodule +module \$_NOR_ (A, B, Y); +input A, B; +output Y; +assign Y = ~(A | B); +endmodule + module \$_XOR_ (A, B, Y); input A, B; output Y; assign Y = A ^ B; endmodule +module \$_XNOR_ (A, B, Y); +input A, B; +output Y; +assign Y = ~(A ^ B); +endmodule + module \$_MUX_ (A, B, S, Y); input A, B, S; output Y; assign Y = S ? B : A; endmodule +module \$_AOI3_ (A, B, C, Y); +input A, B, C; +output Y; +assign Y = ~((A & B) | C); +endmodule + +module \$_OAI3_ (A, B, C, Y); +input A, B, C; +output Y; +assign Y = ~((A | B) & C); +endmodule + +module \$_AOI4_ (A, B, C, D, Y); +input A, B, C, D; +output Y; +assign Y = ~((A & B) | (C & D)); +endmodule + +module \$_OAI4_ (A, B, C, D, Y); +input A, B, C, D; +output Y; +assign Y = ~((A | B) & (C | D)); +endmodule + module \$_SR_NN_ (S, R, Q); input S, R; output reg Q; -- cgit v1.2.3 From 976bda71029b9d25ffad9ec8fbf3ceed2d1287e1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 16 Aug 2014 21:07:29 +0200 Subject: Multiply using a carry-save accumulator --- techlibs/common/techmap.v | 50 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 9b733c6f0..9bdff4f33 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -502,21 +502,61 @@ module \$__arraymul (A, B, Y); input [WIDTH-1:0] A, B; output [WIDTH-1:0] Y; - wire [1023:0] _TECHMAP_DO_ = "proc;;"; + wire [1023:0] _TECHMAP_DO_ = "proc;; opt"; integer i; - reg [WIDTH-1:0] x, y; + reg [WIDTH-1:0] x; + reg [2*WIDTH-1:0] y; + + function [2*WIDTH-1:0] acc_set; + input [WIDTH-1:0] value; + integer k; + begin + for (k = 0; k < WIDTH; k = k+1) begin + acc_set[2*k +: 2] = value[k]; + end + end + endfunction + + function [2*WIDTH-1:0] acc_add; + input [2*WIDTH-1:0] old_acc; + input [WIDTH-1:0] value; + integer k; + reg a, b, c; + begin + for (k = 0; k < WIDTH; k = k+1) begin + a = old_acc[2*k]; + b = k ? old_acc[2*k-1] : 1'b0; + c = value[k]; + acc_add[2*k] = (a ^ b) ^ c; + acc_add[2*k+1] = (a & b) | ((a ^ b) & c); + end + end + endfunction + + function [WIDTH-1:0] acc_get; + input [2*WIDTH-1:0] acc; + integer k; + begin + // at the end of the multiplier chain the carry-save accumulator + // should also have propagated all carries. thus we just need to + // copy the even bits from the carry accumulator to the output. + for (k = 0; k < WIDTH; k = k+1) begin + acc_get[k] = acc[2*k]; + end + end + endfunction always @* begin x = B; - y = A[0] ? x : 0; + y = acc_set(A[0] ? x : 0); for (i = 1; i < WIDTH; i = i+1) begin x = {x[WIDTH-2:0], 1'b0}; - y = y + (A[i] ? x : 0); + y = acc_add(y, A[i] ? x : 0); end end - assign Y = y; + assign Y = acc_get(y); endmodule module \$mul (A, B, Y); -- cgit v1.2.3 From 4b3834e0cc3c34b6845ab50ffd7e9fe396173e8d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 18 Aug 2014 00:03:33 +0200 Subject: Replaced recursive lcu scheme with bk adder --- techlibs/common/techmap.v | 92 ++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 61 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 9bdff4f33..5bbe883ef 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -285,80 +285,50 @@ module \$__alu_ripple (A, B, CI, X, Y, CO, CS); endgenerate endmodule -module \$__lcu_simple (P, G, CI, CO, PG, GG); - parameter WIDTH = 1; +module \$__lcu (P, G, CI, CO); + parameter WIDTH = 2; input [WIDTH-1:0] P, G; input CI; output reg [WIDTH:0] CO; - output reg PG, GG; - wire [1023:0] _TECHMAP_DO_ = "proc;;"; + integer i, j, k; + reg [WIDTH-1:0] p, g; - integer i, j; - reg [WIDTH-1:0] tmp; + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; always @* begin - PG = &P; - GG = 0; - for (i = 0; i < WIDTH; i = i+1) begin - tmp = ~0; - tmp[i] = G[i]; - for (j = i+1; j < WIDTH; j = j+1) - tmp[j] = P[j]; - GG = GG || &tmp[WIDTH-1:i]; - end - - CO[0] = CI; - for (i = 0; i < WIDTH; i = i+1) - CO[i+1] = G[i] | (P[i] & CO[i]); - end -endmodule - -module \$__lcu (P, G, CI, CO, PG, GG); - parameter WIDTH = 1; - - function integer get_group_size; - begin - get_group_size = 4; - while (4 * get_group_size < WIDTH) - get_group_size = 4 * get_group_size; + p = P; + g = G; + + // in almost all cases CI will be constant zero + g[0] = g[0] | (p[0] & CI); + + // [[CITE]] Brent Kung Adder + // R. P. Brent and H. T. Kung, “A Regular Layout for Parallel Adders”, + // IEEE Transaction on Computers, Vol. C-31, No. 3, p. 260-264, March, 1982 + + // Main tree + for (i = 1; i <= $clog2(WIDTH); i = i+1) begin + for (j = 2**i - 1; j < WIDTH; j = j + 2**i) begin + k = j - 2**(i-1); + g[j] = g[j] | p[j] & g[k]; + p[j] = p[j] & p[k]; + end end - endfunction - input [WIDTH-1:0] P, G; - input CI; - - output [WIDTH:0] CO; - output PG, GG; - - genvar i; - generate - if (WIDTH <= 4) begin - \$__lcu_simple #(.WIDTH(WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO), .PG(PG), .GG(GG)); - end else begin - localparam GROUP_SIZE = get_group_size(); - localparam GROUPS_NUM = (WIDTH + GROUP_SIZE - 1) / GROUP_SIZE; - - wire [GROUPS_NUM-1:0] groups_p, groups_g; - wire [GROUPS_NUM:0] groups_ci; - - for (i = 0; i < GROUPS_NUM; i = i+1) begin:V - localparam g_size = `MIN(GROUP_SIZE, WIDTH - i*GROUP_SIZE); - localparam g_offset = i*GROUP_SIZE; - wire [g_size:0] g_co; - - \$__lcu #(.WIDTH(g_size)) g (.P(P[g_offset +: g_size]), .G(G[g_offset +: g_size]), - .CI(groups_ci[i]), .CO(g_co), .PG(groups_p[i]), .GG(groups_g[i])); - assign CO[g_offset+1 +: g_size] = g_co[1 +: g_size]; + // Inverse tree + for (i = $clog2(WIDTH); i > 0; i = i-1) begin + for (j = 2**i + 2**(i-1) - 1; j < WIDTH; j = j + 2**i) begin + k = j - 2**(i-1); + g[j] = g[j] | p[j] & g[k]; + p[j] = p[j] & p[k]; end - - \$__lcu_simple #(.WIDTH(GROUPS_NUM)) super_lcu (.P(groups_p), .G(groups_g), .CI(CI), .CO(groups_ci), .PG(PG), .GG(GG)); - - assign CO[0] = CI; end - endgenerate + end + + assign CO = {g, CI}; endmodule module \$__alu_lookahead (A, B, CI, X, Y, CO, CS); -- cgit v1.2.3 From 6f33fc3e87f5d0429f2236662eb31954e51a71ed Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 18 Aug 2014 00:27:54 +0200 Subject: Performance fix for new $__lcu techmap rule --- techlibs/common/techmap.v | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 5bbe883ef..366351ec0 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -293,7 +293,7 @@ module \$__lcu (P, G, CI, CO); output reg [WIDTH:0] CO; - integer i, j, k; + integer i, j; reg [WIDTH-1:0] p, g; wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; @@ -312,18 +312,16 @@ module \$__lcu (P, G, CI, CO); // Main tree for (i = 1; i <= $clog2(WIDTH); i = i+1) begin for (j = 2**i - 1; j < WIDTH; j = j + 2**i) begin - k = j - 2**(i-1); - g[j] = g[j] | p[j] & g[k]; - p[j] = p[j] & p[k]; + g[j] = g[j] | p[j] & g[j - 2**(i-1)]; + p[j] = p[j] & p[j - 2**(i-1)]; end end // Inverse tree for (i = $clog2(WIDTH); i > 0; i = i-1) begin for (j = 2**i + 2**(i-1) - 1; j < WIDTH; j = j + 2**i) begin - k = j - 2**(i-1); - g[j] = g[j] | p[j] & g[k]; - p[j] = p[j] & p[k]; + g[j] = g[j] | p[j] & g[j - 2**(i-1)]; + p[j] = p[j] & p[j - 2**(i-1)]; end end end -- cgit v1.2.3 From a92a68ce521c1e86c0666b9add0c88d59154325e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 18 Aug 2014 14:30:20 +0200 Subject: Using "via_celltype" in $mul carry-save-acc implementation --- techlibs/common/techmap.v | 106 +++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 34 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 366351ec0..1486b801e 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -465,62 +465,98 @@ endmodule // Multiply // -------------------------------------------------------- -module \$__arraymul (A, B, Y); - parameter WIDTH = 8; +module \$__acc_set (acc_new, value); + parameter WIDTH = 1; + output reg [2*WIDTH-1:0] acc_new; + input [WIDTH-1:0] value; + + wire [1023:0] _TECHMAP_DO_ = "proc;;;"; + + integer k; + always @* begin + for (k = 0; k < WIDTH; k = k+1) begin + acc_new[2*k +: 2] = value[k]; + end + end +endmodule + +module \$__acc_add (acc_new, acc_old, value); + parameter WIDTH = 1; + output reg [2*WIDTH-1:0] acc_new; + input [2*WIDTH-1:0] acc_old; + input [WIDTH-1:0] value; + + wire [1023:0] _TECHMAP_DO_ = "proc; simplemap; opt -purge"; + + integer k; + reg a, b, c; + + always @* begin + for (k = 0; k < WIDTH; k = k+1) begin + a = acc_old[2*k]; + b = k ? acc_old[2*k-1] : 1'b0; + c = value[k]; + acc_new[2*k] = (a ^ b) ^ c; + acc_new[2*k+1] = (a & b) | ((a ^ b) & c); + end + end +endmodule + +module \$__acc_get (value, acc); + parameter WIDTH = 1; + output reg [WIDTH-1:0] value; + input [2*WIDTH-1:0] acc; + + wire [1023:0] _TECHMAP_DO_ = "proc;;;"; + + integer k; + + always @* begin + // at the end of the multiplier chain the carry-save accumulator + // should also have propagated all carries. thus we just need to + // copy the even bits from the carry accumulator to the output. + for (k = 0; k < WIDTH; k = k+1) begin + value[k] = acc[2*k]; + end + end +endmodule + +module \$__acc_mul (A, B, Y); + parameter WIDTH = 1; input [WIDTH-1:0] A, B; output [WIDTH-1:0] Y; - wire [1023:0] _TECHMAP_DO_ = "proc;; opt"; + wire [1023:0] _TECHMAP_DO_ = "proc;;"; integer i; reg [WIDTH-1:0] x; reg [2*WIDTH-1:0] y; + (* via_celltype = "\\$__acc_set acc_new" *) + (* via_celltype_defparam_WIDTH = WIDTH *) function [2*WIDTH-1:0] acc_set; input [WIDTH-1:0] value; - integer k; - begin - for (k = 0; k < WIDTH; k = k+1) begin - acc_set[2*k +: 2] = value[k]; - end - end endfunction + (* via_celltype = "\\$__acc_add acc_new" *) + (* via_celltype_defparam_WIDTH = WIDTH *) function [2*WIDTH-1:0] acc_add; - input [2*WIDTH-1:0] old_acc; + input [2*WIDTH-1:0] acc_old; input [WIDTH-1:0] value; - integer k; - reg a, b, c; - begin - for (k = 0; k < WIDTH; k = k+1) begin - a = old_acc[2*k]; - b = k ? old_acc[2*k-1] : 1'b0; - c = value[k]; - acc_add[2*k] = (a ^ b) ^ c; - acc_add[2*k+1] = (a & b) | ((a ^ b) & c); - end - end endfunction + (* via_celltype = "\\$__acc_get value" *) + (* via_celltype_defparam_WIDTH = WIDTH *) function [WIDTH-1:0] acc_get; input [2*WIDTH-1:0] acc; - integer k; - begin - // at the end of the multiplier chain the carry-save accumulator - // should also have propagated all carries. thus we just need to - // copy the even bits from the carry accumulator to the output. - for (k = 0; k < WIDTH; k = k+1) begin - acc_get[k] = acc[2*k]; - end - end endfunction always @* begin x = B; - y = acc_set(A[0] ? x : 0); + y = acc_set(A[0] ? x : 1'b0); for (i = 1; i < WIDTH; i = i+1) begin x = {x[WIDTH-2:0], 1'b0}; - y = acc_add(y, A[i] ? x : 0); + y = acc_add(y, A[i] ? x : 1'b0); end end @@ -538,13 +574,15 @@ module \$mul (A, B, Y); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; + wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt -purge"; + wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - \$__arraymul #( + \$__acc_mul #( .WIDTH(Y_WIDTH) - ) arraymul ( + ) _TECHMAP_REPLACE_ ( .A(A_buf), .B(B_buf), .Y(Y) -- cgit v1.2.3 From eb571cba6a8a2a53b179578d07798517addac7c0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 30 Aug 2014 15:12:39 +0200 Subject: Replaced $__alu CO/CS outputs with full-width CO output --- techlibs/common/techmap.v | 60 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 1486b801e..452b64b8f 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -251,19 +251,18 @@ endmodule // ALU Infrastructure // -------------------------------------------------------- -module \$__alu_ripple (A, B, CI, X, Y, CO, CS); +module \$__alu_ripple (A, B, CI, X, Y, CO); parameter WIDTH = 1; input [WIDTH-1:0] A, B; output [WIDTH-1:0] X, Y; input CI; - output CO, CS; + output [WIDTH-1:0] CO; wire [WIDTH:0] carry; assign carry[0] = CI; - assign CO = carry[WIDTH]; - assign CS = carry[WIDTH-1]; + assign CO = carry[WIDTH:1]; genvar i; generate @@ -291,7 +290,7 @@ module \$__lcu (P, G, CI, CO); input [WIDTH-1:0] P, G; input CI; - output reg [WIDTH:0] CO; + output [WIDTH-1:0] CO; integer i, j; reg [WIDTH-1:0] p, g; @@ -326,23 +325,20 @@ module \$__lcu (P, G, CI, CO); end end - assign CO = {g, CI}; + assign CO = g; endmodule -module \$__alu_lookahead (A, B, CI, X, Y, CO, CS); +module \$__alu_lookahead (A, B, CI, X, Y, CO); parameter WIDTH = 1; input [WIDTH-1:0] A, B; output [WIDTH-1:0] X, Y; input CI; - output CO, CS; + output [WIDTH-1:0] CO; wire [WIDTH-1:0] P, G; - wire [WIDTH:0] C; - - assign CO = C[WIDTH]; - assign CS = C[WIDTH-1]; + wire [WIDTH:0] carry; genvar i; generate @@ -354,15 +350,16 @@ module \$__alu_lookahead (A, B, CI, X, Y, CO, CS); \$_XOR_ gate2 ( .A(a), .B(b), .Y(p) ); \$_XOR_ gate3 ( .A(p), .B(c), .Y(y) ); - assign a = A[i], b = B[i], c = C[i]; + assign a = A[i], b = B[i], c = carry[i]; assign P[i] = p, G[i] = g, X[i] = p, Y[i] = y; end endgenerate - \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(C)); + \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); + assign carry = {CO, CI}; endmodule -module \$__alu (A, B, CI, BI, X, Y, CO, CS); +module \$__alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -375,19 +372,19 @@ module \$__alu (A, B, CI, BI, X, Y, CO, CS); // carry in, sub, carry out, carry sign input CI, BI; - output CO, CS; + output [Y_WIDTH-1:0] CO; wire [Y_WIDTH-1:0] A_buf, B_buf; \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); `ifdef ALU_RIPPLE - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); `else if (Y_WIDTH <= 4) begin - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); end else begin - \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO), .CS(CS)); + \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); end `endif endmodule @@ -397,7 +394,7 @@ endmodule // ALU Cell Types: Compare, Add, Subtract // -------------------------------------------------------- -`define ALU_COMMONS(_width, _ci, _bi) """ +`define ALU_COMMONS(_width, _sub) """ parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -410,8 +407,8 @@ endmodule input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] Y; - wire alu_co, alu_cs; - wire [WIDTH-1:0] alu_x, alu_y; + wire [WIDTH-1:0] alu_x, alu_y, alu_co; + wire [WIDTH:0] carry = {alu_co, |_sub}; \$__alu #( .A_SIGNED(A_SIGNED), @@ -422,41 +419,40 @@ endmodule ) alu ( .A(A), .B(B), - .CI(_ci), - .BI(_bi), + .CI(|_sub), + .BI(|_sub), .X(alu_x), .Y(alu_y), - .CO(alu_co), - .CS(alu_cs) + .CO(alu_co) ); wire cf, of, zf, sf; - assign cf = !alu_co; - assign of = alu_co ^ alu_cs; + assign cf = !carry[WIDTH]; + assign of = carry[WIDTH] ^ carry[WIDTH-1]; assign sf = alu_y[WIDTH-1]; """ module \$lt (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) + `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1) assign Y = A_SIGNED && B_SIGNED ? of != sf : cf; endmodule module \$le (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1, 1) + `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1) assign Y = &alu_x || (A_SIGNED && B_SIGNED ? of != sf : cf); endmodule module \$add (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(Y_WIDTH, 0, 0) + `ALU_COMMONS(Y_WIDTH, 0) assign Y = alu_y; endmodule module \$sub (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(Y_WIDTH, 1, 1) + `ALU_COMMONS(Y_WIDTH, 1) assign Y = alu_y; endmodule -- cgit v1.2.3 From 4724d94fbce587b39cd7343dc8de3b859311f55c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 30 Aug 2014 18:59:05 +0200 Subject: Added $alu cell type --- techlibs/common/simlib.v | 45 +++++++++++++++++++++++++++++++++++++++++++++ techlibs/common/techmap.v | 5 ++--- 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 8c0a54e4e..09ffa9a68 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -467,6 +467,51 @@ endmodule // -------------------------------------------------------- +module \$alu (A, B, CI, BI, X, Y, CO); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] X, Y; + +input CI, BI; +output [Y_WIDTH-1:0] CO; + +wire [Y_WIDTH-1:0] AA, BB; + +generate + if (A_SIGNED && B_SIGNED) begin:BLOCK1 + assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B); + end else begin:BLOCK2 + assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B); + end +endgenerate + +assign X = AA ^ BB; +assign Y = AA + BB + CI; + +function get_carry; + input a, b, c; + get_carry = (a&b) | (a&c) | (b&c); +endfunction + +genvar i; +generate + assign CO[0] = get_carry(AA[0], BB[0], CI); + for (i = 1; i < Y_WIDTH; i = i+1) begin:BLOCK3 + assign CO[i] = get_carry(AA[i], BB[i], CO[i-1]); + end +endgenerate + +endmodule + +// -------------------------------------------------------- + module \$lt (A, B, Y); parameter A_SIGNED = 0; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 452b64b8f..d6b249456 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -359,7 +359,7 @@ module \$__alu_lookahead (A, B, CI, X, Y, CO); assign carry = {CO, CI}; endmodule -module \$__alu (A, B, CI, BI, X, Y, CO); +module \$alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -370,7 +370,6 @@ module \$__alu (A, B, CI, BI, X, Y, CO); input [B_WIDTH-1:0] B; output [Y_WIDTH-1:0] X, Y; - // carry in, sub, carry out, carry sign input CI, BI; output [Y_WIDTH-1:0] CO; @@ -410,7 +409,7 @@ endmodule wire [WIDTH-1:0] alu_x, alu_y, alu_co; wire [WIDTH:0] carry = {alu_co, |_sub}; - \$__alu #( + \$alu #( .A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), -- cgit v1.2.3 From 8649b57b6f4c3a4322acaf73f5c02d5119629c1e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 31 Aug 2014 17:06:36 +0200 Subject: Added $lut support in test_cell, techmap, satgen --- techlibs/common/techmap.v | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index d6b249456..c0645267d 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -841,3 +841,20 @@ module \$pmux (A, B, S, Y); assign Y = |S ? Y_B : A; endmodule + +// -------------------------------------------------------- +// LUTs +// -------------------------------------------------------- + +`ifndef NOLUT +module \$lut (A, Y); + parameter WIDTH = 1; + parameter LUT = 0; + + input [WIDTH-1:0] A; + output Y; + + assign Y = LUT[A]; +endmodule +`endif + -- cgit v1.2.3 From 9923762461d2bc0822daef76bf0b58e772045bc8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 1 Sep 2014 15:37:56 +0200 Subject: Fixed "test_cell -simlib all" --- techlibs/common/simlib.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 09ffa9a68..3c931c813 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -108,12 +108,13 @@ parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; +wire [Y_WIDTH-1:0] tmp; generate if (A_SIGNED) begin:BLOCK1 - assign Y = -$signed(A); + assign tmp = $signed(A), Y = -tmp; end else begin:BLOCK2 - assign Y = -A; + assign tmp = A, Y = -tmp; end endgenerate -- cgit v1.2.3 From c38283dbd033ba95554600bbaa850de707ab2a78 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 2 Sep 2014 17:48:41 +0200 Subject: Small bug fixes in $not, $neg, and $shiftx models --- techlibs/common/simlib.v | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 3c931c813..09ffa9a68 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -108,13 +108,12 @@ parameter Y_WIDTH = 0; input [A_WIDTH-1:0] A; output [Y_WIDTH-1:0] Y; -wire [Y_WIDTH-1:0] tmp; generate if (A_SIGNED) begin:BLOCK1 - assign tmp = $signed(A), Y = -tmp; + assign Y = -$signed(A); end else begin:BLOCK2 - assign tmp = A, Y = -tmp; + assign Y = -A; end endgenerate -- cgit v1.2.3 From 635b922afeabea8c69ac4e749881b10aeda7448b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 2 Sep 2014 23:21:59 +0200 Subject: Undef-related fixes in simlib $alu model --- techlibs/common/simlib.v | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 09ffa9a68..61215f59e 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -492,8 +492,11 @@ generate end endgenerate +// this is 'x' if Y and CO should be all 'x', and '0' otherwise +wire y_co_undef = ^{A, A, B, B, CI, CI, BI, BI}; + assign X = AA ^ BB; -assign Y = AA + BB + CI; +assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}}; function get_carry; input a, b, c; @@ -502,9 +505,9 @@ endfunction genvar i; generate - assign CO[0] = get_carry(AA[0], BB[0], CI); + assign CO[0] = get_carry(AA[0], BB[0], CI) ^ y_co_undef; for (i = 1; i < Y_WIDTH; i = i+1) begin:BLOCK3 - assign CO[i] = get_carry(AA[i], BB[i], CO[i-1]); + assign CO[i] = get_carry(AA[i], BB[i], CO[i-1]) ^ y_co_undef; end endgenerate -- cgit v1.2.3 From 8927aa6148f5575b2da9bfb76afb4af076fe18f3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 4 Sep 2014 02:07:52 +0200 Subject: Removed $bu0 cell type --- techlibs/common/simlib.v | 24 ------------------------ techlibs/common/techmap.v | 15 +++++---------- 2 files changed, 5 insertions(+), 34 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 61215f59e..17700a61e 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -53,30 +53,6 @@ endgenerate endmodule -// -------------------------------------------------------- - -module \$bu0 (A, Y); - -parameter A_SIGNED = 0; -parameter A_WIDTH = 0; -parameter Y_WIDTH = 0; - -input [A_WIDTH-1:0] A; -output [Y_WIDTH-1:0] Y; - -generate - if (!A_SIGNED && 0 < A_WIDTH && A_WIDTH < Y_WIDTH) begin:BLOCK1 - assign Y[A_WIDTH-1:0] = A; - assign Y[Y_WIDTH-1:A_WIDTH] = 0; - end else if (A_SIGNED) begin:BLOCK2 - assign Y = $signed(A); - end else begin:BLOCK3 - assign Y = A; - end -endgenerate - -endmodule - // -------------------------------------------------------- module \$pos (A, Y); diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index c0645267d..fccbe2f81 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -38,11 +38,6 @@ // Use simplemap for trivial cell types // -------------------------------------------------------- -(* techmap_simplemap *) -(* techmap_celltype = "$pos $bu0" *) -module simplemap_buffers; -endmodule - (* techmap_simplemap *) (* techmap_celltype = "$not $and $or $xor $xnor" *) module simplemap_bool_ops; @@ -59,7 +54,7 @@ module simplemap_logic_ops; endmodule (* techmap_simplemap *) -(* techmap_celltype = "$slice $concat $mux" *) +(* techmap_celltype = "$pos $slice $concat $mux" *) module simplemap_various; endmodule @@ -738,8 +733,8 @@ module \$eq (A, B, Y); wire carry, carry_sign; wire [WIDTH-1:0] A_buf, B_buf; - \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); assign Y = ~|(A_buf ^ B_buf); endmodule @@ -759,8 +754,8 @@ module \$ne (A, B, Y); wire carry, carry_sign; wire [WIDTH-1:0] A_buf, B_buf; - \$bu0 #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$bu0 #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); + \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); + \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); assign Y = |(A_buf ^ B_buf); endmodule -- cgit v1.2.3 From bff4706b62ca73ba0a627eda2ad903b487634cae Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 6 Sep 2014 17:59:12 +0200 Subject: Added $macc simlib model (also use as techmap rule for now) --- techlibs/common/simlib.v | 86 +++++++++++++++++++++++++++++++++++++++++++++++ techlibs/common/techmap.v | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 17700a61e..eabd65951 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -755,6 +755,92 @@ endmodule // -------------------------------------------------------- +module \$macc (A, B, Y); + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + parameter CONFIG = 4'b0000; + parameter CONFIG_WIDTH = 4; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output reg [Y_WIDTH-1:0] Y; + + localparam integer num_bits = CONFIG[3:0]; + localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); + localparam integer num_abits = $clog2(A_WIDTH); + + function [2*num_ports*num_abits-1:0] get_port_offsets; + input [CONFIG_WIDTH-1:0] CONFIG; + integer i, cursor; + begin + cursor = 0; + get_port_offsets = 0; + for (i = 0; i < num_ports; i = i+1) begin + get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; + cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; + get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; + cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; + end + end + endfunction + + localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); + + `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) + `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) + `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) + `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) + `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) + `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) + + integer i, j; + reg [Y_WIDTH-1:0] tmp_a, tmp_b; + + always @* begin + Y = 0; + for (i = 0; i < num_ports; i = i+1) + begin + tmp_a = 0; + tmp_b = 0; + + for (j = 0; j < `PORT_SIZE_A; j = j+1) + tmp_a[j] = A[`PORT_OFFSET_A + j]; + + if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) + for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) + tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; + + for (j = 0; j < `PORT_SIZE_B; j = j+1) + tmp_b[j] = A[`PORT_OFFSET_B + j]; + + if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) + for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) + tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; + + if (`PORT_SIZE_B > 0) + tmp_a = tmp_a * tmp_b; + + if (`PORT_DO_SUBTRACT) + Y = Y - tmp_a; + else + Y = Y + tmp_a; + end + for (i = 0; i < B_WIDTH; i = i+1) begin + Y = Y + B[i]; + end + end + + `undef PORT_IS_SIGNED + `undef PORT_DO_SUBTRACT + `undef PORT_SIZE_A + `undef PORT_SIZE_B + `undef PORT_OFFSET_A + `undef PORT_OFFSET_B +endmodule + +// -------------------------------------------------------- + module \$div (A, B, Y); parameter A_SIGNED = 0; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index fccbe2f81..8237a7372 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -579,6 +579,92 @@ module \$mul (A, B, Y); ); endmodule +module \$macc (A, B, Y); + parameter A_WIDTH = 0; + parameter B_WIDTH = 0; + parameter Y_WIDTH = 0; + parameter CONFIG = 4'b0000; + parameter CONFIG_WIDTH = 4; + + input [A_WIDTH-1:0] A; + input [B_WIDTH-1:0] B; + output reg [Y_WIDTH-1:0] Y; + + wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; + + localparam integer num_bits = CONFIG[3:0]; + localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); + localparam integer num_abits = $clog2(A_WIDTH); + + function [2*num_ports*num_abits-1:0] get_port_offsets; + input [CONFIG_WIDTH-1:0] CONFIG; + integer i, cursor; + begin + cursor = 0; + get_port_offsets = 0; + for (i = 0; i < num_ports; i = i+1) begin + get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; + cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; + get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; + cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; + end + end + endfunction + + localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); + + `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) + `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) + `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) + `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) + `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) + `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) + + integer i, j; + reg [Y_WIDTH-1:0] tmp_a, tmp_b; + + always @* begin + Y = 0; + for (i = 0; i < num_ports; i = i+1) + begin + tmp_a = 0; + tmp_b = 0; + + for (j = 0; j < `PORT_SIZE_A; j = j+1) + tmp_a[j] = A[`PORT_OFFSET_A + j]; + + if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) + for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) + tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; + + for (j = 0; j < `PORT_SIZE_B; j = j+1) + tmp_b[j] = A[`PORT_OFFSET_B + j]; + + if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) + for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) + tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; + + if (`PORT_SIZE_B > 0) + tmp_a = tmp_a * tmp_b; + + if (`PORT_DO_SUBTRACT) + Y = Y - tmp_a; + else + Y = Y + tmp_a; + end + for (i = 0; i < B_WIDTH; i = i+1) begin + Y = Y + B[i]; + end + end + + `undef PORT_IS_SIGNED + `undef PORT_DO_SUBTRACT + `undef PORT_SIZE_A + `undef PORT_SIZE_B + `undef PORT_OFFSET_A + `undef PORT_OFFSET_B +endmodule + // -------------------------------------------------------- // Divide and Modulo -- cgit v1.2.3 From fa64942018a39085301d7f24832ad0ad7b0d22f1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 6 Sep 2014 19:44:11 +0200 Subject: Added $macc SAT model --- techlibs/common/simlib.v | 6 +++--- techlibs/common/techmap.v | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index eabd65951..b1f871d9b 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -771,16 +771,16 @@ module \$macc (A, B, Y); localparam integer num_abits = $clog2(A_WIDTH); function [2*num_ports*num_abits-1:0] get_port_offsets; - input [CONFIG_WIDTH-1:0] CONFIG; + input [CONFIG_WIDTH-1:0] cfg; integer i, cursor; begin cursor = 0; get_port_offsets = 0; for (i = 0; i < num_ports; i = i+1) begin get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; - cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; - cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; end end endfunction diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 8237a7372..f0397858f 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -597,16 +597,16 @@ module \$macc (A, B, Y); localparam integer num_abits = $clog2(A_WIDTH); function [2*num_ports*num_abits-1:0] get_port_offsets; - input [CONFIG_WIDTH-1:0] CONFIG; + input [CONFIG_WIDTH-1:0] cfg; integer i, cursor; begin cursor = 0; get_port_offsets = 0; for (i = 0; i < num_ports; i = i+1) begin get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; - cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; - cursor = cursor + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; end end endfunction -- cgit v1.2.3 From 9329a768181d3765a08c3b264c8b0031b732c0d4 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 6 Sep 2014 20:30:46 +0200 Subject: Various bug fixes (related to $macc model testing) --- techlibs/common/simlib.v | 2 +- techlibs/common/techmap.v | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index b1f871d9b..465efc0a7 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -768,7 +768,7 @@ module \$macc (A, B, Y); localparam integer num_bits = CONFIG[3:0]; localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); - localparam integer num_abits = $clog2(A_WIDTH); + localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; function [2*num_ports*num_abits-1:0] get_port_offsets; input [CONFIG_WIDTH-1:0] cfg; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index f0397858f..3fc6ccb8e 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -594,7 +594,7 @@ module \$macc (A, B, Y); localparam integer num_bits = CONFIG[3:0]; localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); - localparam integer num_abits = $clog2(A_WIDTH); + localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; function [2*num_ports*num_abits-1:0] get_port_offsets; input [CONFIG_WIDTH-1:0] cfg; -- cgit v1.2.3 From dd887cc02544e76f4ff9e57547231391388c1fa1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 7 Sep 2014 18:24:08 +0200 Subject: Using maccmap for $macc and $mul techmap --- techlibs/common/techmap.v | 206 ++++------------------------------------------ 1 file changed, 16 insertions(+), 190 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 3fc6ccb8e..dc52ca5fa 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -455,102 +455,8 @@ endmodule // Multiply // -------------------------------------------------------- -module \$__acc_set (acc_new, value); - parameter WIDTH = 1; - output reg [2*WIDTH-1:0] acc_new; - input [WIDTH-1:0] value; - - wire [1023:0] _TECHMAP_DO_ = "proc;;;"; - - integer k; - always @* begin - for (k = 0; k < WIDTH; k = k+1) begin - acc_new[2*k +: 2] = value[k]; - end - end -endmodule - -module \$__acc_add (acc_new, acc_old, value); - parameter WIDTH = 1; - output reg [2*WIDTH-1:0] acc_new; - input [2*WIDTH-1:0] acc_old; - input [WIDTH-1:0] value; - - wire [1023:0] _TECHMAP_DO_ = "proc; simplemap; opt -purge"; - - integer k; - reg a, b, c; - - always @* begin - for (k = 0; k < WIDTH; k = k+1) begin - a = acc_old[2*k]; - b = k ? acc_old[2*k-1] : 1'b0; - c = value[k]; - acc_new[2*k] = (a ^ b) ^ c; - acc_new[2*k+1] = (a & b) | ((a ^ b) & c); - end - end -endmodule - -module \$__acc_get (value, acc); - parameter WIDTH = 1; - output reg [WIDTH-1:0] value; - input [2*WIDTH-1:0] acc; - - wire [1023:0] _TECHMAP_DO_ = "proc;;;"; - - integer k; - - always @* begin - // at the end of the multiplier chain the carry-save accumulator - // should also have propagated all carries. thus we just need to - // copy the even bits from the carry accumulator to the output. - for (k = 0; k < WIDTH; k = k+1) begin - value[k] = acc[2*k]; - end - end -endmodule - -module \$__acc_mul (A, B, Y); - parameter WIDTH = 1; - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "proc;;"; - - integer i; - reg [WIDTH-1:0] x; - reg [2*WIDTH-1:0] y; - - (* via_celltype = "\\$__acc_set acc_new" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [2*WIDTH-1:0] acc_set; - input [WIDTH-1:0] value; - endfunction - - (* via_celltype = "\\$__acc_add acc_new" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [2*WIDTH-1:0] acc_add; - input [2*WIDTH-1:0] acc_old; - input [WIDTH-1:0] value; - endfunction - - (* via_celltype = "\\$__acc_get value" *) - (* via_celltype_defparam_WIDTH = WIDTH *) - function [WIDTH-1:0] acc_get; - input [2*WIDTH-1:0] acc; - endfunction - - always @* begin - x = B; - y = acc_set(A[0] ? x : 1'b0); - for (i = 1; i < WIDTH; i = i+1) begin - x = {x[WIDTH-2:0], 1'b0}; - y = acc_add(y, A[i] ? x : 1'b0); - end - end - - assign Y = acc_get(y); +(* techmap_maccmap *) +module \$macc ; endmodule module \$mul (A, B, Y); @@ -566,105 +472,25 @@ module \$mul (A, B, Y); wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt -purge"; - wire [Y_WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - - \$__acc_mul #( - .WIDTH(Y_WIDTH) + localparam [ 3:0] CONFIG_WIDTH_BITS = 15; + localparam [ 0:0] CONFIG_IS_SIGNED = A_SIGNED && B_SIGNED; + localparam [ 0:0] CONFIG_DO_SUBTRACT = 0; + localparam [14:0] CONFIG_A_WIDTH = A_WIDTH; + localparam [14:0] CONFIG_B_WIDTH = B_WIDTH; + + \$macc #( + .CONFIG({CONFIG_B_WIDTH, CONFIG_A_WIDTH, CONFIG_DO_SUBTRACT, CONFIG_IS_SIGNED, CONFIG_WIDTH_BITS}), + .CONFIG_WIDTH(15 + 15 + 2 + 4), + .A_WIDTH(B_WIDTH + A_WIDTH), + .B_WIDTH(0), + .Y_WIDTH(Y_WIDTH) ) _TECHMAP_REPLACE_ ( - .A(A_buf), - .B(B_buf), + .A({B, A}), + .B(), .Y(Y) ); endmodule -module \$macc (A, B, Y); - parameter A_WIDTH = 0; - parameter B_WIDTH = 0; - parameter Y_WIDTH = 0; - parameter CONFIG = 4'b0000; - parameter CONFIG_WIDTH = 4; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output reg [Y_WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast"; - - localparam integer num_bits = CONFIG[3:0]; - localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); - localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; - - function [2*num_ports*num_abits-1:0] get_port_offsets; - input [CONFIG_WIDTH-1:0] cfg; - integer i, cursor; - begin - cursor = 0; - get_port_offsets = 0; - for (i = 0; i < num_ports; i = i+1) begin - get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; - get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; - end - end - endfunction - - localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); - - `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) - `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) - `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) - `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) - `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) - `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) - - integer i, j; - reg [Y_WIDTH-1:0] tmp_a, tmp_b; - - always @* begin - Y = 0; - for (i = 0; i < num_ports; i = i+1) - begin - tmp_a = 0; - tmp_b = 0; - - for (j = 0; j < `PORT_SIZE_A; j = j+1) - tmp_a[j] = A[`PORT_OFFSET_A + j]; - - if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) - for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) - tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; - - for (j = 0; j < `PORT_SIZE_B; j = j+1) - tmp_b[j] = A[`PORT_OFFSET_B + j]; - - if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) - for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) - tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; - - if (`PORT_SIZE_B > 0) - tmp_a = tmp_a * tmp_b; - - if (`PORT_DO_SUBTRACT) - Y = Y - tmp_a; - else - Y = Y + tmp_a; - end - for (i = 0; i < B_WIDTH; i = i+1) begin - Y = Y + B[i]; - end - end - - `undef PORT_IS_SIGNED - `undef PORT_DO_SUBTRACT - `undef PORT_SIZE_A - `undef PORT_SIZE_B - `undef PORT_OFFSET_A - `undef PORT_OFFSET_B -endmodule - // -------------------------------------------------------- // Divide and Modulo -- cgit v1.2.3 From d46bac330520f91ee5bf8027abe98a8f9389f696 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 12:15:39 +0200 Subject: Added "$fa" cell type --- techlibs/common/simlib.v | 16 ++++++++++++++++ techlibs/common/techmap.v | 12 ++++++++++++ 2 files changed, 28 insertions(+) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 465efc0a7..c170945ea 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -443,6 +443,22 @@ endmodule // -------------------------------------------------------- +module \$fa (A, B, C, X, Y); + +parameter WIDTH = 1; + +input [WIDTH-1:0] A, B, C; +output [WIDTH-1:0] X, Y; + +wire [WIDTH-1:0] t1, t2, t3; + +assign t1 = A ^ B, t2 = A & B, t3 = C & t1; +assign Y = t1 ^ C, X = t2 | t3; + +endmodule + +// -------------------------------------------------------- + module \$alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index dc52ca5fa..050746376 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -246,6 +246,18 @@ endmodule // ALU Infrastructure // -------------------------------------------------------- +module \$fa (A, B, C, X, Y); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B, C; + output [WIDTH-1:0] X, Y; + + wire [WIDTH-1:0] t1, t2, t3; + + assign t1 = A ^ B, t2 = A & B, t3 = C & t1; + assign Y = t1 ^ C, X = t2 | t3; +endmodule + module \$__alu_ripple (A, B, CI, X, Y, CO); parameter WIDTH = 1; -- cgit v1.2.3 From af0c8873bbc13eea10b3d705061b4cf68fe27c17 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 13:28:23 +0200 Subject: Added $lcu cell type --- techlibs/common/simlib.v | 23 +++++++++++++ techlibs/common/techmap.v | 82 +++++------------------------------------------ 2 files changed, 31 insertions(+), 74 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index c170945ea..1b67f3257 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -459,6 +459,29 @@ endmodule // -------------------------------------------------------- +module \$lcu (P, G, CI, CO); + +parameter WIDTH = 1; + +input [WIDTH-1:0] P, G; +input CI; + +output reg [WIDTH-1:0] CO; + +integer i; +always @* begin + CO = 'bx; + if (^{P, G, CI} !== 1'bx) begin + CO[0] = G[0] || (P[0] && CI); + for (i = 1; i < WIDTH; i = i+1) + CO[i] = G[i] || (P[i] && CO[i-1]); + end +end + +endmodule + +// -------------------------------------------------------- + module \$alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 050746376..491511dbc 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -258,40 +258,7 @@ module \$fa (A, B, C, X, Y); assign Y = t1 ^ C, X = t2 | t3; endmodule -module \$__alu_ripple (A, B, CI, X, Y, CO); - parameter WIDTH = 1; - - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] X, Y; - - input CI; - output [WIDTH-1:0] CO; - - wire [WIDTH:0] carry; - assign carry[0] = CI; - assign CO = carry[WIDTH:1]; - - genvar i; - generate - for (i = 0; i < WIDTH; i = i+1) - begin:V - // {x, y} = a + b + c - wire a, b, c, x, y; - wire t1, t2, t3; - - \$_AND_ gate1 ( .A(a), .B(b), .Y(t1) ); - \$_XOR_ gate2 ( .A(a), .B(b), .Y(t2) ); - \$_AND_ gate3 ( .A(t2), .B(c), .Y(t3) ); - \$_XOR_ gate4 ( .A(t2), .B(c), .Y(y) ); - \$_OR_ gate5 ( .A(t1), .B(t3), .Y(x) ); - - assign a = A[i], b = B[i], c = carry[i]; - assign carry[i+1] = x, X[i] = t2, Y[i] = y; - end - endgenerate -endmodule - -module \$__lcu (P, G, CI, CO); +module \$lcu (P, G, CI, CO); parameter WIDTH = 2; input [WIDTH-1:0] P, G; @@ -335,37 +302,6 @@ module \$__lcu (P, G, CI, CO); assign CO = g; endmodule -module \$__alu_lookahead (A, B, CI, X, Y, CO); - parameter WIDTH = 1; - - input [WIDTH-1:0] A, B; - output [WIDTH-1:0] X, Y; - - input CI; - output [WIDTH-1:0] CO; - - wire [WIDTH-1:0] P, G; - wire [WIDTH:0] carry; - - genvar i; - generate - for (i = 0; i < WIDTH; i = i+1) - begin:V - wire a, b, c, p, g, y; - - \$_AND_ gate1 ( .A(a), .B(b), .Y(g) ); - \$_XOR_ gate2 ( .A(a), .B(b), .Y(p) ); - \$_XOR_ gate3 ( .A(p), .B(c), .Y(y) ); - - assign a = A[i], b = B[i], c = carry[i]; - assign P[i] = p, G[i] = g, X[i] = p, Y[i] = y; - end - endgenerate - - \$__lcu #(.WIDTH(WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); - assign carry = {CO, CI}; -endmodule - module \$alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; parameter B_SIGNED = 0; @@ -384,15 +320,13 @@ module \$alu (A, B, CI, BI, X, Y, CO); \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); -`ifdef ALU_RIPPLE - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); -`else - if (Y_WIDTH <= 4) begin - \$__alu_ripple #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); - end else begin - \$__alu_lookahead #(.WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_buf), .B(BI ? ~B_buf : B_buf), .CI(CI), .X(X), .Y(Y), .CO(CO)); - end -`endif + wire [Y_WIDTH-1:0] AA = A_buf; + wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; + + \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); + + assign X = AA ^ BB; + assign Y = X ^ {CO, CI}; endmodule -- cgit v1.2.3 From 6dc07eb1f23757b17b6d856c95d0901d751eeb25 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 13:29:13 +0200 Subject: Fixes and cleanups for blackbox.v --- techlibs/common/blackbox.sed | 5 +- techlibs/common/simlib.v | 138 ++++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 70 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/blackbox.sed b/techlibs/common/blackbox.sed index 21693ecdd..db8900344 100644 --- a/techlibs/common/blackbox.sed +++ b/techlibs/common/blackbox.sed @@ -1,4 +1,5 @@ #!/bin/sed -r -/^(wire|assign|reg|event)/ d; -/^(genvar|generate|always|initial)/,/^end/ d; +/^(wire|assign|reg|event|integer|localparam|\/\/|[\/ ]\*| *$|`)/ d; +/^(genvar|generate|always|initial|task|function)/,/^end/ d; +/^endmodule/ s/$/\n/; s/ reg / /; diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 1b67f3257..da745b5e0 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -795,87 +795,89 @@ endmodule // -------------------------------------------------------- module \$macc (A, B, Y); - parameter A_WIDTH = 0; - parameter B_WIDTH = 0; - parameter Y_WIDTH = 0; - parameter CONFIG = 4'b0000; - parameter CONFIG_WIDTH = 4; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output reg [Y_WIDTH-1:0] Y; - - localparam integer num_bits = CONFIG[3:0]; - localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); - localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; - - function [2*num_ports*num_abits-1:0] get_port_offsets; - input [CONFIG_WIDTH-1:0] cfg; - integer i, cursor; - begin - cursor = 0; - get_port_offsets = 0; - for (i = 0; i < num_ports; i = i+1) begin - get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; - get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; - cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; - end + +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; +parameter CONFIG = 4'b0000; +parameter CONFIG_WIDTH = 4; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output reg [Y_WIDTH-1:0] Y; + +localparam integer num_bits = CONFIG[3:0]; +localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); +localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; + +function [2*num_ports*num_abits-1:0] get_port_offsets; + input [CONFIG_WIDTH-1:0] cfg; + integer i, cursor; + begin + cursor = 0; + get_port_offsets = 0; + for (i = 0; i < num_ports; i = i+1) begin + get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; + get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; + cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; end - endfunction + end +endfunction - localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); +localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); - `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) - `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) - `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) - `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) - `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) - `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) +`define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) +`define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) +`define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) +`define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) +`define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) +`define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) - integer i, j; - reg [Y_WIDTH-1:0] tmp_a, tmp_b; +integer i, j; +reg [Y_WIDTH-1:0] tmp_a, tmp_b; - always @* begin - Y = 0; - for (i = 0; i < num_ports; i = i+1) - begin - tmp_a = 0; - tmp_b = 0; +always @* begin + Y = 0; + for (i = 0; i < num_ports; i = i+1) + begin + tmp_a = 0; + tmp_b = 0; - for (j = 0; j < `PORT_SIZE_A; j = j+1) - tmp_a[j] = A[`PORT_OFFSET_A + j]; + for (j = 0; j < `PORT_SIZE_A; j = j+1) + tmp_a[j] = A[`PORT_OFFSET_A + j]; - if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) - for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) - tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; + if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) + for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) + tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; - for (j = 0; j < `PORT_SIZE_B; j = j+1) - tmp_b[j] = A[`PORT_OFFSET_B + j]; + for (j = 0; j < `PORT_SIZE_B; j = j+1) + tmp_b[j] = A[`PORT_OFFSET_B + j]; - if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) - for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) - tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; + if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) + for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) + tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; - if (`PORT_SIZE_B > 0) - tmp_a = tmp_a * tmp_b; + if (`PORT_SIZE_B > 0) + tmp_a = tmp_a * tmp_b; - if (`PORT_DO_SUBTRACT) - Y = Y - tmp_a; - else - Y = Y + tmp_a; - end - for (i = 0; i < B_WIDTH; i = i+1) begin - Y = Y + B[i]; - end + if (`PORT_DO_SUBTRACT) + Y = Y - tmp_a; + else + Y = Y + tmp_a; + end + for (i = 0; i < B_WIDTH; i = i+1) begin + Y = Y + B[i]; end +end + +`undef PORT_IS_SIGNED +`undef PORT_DO_SUBTRACT +`undef PORT_SIZE_A +`undef PORT_SIZE_B +`undef PORT_OFFSET_A +`undef PORT_OFFSET_B - `undef PORT_IS_SIGNED - `undef PORT_DO_SUBTRACT - `undef PORT_SIZE_A - `undef PORT_SIZE_B - `undef PORT_OFFSET_A - `undef PORT_OFFSET_B endmodule // -------------------------------------------------------- -- cgit v1.2.3 From fcb46138cebd57587d35489cef3a3a48ebe40bcf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 16:59:39 +0200 Subject: Simplified $fa undef model --- techlibs/common/simlib.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index da745b5e0..dd12bd39f 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -453,7 +453,7 @@ output [WIDTH-1:0] X, Y; wire [WIDTH-1:0] t1, t2, t3; assign t1 = A ^ B, t2 = A & B, t3 = C & t1; -assign Y = t1 ^ C, X = t2 | t3; +assign Y = t1 ^ C, X = (t2 | t3) ^ (Y ^ Y); endmodule -- cgit v1.2.3 From 44b5bd4b631874e5ed083d5de75f5b87431f935f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 17:09:39 +0200 Subject: Fixed simlib $macc model for xilinx xsim --- techlibs/common/simlib.v | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index dd12bd39f..0ad8d14b2 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -806,9 +806,23 @@ input [A_WIDTH-1:0] A; input [B_WIDTH-1:0] B; output reg [Y_WIDTH-1:0] Y; +// Xilinx XSIM does not like $clog2() below.. +function integer my_clog2; + input integer v; + begin + if (v > 0) + v = v - 1; + my_clog2 = 0; + while (v) begin + v = v >> 1; + my_clog2 = my_clog2 + 1; + end + end +endfunction + localparam integer num_bits = CONFIG[3:0]; localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); -localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1; +localparam integer num_abits = my_clog2(A_WIDTH) > 0 ? my_clog2(A_WIDTH) : 1; function [2*num_ports*num_abits-1:0] get_port_offsets; input [CONFIG_WIDTH-1:0] cfg; -- cgit v1.2.3 From 923bbbeaf049d2c5386765cb4fe62014a1770204 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Sep 2014 14:50:15 +0200 Subject: Using alumacc in techmap.v --- techlibs/common/techmap.v | 270 ++++++---------------------------------------- 1 file changed, 33 insertions(+), 237 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 491511dbc..b6c075b67 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -40,101 +40,27 @@ (* techmap_simplemap *) (* techmap_celltype = "$not $and $or $xor $xnor" *) -module simplemap_bool_ops; +module _90_simplemap_bool_ops; endmodule (* techmap_simplemap *) (* techmap_celltype = "$reduce_and $reduce_or $reduce_xor $reduce_xnor $reduce_bool" *) -module simplemap_reduce_ops; +module _90_simplemap_reduce_ops; endmodule (* techmap_simplemap *) (* techmap_celltype = "$logic_not $logic_and $logic_or" *) -module simplemap_logic_ops; +module _90_simplemap_logic_ops; endmodule (* techmap_simplemap *) (* techmap_celltype = "$pos $slice $concat $mux" *) -module simplemap_various; +module _90_simplemap_various; endmodule (* techmap_simplemap *) (* techmap_celltype = "$sr $dff $adff $dffsr $dlatch" *) -module simplemap_registers; -endmodule - - -// -------------------------------------------------------- -// Trivial substitutions -// -------------------------------------------------------- - -module \$neg (A, Y); - parameter A_SIGNED = 0; - parameter A_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - output [Y_WIDTH-1:0] Y; - - \$sub #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(A_SIGNED), - .A_WIDTH(1), - .B_WIDTH(A_WIDTH), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A(1'b0), - .B(A), - .Y(Y) - ); -endmodule - -module \$ge (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$le #( - .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) - ); -endmodule - -module \$gt (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - \$lt #( - .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) - ); +module _90_simplemap_registers; endmodule @@ -143,7 +69,7 @@ endmodule // -------------------------------------------------------- (* techmap_celltype = "$shr $shl $sshl $sshr" *) -module shift_ops_shr_shl_sshl_sshr (A, B, Y); +module _90_shift_ops_shr_shl_sshl_sshr (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -187,7 +113,7 @@ module shift_ops_shr_shl_sshl_sshr (A, B, Y); endmodule (* techmap_celltype = "$shift $shiftx" *) -module shift_shiftx (A, B, Y); +module _90_shift_shiftx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -243,10 +169,11 @@ endmodule // -------------------------------------------------------- -// ALU Infrastructure +// Arithmetic operators // -------------------------------------------------------- -module \$fa (A, B, C, X, Y); +(* techmap_celltype = "$fa" *) +module _90_fa (A, B, C, X, Y); parameter WIDTH = 1; input [WIDTH-1:0] A, B, C; @@ -258,7 +185,8 @@ module \$fa (A, B, C, X, Y); assign Y = t1 ^ C, X = t2 | t3; endmodule -module \$lcu (P, G, CI, CO); +(* techmap_celltype = "$lcu" *) +module _90_lcu (P, G, CI, CO); parameter WIDTH = 2; input [WIDTH-1:0] P, G; @@ -302,7 +230,8 @@ module \$lcu (P, G, CI, CO); assign CO = g; endmodule -module \$alu (A, B, CI, BI, X, Y, CO); +(* techmap_celltype = "$alu" *) +module _90_alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -329,112 +258,14 @@ module \$alu (A, B, CI, BI, X, Y, CO); assign Y = X ^ {CO, CI}; endmodule - -// -------------------------------------------------------- -// ALU Cell Types: Compare, Add, Subtract -// -------------------------------------------------------- - -`define ALU_COMMONS(_width, _sub) """ - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = _width; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [WIDTH-1:0] alu_x, alu_y, alu_co; - wire [WIDTH:0] carry = {alu_co, |_sub}; - - \$alu #( - .A_SIGNED(A_SIGNED), - .B_SIGNED(B_SIGNED), - .A_WIDTH(A_WIDTH), - .B_WIDTH(B_WIDTH), - .Y_WIDTH(WIDTH) - ) alu ( - .A(A), - .B(B), - .CI(|_sub), - .BI(|_sub), - .X(alu_x), - .Y(alu_y), - .CO(alu_co) - ); - - wire cf, of, zf, sf; - assign cf = !carry[WIDTH]; - assign of = carry[WIDTH] ^ carry[WIDTH-1]; - assign sf = alu_y[WIDTH-1]; -""" - -module \$lt (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1) - assign Y = A_SIGNED && B_SIGNED ? of != sf : cf; -endmodule - -module \$le (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(`MAX(A_WIDTH, B_WIDTH), 1) - assign Y = &alu_x || (A_SIGNED && B_SIGNED ? of != sf : cf); -endmodule - -module \$add (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(Y_WIDTH, 0) - assign Y = alu_y; -endmodule - -module \$sub (A, B, Y); - wire [1023:0] _TECHMAP_DO_ = "RECURSION; opt_const -mux_undef -mux_bool -fine;;;"; - `ALU_COMMONS(Y_WIDTH, 1) - assign Y = alu_y; -endmodule - - -// -------------------------------------------------------- -// Multiply -// -------------------------------------------------------- - (* techmap_maccmap *) -module \$macc ; +(* techmap_celltype = "$macc" *) +module _90_macc; endmodule -module \$mul (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire [1023:0] _TECHMAP_DO_ = "RECURSION; CONSTMAP; opt -purge"; - - localparam [ 3:0] CONFIG_WIDTH_BITS = 15; - localparam [ 0:0] CONFIG_IS_SIGNED = A_SIGNED && B_SIGNED; - localparam [ 0:0] CONFIG_DO_SUBTRACT = 0; - localparam [14:0] CONFIG_A_WIDTH = A_WIDTH; - localparam [14:0] CONFIG_B_WIDTH = B_WIDTH; - - \$macc #( - .CONFIG({CONFIG_B_WIDTH, CONFIG_A_WIDTH, CONFIG_DO_SUBTRACT, CONFIG_IS_SIGNED, CONFIG_WIDTH_BITS}), - .CONFIG_WIDTH(15 + 15 + 2 + 4), - .A_WIDTH(B_WIDTH + A_WIDTH), - .B_WIDTH(0), - .Y_WIDTH(Y_WIDTH) - ) _TECHMAP_REPLACE_ ( - .A({B, A}), - .B(), - .Y(Y) - ); +(* techmap_wrap = "alumacc" *) +(* techmap_celltype = "$lt $le $ge $gt $add $sub $neg $mul" *) +module _90_alumacc; endmodule @@ -504,7 +335,8 @@ module \$__div_mod (A, B, Y, R); assign R = A_SIGNED && B_SIGNED && A_buf[WIDTH-1] ? -R_u : R_u; endmodule -module \$div (A, B, Y); +(* techmap_celltype = "$div" *) +module _90_div (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -528,7 +360,8 @@ module \$div (A, B, Y); ); endmodule -module \$mod (A, B, Y); +(* techmap_celltype = "$mod" *) +module _90_mod (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -557,7 +390,8 @@ endmodule // Power // -------------------------------------------------------- -module \$pow (A, B, Y); +(* techmap_celltype = "$pow" *) +module _90_pow (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -576,49 +410,8 @@ endmodule // Equal and Not-Equal // -------------------------------------------------------- -module \$eq (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = ~|(A_buf ^ B_buf); -endmodule - -module \$ne (A, B, Y); - parameter A_SIGNED = 0; - parameter B_SIGNED = 0; - parameter A_WIDTH = 1; - parameter B_WIDTH = 1; - parameter Y_WIDTH = 1; - - localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; - - input [A_WIDTH-1:0] A; - input [B_WIDTH-1:0] B; - output [Y_WIDTH-1:0] Y; - - wire carry, carry_sign; - wire [WIDTH-1:0] A_buf, B_buf; - \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf)); - \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf)); - - assign Y = |(A_buf ^ B_buf); -endmodule - -module \$eqx (A, B, Y); +(* techmap_celltype = "$eq $eqx" *) +module _90_eq_eqx (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -639,7 +432,8 @@ module \$eqx (A, B, Y); assign Y = ~|(A_buf ^ B_buf); endmodule -module \$nex (A, B, Y); +(* techmap_celltype = "$ne $nex" *) +module _90_ne_nex (A, B, Y); parameter A_SIGNED = 0; parameter B_SIGNED = 0; parameter A_WIDTH = 1; @@ -665,7 +459,8 @@ endmodule // Parallel Multiplexers // -------------------------------------------------------- -module \$pmux (A, B, S, Y); +(* techmap_celltype = "$pmux" *) +module _90_pmux (A, B, S, Y); parameter WIDTH = 1; parameter S_WIDTH = 1; @@ -700,7 +495,8 @@ endmodule // -------------------------------------------------------- `ifndef NOLUT -module \$lut (A, Y); +(* techmap_celltype = "$lut" *) +module _90_lut (A, Y); parameter WIDTH = 1; parameter LUT = 0; -- cgit v1.2.3 From 7815f81c320a025c5b92677e375c12951dcbd14b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 14 Sep 2014 16:09:06 +0200 Subject: Added "synth" command --- techlibs/common/Makefile.inc | 2 + techlibs/common/synth.cc | 152 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 techlibs/common/synth.cc (limited to 'techlibs/common') diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index 461c1cb44..7c8cc2f66 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -1,4 +1,6 @@ +OBJS += techlibs/common/synth.o + EXTRA_TARGETS += techlibs/common/blackbox.v techlibs/common/blackbox.v: techlibs/common/blackbox.sed techlibs/common/simlib.v techlibs/common/simcells.v diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc new file mode 100644 index 000000000..95221afa9 --- /dev/null +++ b/techlibs/common/synth.cc @@ -0,0 +1,152 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +static bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) +{ + if (!run_from.empty() && run_from == run_to) { + active = (label == run_from); + } else { + if (label == run_from) + active = true; + if (label == run_to) + active = false; + } + return active; +} + +struct SynthPass : public Pass { + SynthPass() : Pass("synth", "generic synthesis script") { } + virtual void help() + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth [options]\n"); + log("\n"); + log("This command runs the default synthesis script. This command does not operate\n"); + log("on partly selected designs.\n"); + log("\n"); + log(" -top \n"); + log(" use the specified module as top module (default='top')\n"); + log("\n"); + log(" -run [:]\n"); + log(" only run the commands between the labels (see below). an empty\n"); + log(" from label is synonymous to 'begin', and empty to label is\n"); + log(" synonymous to the end of the command list.\n"); + log("\n"); + log("\n"); + log("The following commands are executed by this synthesis command:\n"); + log("\n"); + log(" begin:\n"); + log(" hierarchy -check [-top ]\n"); + log("\n"); + log(" coarse:\n"); + log(" proc\n"); + log(" opt\n"); + log(" wreduce\n"); + log(" alumacc\n"); + log(" share\n"); + log(" opt -fast\n"); + log(" fsm\n"); + log(" opt -fast\n"); + log(" memory\n"); + log("\n"); + log(" fine:\n"); + log(" techmap\n"); + log(" opt -fast\n"); + #ifdef YOSYS_ENABLE_ABC + log(" abc\n"); + #endif + log(" clean\n"); + log("\n"); + } + virtual void execute(std::vector args, RTLIL::Design *design) + { + std::string top_module; + std::string run_from, run_to; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-top" && argidx+1 < args.size()) { + top_module = args[++argidx]; + continue; + } + if (args[argidx] == "-run" && argidx+1 < args.size()) { + size_t pos = args[argidx+1].find(':'); + if (pos == std::string::npos) { + run_from = args[++argidx]; + run_to = args[argidx]; + } else { + run_from = args[++argidx].substr(0, pos); + run_to = args[argidx].substr(pos+1); + } + continue; + } + break; + } + extra_args(args, argidx, design); + + if (!design->full_selection()) + log_cmd_error("This comannd only operates on fully selected designs!\n"); + + bool active = run_from.empty(); + + log_header("Executing SYNTH pass.\n"); + log_push(); + + if (check_label(active, run_from, run_to, "begin")) + { + if (top_module.empty()) + Pass::call(design, stringf("hierarchy -check")); + else + Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str())); + } + + if (check_label(active, run_from, run_to, "coarse")) + { + Pass::call(design, "proc"); + Pass::call(design, "opt"); + Pass::call(design, "wreduce"); + Pass::call(design, "alumacc"); + Pass::call(design, "share"); + Pass::call(design, "opt -fast"); + Pass::call(design, "fsm"); + Pass::call(design, "opt -fast"); + Pass::call(design, "memory"); + } + + if (check_label(active, run_from, run_to, "fine")) + { + Pass::call(design, "techmap"); + Pass::call(design, "opt -fast"); + #ifdef YOSYS_ENABLE_ABC + Pass::call(design, "abc"); + #endif + Pass::call(design, "clean"); + } + + log_pop(); + } +} SynthPass; + -- cgit v1.2.3 From 6644e27cd4112070eca0958c19b71e97ba29a80d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 16 Sep 2014 08:19:35 +0200 Subject: Fixed $macc simlib model for zero-config --- techlibs/common/simlib.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'techlibs/common') diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 0ad8d14b2..2d8088adb 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -820,7 +820,7 @@ function integer my_clog2; end endfunction -localparam integer num_bits = CONFIG[3:0]; +localparam integer num_bits = CONFIG[3:0] > 0 ? CONFIG[3:0] : 1; localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); localparam integer num_abits = my_clog2(A_WIDTH) > 0 ? my_clog2(A_WIDTH) : 1; -- cgit v1.2.3 From 4888d61c651e1230c592cff7c0d8143bcc8394e1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 18 Sep 2014 12:57:55 +0200 Subject: Improvements in "synth" script --- techlibs/common/synth.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'techlibs/common') diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 95221afa9..4ccacd30b 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -66,18 +66,20 @@ struct SynthPass : public Pass { log(" wreduce\n"); log(" alumacc\n"); log(" share\n"); - log(" opt -fast\n"); + log(" opt\n"); log(" fsm\n"); log(" opt -fast\n"); - log(" memory\n"); + log(" memory -nomap\n"); + log(" opt_clean\n"); log("\n"); log(" fine:\n"); + log(" memory_map\n"); log(" techmap\n"); log(" opt -fast\n"); #ifdef YOSYS_ENABLE_ABC - log(" abc\n"); + log(" abc -fast\n"); + log(" opt_clean\n"); #endif - log(" clean\n"); log("\n"); } virtual void execute(std::vector args, RTLIL::Design *design) @@ -130,20 +132,22 @@ struct SynthPass : public Pass { Pass::call(design, "wreduce"); Pass::call(design, "alumacc"); Pass::call(design, "share"); - Pass::call(design, "opt -fast"); + Pass::call(design, "opt"); Pass::call(design, "fsm"); Pass::call(design, "opt -fast"); - Pass::call(design, "memory"); + Pass::call(design, "memory -nomap"); + Pass::call(design, "opt_clean"); } if (check_label(active, run_from, run_to, "fine")) { + Pass::call(design, "memory_map"); Pass::call(design, "techmap"); Pass::call(design, "opt -fast"); #ifdef YOSYS_ENABLE_ABC - Pass::call(design, "abc"); + Pass::call(design, "abc -fast"); + Pass::call(design, "opt_clean"); #endif - Pass::call(design, "clean"); } log_pop(); -- cgit v1.2.3