simple unsigned maths problem with if statement

D

David Perry

Guest
I'm having an issue with a simple if statement:

if ClampIn_u + DMD_u < x"FFFF" then --this doesn't work :(
ClampIn_u := ClampIn_u + DMD_u;
else
ClampIn_u := x"FFFF";
end if;

What happens is the addition always occurs, I end up overflowing and I get the wrong result.

I tried making the right hand side of the if bigger in attempt to make it work:

if ClampIn_u + DMD_u < x"0FFFF" then

but that fails in the same way.

If I rearrange the maths (subtract DMD_u from both sides):

if ClampIn_u < x"FFFF" - DMD_u then

this works.

DMD_u is an unsigned 16 bit signal, ClampIn_u is an unsigned 16 bit variable.

I'm struggling to find an explanation, I can see why my original might fail but I would have expected "0FFFF" to work.

Any insight would be appreciated :)

Dave
 
On 2/22/18 6:38 AM, David Perry wrote:
I'm having an issue with a simple if statement:

if ClampIn_u + DMD_u < x"FFFF" then --this doesn't work :(
ClampIn_u := ClampIn_u + DMD_u;
else
ClampIn_u := x"FFFF";
end if;

What happens is the addition always occurs, I end up overflowing and I get the wrong result.

I tried making the right hand side of the if bigger in attempt to make it work:

if ClampIn_u + DMD_u < x"0FFFF" then

but that fails in the same way.

If I rearrange the maths (subtract DMD_u from both sides):

if ClampIn_u < x"FFFF" - DMD_u then

this works.

DMD_u is an unsigned 16 bit signal, ClampIn_u is an unsigned 16 bit variable.

I'm struggling to find an explanation, I can see why my original might fail but I would have expected "0FFFF" to work.

Any insight would be appreciated :)

Dave

A 16 bit unsigned + a 16 bit unsigned will do the arithmetic in 16 bits,
and ignore the overflow/carry out. Making the right hand side bigger
doesn't affect how the left hand side is computed.

If you coerced the signals on the left hand side to be 17 bit signals
(by concatenating a higher order 0 bit), then the arithmetic would
produce the needed value, and the comparison would work.
 
I see, my assumptions were incorrect.
So something like:

MyTemp17b_u := ClampIn_u + DMD_u; --a 17bit unsigned variable
if MyTemp17b_u < x"FFFF" then
ClampIn_u := ClampIn_u + DMD_u;
else
ClampIn_u := x"FFFF";
end if;

I could perhaps then use that extra bit to my advantage by testing that rather than the whole result? Such as:

if MyTemp17b_u(16) = '0' then --check the overflow bit

And would I be best re-using the result and just copying the lower 16 bits, I suspect it might create a second addition otherwise, so I end up with:

MyTemp17b_u := ClampIn_u + DMD_u; --a 17bit unsigned variable
if MyTemp17b_u(16) = '0' then --check the overflow bit
ClampIn_u := MyTemp17b_u(15 downto 0);
else
ClampIn_u := x"FFFF";
end if;

I don't actually need to be gate efficient with what I'm playing with, but it's interesting to fiddle with :)

Appreciate the time Richard, cheers.
Dave
 
On 2/22/18 9:53 AM, David Perry wrote:
I see, my assumptions were incorrect.
So something like:

MyTemp17b_u := ClampIn_u + DMD_u; --a 17bit unsigned variable
if MyTemp17b_u < x"FFFF" then
ClampIn_u := ClampIn_u + DMD_u;
else
ClampIn_u := x"FFFF";
end if;

I could perhaps then use that extra bit to my advantage by testing that rather than the whole result? Such as:

if MyTemp17b_u(16) = '0' then --check the overflow bit

And would I be best re-using the result and just copying the lower 16 bits, I suspect it might create a second addition otherwise, so I end up with:

MyTemp17b_u := ClampIn_u + DMD_u; --a 17bit unsigned variable
if MyTemp17b_u(16) = '0' then --check the overflow bit
ClampIn_u := MyTemp17b_u(15 downto 0);
else
ClampIn_u := x"FFFF";
end if;

I don't actually need to be gate efficient with what I'm playing with, but it's interesting to fiddle with :)

Appreciate the time Richard, cheers.
Dave

I am not an expert here, but my first expectation would be that the term
ClampIn_u + DMD_u would still be done to 16 bit here, and then that 16
bit result extended to 17 (but I would admit I might be wrong).

I would extend ClampIn_u and DMD_u to 17 bits first, and then add them
(preferably saving the 17 bit result for reuse).
 
On 24.02.2018 01:43, Richard Damon wrote:
[...]
I am not an expert here, but my first expectation would be that the term
ClampIn_u + DMD_u would still be done to 16 bit here, and then that 16
bit result extended to 17 (but I would admit I might be wrong).

I would extend ClampIn_u and DMD_u to 17 bits first, and then add them
(preferably saving the 17 bit result for reuse).

