summaryrefslogtreecommitdiff
path: root/techlibs
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-08-13 18:40:57 +0200
committerClifford Wolf <clifford@clifford.at>2014-08-13 18:40:57 +0200
commit7e758d5fbba4769ba268229bece7b5c486c61223 (patch)
tree39ae6a8b100e8fd3e011c108b7684f18c34ebbe3 /techlibs
parent9a065509acd53d4fdbfe2e98ab0aba5e6851d8e8 (diff)
Added techmap support for actual lookahead carry unit
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/common/techmap.v95
1 files changed, 73 insertions, 22 deletions
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index 59f91bc5..3670bd69 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