Addition With Carry Problem

S

Samuel Winchenbach

Guest
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
Try "GUESS = (A | ~B) + {4'b0000,!Cin_BAR};" and see what you get.

When you get the correct answer, think about how the tool might be
interpreting your original equation.

Do you have Verilog LINTint? Do you get any warnings related to that line?

Happy coding!

"Samuel Winchenbach" <swinchen@eece.maine.edu> wrote in message
news:edfcd431.0310151045.71c95d10@posting.google.com...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
swinchen@eece.maine.edu (Samuel Winchenbach) writes:

Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000
Your problem is related to the size of the result of (A|~B).

Try the following experient: Make two temporary reg's called tmp1 and
tmp2, with tmp1 being [3:0] and tmp2 being [4:0]. Now set tmp1 = A|~B;
and tmp2 = A|~B; and $display tmp1 and tmp2. You will see that the
change in output bitwidth for this function does have an effect. Now
think about what adding a one to either of those numbers does.

--
Brian K. Ogilvie
bko-no-spam-please@ieee.org (remove the obvious to reply).
 
Thanks John for the speedy response.

Unfortunately that did not solve the problem. My partner and I believe that
the error occurs due to (A | ~B) Or perhaps setting A equal to the integer Ax
is causing the problem? I forgot to mention before that A and B are both
input pins to the ALU.

If anyone can think of any other possible solution to this problem it would be
very helpful and appreciated as this is a time critical project.

Thank You,

Samuel Winchenbach
Mohamed Driss

John_H wrote:

Try "GUESS = (A | ~B) + {4'b0000,!Cin_BAR};" and see what you get.

When you get the correct answer, think about how the tool might be
interpreting your original equation.

Do you have Verilog LINTint? Do you get any warnings related to that line?

Happy coding!

"Samuel Winchenbach" <swinchen@eece.maine.edu> wrote in message
news:edfcd431.0310151045.71c95d10@posting.google.com...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
bko-no-spam-please@ieee.org wrote:

swinchen@eece.maine.edu (Samuel Winchenbach) writes:

Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Your problem is related to the size of the result of (A|~B).

Try the following experient: Make two temporary reg's called tmp1 and
tmp2, with tmp1 being [3:0] and tmp2 being [4:0]. Now set tmp1 = A|~B;
and tmp2 = A|~B; and $display tmp1 and tmp2. You will see that the
change in output bitwidth for this function does have an effect. Now
think about what adding a one to either of those numbers does.

--
Brian K. Ogilvie
bko-no-spam-please@ieee.org (remove the obvious to reply).
Yes, we have thought of this. We think that it sign extends the
answer....

if tmp1 = -1, tmp1 will be 1111
if tmp2 = -1, tmp2 will be 11111

We are trying to avoid the signed and unsigned values though.

Also what is the dimension of A and B in your experiment?

Thanks,

Sam and Mo.
 
"John_H" <johnhandwork@mail.com> wrote in message
news:GJhjb.16$4d7.5072@news-west.eli.net...
Do you have Verilog LINTint? Do you get any warnings related to that
line?

Sorry... "Do you have Verilog LINTing?"
 
Samuel Winchenbach <swinchen@eece.maine.edu> writes:

bko-no-spam-please@ieee.org wrote:
Your problem is related to the size of the result of (A|~B).

if tmp1 = -1, tmp1 will be 1111
if tmp2 = -1, tmp2 will be 11111
OK, now you are starting to see the light. Think about what 1111 + 1 into a
5-bit result is versus 11111 + 1 into the same 5-bit result. One is what you
want, the other is what you are getting now.

Try using tmp1 in your addition:
GUESS = tmp1 + !Cin_BAR;
and see what you get. Try to figure out why this is the case.

We are trying to avoid the signed and unsigned values though.
You are not using the signed declaration (it appears) so signed versus unsigned
is not on the right track.

Ask yourself what does Verilog do when the left-hand-side result bitwidth is
larger than the right-hand-side operand bitwidth?

What would be the result of

GUESS = 5'b11111 + 1'b1; // GUESS IS [4:0]

versus

GUESS = 4'b1111 + 1'b1; // GUESS IS [4:0]

If you can't figure it out from this, try the above code for GUESS.

Also what is the dimension of A and B in your experiment?
Same as your example, [3:0].

--
Brian K. Ogilvie
bko-no-spam-please@ieee.org
 
I would suggest that you find documentation of the rules for
width-extension in Verilog, which includes the fact that all
operands are extended to the full width of the expression
before any operations are performed, and the width of the
expression is affected by the left-hand-side of the assignment.

If it is not clear to you how this affects your situation, then
try experimenting with subsets of your expression. Eliminate
some of the operands and see what results you get for those
simplified expressions.
 
I don't know what you're trying to achieve using for loop here.

Option 1. You can use gate level modeling. You must be having gate
level diagram of full adder, try to model that in verilog..
Option2. You can use assign statement. + operator is used for
addition. Use concatenation operator if you care about output carry.

- Give values to A, B and Cin in the testbench, not here.

-Anil

swinchen@eece.maine.edu (Samuel Winchenbach) wrote in message news:<edfcd431.0310151045.71c95d10@posting.google.com>...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
Can you try this pseudo code


