Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20689 Discussions

Bit extending when adding

Altera_Forum
Honored Contributor II
1,373 Views

Hello, 

 

I'm trying to add an signed std_logic_vector(21 downto 0) with a std_logic (unsigned) using the vhdl operator "+". I'm using the "IEEE.std_logic_signed.all" library . I just assumed that the result would be a 23 bit number but the compiler complained and said that the result needed to be a 22 bit vector. Why is that? Does it interpret my std_logic as a signed?  

 

My first attempt looks like this: 

 

signal p_value_truncated : std_logic_vector(21 downto 0); signal p_value_rounded : std_logic_vector(22 downto 0); signal p_value_carry : std_logic; ... p_value_rounded <= p_value_truncated + p_value_carry;  

 

This is going to be in a regulator so it is important that is does not overflow. To make sure, I've opted to sign extend p_value_truncated to 23 bits and extend p_value_carry with a zero. 

 

Does anyone understand how the compiler works in this case? 

 

Best Regards, 

Ola Bångdahl
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
642 Views

Hi Bango 

 

In the std_logic_signed package the returned std_logic_vector is the same width as the input vectors. If you want the overflow then you could tweak your code thus: 

 

p_value_rounded <= (p_value_truncated(p_value_truncated'left) & p_value_truncated) + p_value_carry; 

 

The general advice that goes with std_logic_signed is use numeric_std instead. std_logic_signed isn't a standard package - it certainly isn't an IEEE package and is only compiled into that library as a result of naughtiness. Appraently there aare differences between the Mentor and Synopsis std_logic_signed (and unsigned) packages. If you want a standard package use numeric_std which is an IEEE package. Also this makes it easier to use signed and unsigned in the same source code without confusion. 

 

The downside that you will find is that there doesn't seem to be a "std_logic_vector + std_logic" function in numeric_std - there's everything else but this. 

 

Hope this helps.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

Thank you for the input. I'll take a look at the numeric_std library. Not beeing able to multiply std_logic_vectors with std_logics is not a large problem when designing something new. For the moment I will do like this: 

 

 

p_value_rounded <= sxt(p_value_truncated,23) + p_value_carry_ext;  

 

where p_value_carry_ext is p_value_carry extended with a zero just to be on the safe side with the sign. 

 

Best Regards, 

Ola Bångdahl
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

There are a few quirks with numeric_std which take a bit of getting used to if you've been using std_logic_signed. 

 

E.g. if you're incrementing a std_logic_vector by integer 1 with std_logic_signed: 

 

my_vector <= my_vector + 1; 

 

if you use numeric_std then you have to do a bit of casting: 

 

my_vector <= std_logic_vector( signed(my_vector) + 1 ); 

 

At first I found this a bit laborious but once I got used to it I actually found that it made the code clearer and easier to mix signed and unsigned operations in the same source file. 

 

Good luck.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

It's better to extend the bit sign instead a zero. 

 

Use the numeric_std library. 

 

--Extensión de signo 

adder_in_a(2*N+Ncounter downto 2*N)<=(others=>mult_out(2*N-1)); 

 

adder_in_a(2*N-1 downto 0)<=mult_out; 

 

--El sumador 

adder_out<=std_logic_vector(signed(adder_in_a)+signed(acc_out));
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

I agree that using numeric_std should be promoted and std_logic_arith should be deprecated. 

 

I also think that information passed around should retain the appropriate level of detail. Does it make sense to keep converting an address to a std_logic_vector when it really is an unsigned representation of a number? 

 

-- multiplication signal a : signed(17 downto 0) ; signal b : signed(12 downto 0) ; signal c : signed(a'length + b'length - 1 downto 0) ; c <= a * b ; -- addition signal a : signed(7 downto 0) ; signal b : signed(7 downto 0) ; signal c : signed(12 downto 0) ; c <= resize( a, c'length ) + resize( b, c'length ) ; -- NOTE: resize() will sign or zero extend based on the context it is used -- ram addressing signal ram : ram_t ; signal ram_addr : unsigned(11 downto 0) ; dout <= ram( to_integer( ram_addr ) ) when rising_edge( clock ) ;  

 

Hope this helps.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

 

--- Quote Start ---  

Does it make sense to keep converting an address to a std_logic_vector when it really is an unsigned representation of a number? 

--- Quote End ---  

 

 

Personally I would say yes - signed / unsigned are only high level human interpretations of the binary number. In most applications signed / unsigned doesn't really matter - it doesn't change what the value means but it does interfere when you want to interface to std_logic_vector.  

 

Why add an unnecessary constraint onto the data type? 

 

Sure use signed / unsigned but only when it's absolutely imperative that you capture the signed / unsigned nature of the signal and I've found that this is very rarely.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

I thought about this long and hard, and I respectfully disagree. 

 

When dealing with digital computers, everything is a wire or a transistor but to design using only those two things is absurd. 

 

Since unsigned and signed are subtypes of std_logic_vector, a simple cast is all that is required to interface to std_logic_vector. I believe the ambiguity of the number being represented far outweighs a few casts. 

 

If you were to design a double precision floating point arithmetic module, would you interface to a 64-bit std_logic_vector, or would you create a record for sign, exponent and fraction? 

 

In cases where the number could be either signed or unsigned, std_logic_arith should still not be used since you want to convey what type it is being interpreted as back to the person reading the code. 

 

The purpose is to capture the original intent of the design. VHDL allows the designer to keep the original intent intact with very little impact on the rest of the code. 

 

Unless you're coding for job security, I think signed and unsigned types should be used to convey intent by the designer, but I respect your opinion that they are not required in most cases.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

That's exactly my point - use signed / unsigned types where it matters and adds clarity to the code. For most instances though, a data vector is neither signed nor unsigned - if it doesn't make a difference then use std_logic_vector. 

 

Each to their own though.
0 Kudos
Altera_Forum
Honored Contributor II
642 Views

Hi, again. 

 

Thanks for all the good input. I will have this in mind when I do my next design.  

 

//Ola
0 Kudos
Reply