That's correct. However you only need to extend one operand to 17 bits
to force the result to 17 bits (though extending both works just as well
but requires a bit more typing)

Nicolas
 
OK, how about:
MyTemp17b_u := '0' & ClampIn_u;
MyTemp17b_u := MyTemp17b_u + DMD_u;

I think I need to put the:
'0' &
in there as I have experienced what I can only describe as "filling from the left", something else I've struggled to understand :(

Cheers,
Dave
 
On 02/26/2018 12:57 AM, David Perry wrote:
OK, how about:
MyTemp17b_u := '0' & ClampIn_u;
MyTemp17b_u := MyTemp17b_u + DMD_u;

I think I need to put the:
'0' &
in there as I have experienced what I can only describe as "filling from the left", something else I've struggled to understand :(

Cheers,
Dave

Well then write it this way to do precisely the same thing:

MyTemp17b_u := RESIZE(ClampIn_u, 17)
MyTemp17b_u := MyTemp17b_u + DMD_u;

You have an unsigned value in 16 bits; it's between 0-65535. You can
put as many zeros on as many additional MSBs as you like, which changes
the number of bits you're using to represent it, but the value there is
still 0-65535, the same as in decimal 10, 010, and 000010 all represent
the number between 9 and 11.

--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order. See above to fix.
 
On Thursday, February 22, 2018 at 6:38:54 AM UTC-5, David Perry wrote:
I'm having an issue with a simple if statement:

if ClampIn_u + DMD_u < x"FFFF" then --this doesn't work :(
ClampIn_u := ClampIn_u + DMD_u;
else
ClampIn_u := x"FFFF";
end if;

What happens is the addition always occurs, I end up overflowing and I get the wrong result.

I tried making the right hand side of the if bigger in attempt to make it work:

if ClampIn_u + DMD_u < x"0FFFF" then

but that fails in the same way.

If I rearrange the maths (subtract DMD_u from both sides):

if ClampIn_u < x"FFFF" - DMD_u then

this works.

DMD_u is an unsigned 16 bit signal, ClampIn_u is an unsigned 16 bit variable.

I'm struggling to find an explanation, I can see why my original might fail but I would have expected "0FFFF" to work.

Any insight would be appreciated :)

This thread is getting a bit old in the tooth, but at least it is still the same year, ;)

I see the problem (from the perspective of an old school hardware designer) as being one of not considering what hardware will be produced from your description. After all, HDL stands for "Hardware Description" Language and to produce the best code I think the resulting hardware should be considered when writing code.

The hardware produced by this code should be an adder followed by a multiplexer with the carry out of the adder used to control the mux. In fact, it really isn't even a mux, but just a set of OR gates to force the output to a 1. So this would utilize two 4 input LUTs for each input bit to produce a result. Even better yet would be if the tools were clever enough to combine the OR gates with the adder for 1 LUT per bit, but I'm not sure the tools are quite up to it. Still, the key is using the carry out of the adder to control the OR gates.

I would write this as a 17 bit addition outside of the conditional statement. Then use the msb (which the tools should understand is the carry out of the lower 16 bits) to drive the conditional which selects either the addition result or the max 16 bit value.

MyTemp17b_u := '0' & ClampIn_u + DMD_u;
if (MyTemp17b_u(MyTemp17b_u'high) = '1') then
Result := x"FFFF";
else
Result := MyTemp17b_u;
endif;

To me this is more clear and I am pretty confident of knowing what hardware will be produced by the code.

Rick C.
 
Oddly enough, I'm trying to move away from throwing down gates (I filled a spartan 3AN 1400 with schematics), but there are times when I think to myself, you know, I could throw this down in a few minutes if I didn't do it 'properly' using VHDL...
 
On Wednesday, June 13, 2018 at 2:30:45 PM UTC-4, David Perry wrote:
> Oddly enough, I'm trying to move away from throwing down gates (I filled a spartan 3AN 1400 with schematics), but there are times when I think to myself, you know, I could throw this down in a few minutes if I didn't do it 'properly' using VHDL...

Sorry, I'm not clear on what you are saying. Are you saying you could work faster by not considering how your code is synthesized? Yes, that is certainly true. Or are you saying VHDL is a overstuffed pig of a language and you would just prefer to be laying down gates? I would not totally disagree with that either.

A long time ago one of the posters in c.a.f was famous for very high speed pipelined designs done in modular, hierarchical schematics. He resisted staunchly the movement to HDL... until he was taught how he could accomplish the same sort of library driven, modular, hierarchical designs in VHDL which in addition could be version controlled like any other software. That was when I realized I had no reason to regret having switched to VHDL (other than possibly not having switched to Verilog).

Rick C.
 
Prefer to lay down gates and ditch the VHDL. There are times when I think VHDL might be easier for certain tasks, then I start writing it and wish I'd implemented a schematic....
 

Welcome to EDABoard.com

Sponsor

Back
Top