reg [4:0] temp = {1'b0, A|~B};
GUESS = temp + ~Cin_BAR;


"Samuel Winchenbach" <swinchen@eece.maine.edu> ???
news:edfcd431.0310151045.71c95d10@posting.google.com ???...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
Thanks Allen. Worked like a charm.

Thanks to everyone that helped.

Sam and Mo

Allen wrote:

Can you try this pseudo code

reg [4:0] temp = {1'b0, A|~B};
GUESS = temp + ~Cin_BAR;

"Samuel Winchenbach" <swinchen@eece.maine.edu> ???
news:edfcd431.0310151045.71c95d10@posting.google.com ???...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
Did you ever ***determine*** exactly what the problem is?
I ran some code on Modelsim trying some permutations of the
variables to see where variables were getting extended for
1 or 4 bits to 5 bits. Here's the results:
# guess '(a | ~b) + !c_n' = 5'h00
# guess '(a | b) + !c_n' = 5'h01
# guess '(a | b) + ~c_n' = 5'h1f
# guess '(a | ~b) + c_n' = 5'h1f

I think the last line shows where your real problem happens. Verilog
zero extends 'b' to 5 bits (ie, 5'b00000), then inverts it to be
5'b11111. This is not what you expected. Your code assumed
the invert would happen first (4'b1111), then be zero extended to
be 5'b01111.

An alternate way to write the code is:
# guess '(a | (b ^ 4'hf) ) + (c_n ^ 1'b1)' = 5'h10

Note that here I use the XOR to invert the exact number of bits I care
about rather than depend on how Verilog performs the extend/invert
operations.

John Providenza




Samuel Winchenbach <swinchen@eece.maine.edu> wrote in message news:<3F8EAACC.5238C9C5@eece.maine.edu>...
Thanks Allen. Worked like a charm.

Thanks to everyone that helped.

Sam and Mo

Allen wrote:

Can you try this pseudo code

reg [4:0] temp = {1'b0, A|~B};
GUESS = temp + ~Cin_BAR;

"Samuel Winchenbach" <swinchen@eece.maine.edu> ???
news:edfcd431.0310151045.71c95d10@posting.google.com ???...
Hello,

I am a student at the University of Maine and I am working on creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 
Yes I agree with you.
I think the hardware compiler will do or not do smart bit width conversion.
I will pay attention bit width if I do ALU operation.


"John Providenza" <johnp3+nospam@probo.com> ???
news:349ef8f4.0310170630.7ad44c14@posting.google.com ???...
Did you ever ***determine*** exactly what the problem is?
I ran some code on Modelsim trying some permutations of the
variables to see where variables were getting extended for
1 or 4 bits to 5 bits. Here's the results:
# guess '(a | ~b) + !c_n' = 5'h00
# guess '(a | b) + !c_n' = 5'h01
# guess '(a | b) + ~c_n' = 5'h1f
# guess '(a | ~b) + c_n' = 5'h1f

I think the last line shows where your real problem happens. Verilog
zero extends 'b' to 5 bits (ie, 5'b00000), then inverts it to be
5'b11111. This is not what you expected. Your code assumed
the invert would happen first (4'b1111), then be zero extended to
be 5'b01111.

An alternate way to write the code is:
# guess '(a | (b ^ 4'hf) ) + (c_n ^ 1'b1)' = 5'h10

Note that here I use the XOR to invert the exact number of bits I care
about rather than depend on how Verilog performs the extend/invert
operations.

John Providenza




Samuel Winchenbach <swinchen@eece.maine.edu> wrote in message
news:<3F8EAACC.5238C9C5@eece.maine.edu>...
Thanks Allen. Worked like a charm.

Thanks to everyone that helped.

Sam and Mo

Allen wrote:

Can you try this pseudo code

reg [4:0] temp = {1'b0, A|~B};
GUESS = temp + ~Cin_BAR;

"Samuel Winchenbach" <swinchen@eece.maine.edu> ???
news:edfcd431.0310151045.71c95d10@posting.google.com ???...
Hello,

I am a student at the University of Maine and I am working on
creating
an ALU for a Cadence design project. I am having a bit of trouble
with verilog validation. When added two 4-bit binary numbers that
result in a carry I am getting the incorrect solution. For example:

A = 4'b0000;
B = 4'b0000;
Cin_BAR = 1'b0;

GUESS = (A | ~B) + !Cin_BAR;

GUESS _should_ be equal to 4'b1111 + 1'b1 = 10000.
The code below produces: 00000

Does anyone have any tips on correcting this problem? I believe
that
the problem is due to signed/unsigned numbers. Thanks in advance.

// CODE

integer Ax;
reg[4:0] GUESS;

initial
begin
A[3:0] = 4'b0000;
B[3:0] = 4'b0000;
Cin_BAR = 1'b0;

for(Ax=0; Ax <= 15; Ax = Ax + 1)
begin
A = Ax;
#150
GUESS = (A|~B) + !Cn_BAR; // (Ax | 4'b1111) + 1
$display("%b",GUESS); // This displays 00000, should be 10000
end

end
 

Welcome to EDABoard.com

Sponsor

Back
Top