Continue to Site

# Are these three Carry Look Ahead Circuits Equivalent?

Status
Not open for further replies.

#### kvn0smnsn

##### Junior Member level 2
Code:
module ClaFour( cOut, sum, aOp, bOp, cIn);
output        cOut;
output [ 3:0] sum;
input  [ 3:0] aOp;
input  [ 3:0] bOp;
input         cIn;
wire   [ 3:0] pro;
wire   [ 3:0] gen;
wire   [ 3:0] car;

assign car[ 0] = cIn;

genvar bt;
generate
for (bt = 0; bt < 4; bt = bt + 1)
begin
assign pro[ bt] = aOp[ bt] ^ bOp[ bt];
assign gen[ bt] = aOp[ bt] & bOp[ bt];
assign sum[ bt] = pro[ bt] ^ car[ bt];
end
endgenerate

assign car[ 1] = gen[ 0] | cIn & pro[ 0];
assign car[ 2] = gen[ 1] | pro[ 1] & gen[ 0] | pro[ 1] & pro[ 0] & cIn;
assign car[ 3]
= gen[ 2] | pro[ 2] & gen[ 1] | pro[ 2] & pro[ 1] & gen[ 0]
| pro[ 2] & pro[ 1] & pro[ 0] & cIn;
assign cOut
= gen[ 3] | pro[ 3] & gen[ 2] | pro[ 3] & pro[ 2] & gen[ 1]
| pro[ 3] & pro[ 2] & pro[ 1] & gen[ 0]
| pro[ 3] & pro[ 2] & pro[ 1] & pro[ 0] & cIn;

endmodule
But then I realized that this is really equivalent to this file:
Code:
module ClaFour_Eqv( cOut, sum, aOp, bOp, cIn);
output        cOut;
output [ 3:0] sum;
input  [ 3:0] aOp;
input  [ 3:0] bOp;
input         cIn;
wire   [ 3:0] pro;
wire   [ 3:0] gen;
wire   [ 3:0] car;

assign car[ 0] = cIn;

genvar bt;
generate
for (bt = 0; bt < 4; bt = bt + 1)
begin
assign pro[ bt] = aOp[ bt] ^ bOp[ bt];
assign gen[ bt] = aOp[ bt] & bOp[ bt];
assign sum[ bt] = pro[ bt] ^ car[ bt];
end
endgenerate

assign car[ 1] = gen[ 0] | cIn & pro[ 0];
assign car[ 2] = gen[ 1] | pro[ 1] & (gen[ 0] | pro[ 0] & cIn);
assign car[ 3]
= gen[ 2] | pro[ 2] & (gen[ 1] | pro[ 1] & (gen[ 0] | pro[ 0] & cIn));
assign cOut
=   gen[ 3]
|   pro[ 3]
& ( gen[ 2]
| pro[ 2] & (gen[ 1] | pro[ 1] & (gen[ 0] | pro[ 0] & cIn)));

endmodule
Isn't it? And then I got to thinking, isn't that equivalent to the following
file with (nmBits) set to 4?
Code:
module ClaAdd #( nmBits = 4)
( cOut, sum, aOp, bOp, cIn);
output               cOut;
output [ nmBits-1:0] sum;
input  [ nmBits-1:0] aOp;
input  [ nmBits-1:0] bOp;
input                cIn;
wire   [ nmBits-1:0] pro;
wire   [ nmBits-1:0] gen;
wire   [ nmBits  :0] car;

assign car[ 0] = cIn;
assign cOut    = car[ nmBits];

genvar bt;
generate
for (bt = 0; bt < nmBits; bt = bt + 1)
begin
assign pro[ bt    ] = aOp[ bt] ^ bOp[ bt];
assign gen[ bt    ] = aOp[ bt] & bOp[ bt];
assign sum[ bt    ] = pro[ bt] ^ car[ bt];
assign car[ bt + 1] = gen[ bt] | pro[ bt] & car[ bt];
end
endgenerate

endmodule
So here are three files, that I think do the same thing. Am I wrong? Are any of these slower than the others, and if so, why?

At least the third design is no CLA because carry is generated recursively.
Code:
assign car[ bt + 1] = gen[ bt] | pro[ bt] & car[ bt];

To compare speed, you'll determine the longest combinational path in each design.

### kvn0smnsn

Points: 2
An additional comment. Presumed the three designs are logically equivalent, you should be aware that the synthesis tool may implement the gate level logic differently depending on timing and possible structure constraints. Respectively a CLA might be translated to non-CLA due to relaxed timing constraints or vise-versa non-CLA to CLA enforced by restrictive timing.
--- Updated ---

If the the question refers to FPGA implementation, the answer is partly different. FPGA logic elements have dedicated carry chains that are faster than other logic in- and outputs. Unfortunately, a gate level description as in the example isn't necessarily recognized as adder and doesn't take advantage of the fast carry chain. Adder inference depends on arithmetic operators in HDL code.

Last edited:

### kvn0smnsn

Points: 2
Status
Not open for further replies.