How Do Perform STD_LOGIC_VECTOR Addition Using IEEE.NUMERIC_STD?

C

Chris

Hi All

I have belatedly switched to the IEEE.NUMERIC_STD package after years of
using STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED. In the past, I would implement
a counter using the following method:

count <= UNSIGNED(count) + '1';

where count is type std_logic_vector.

However, the NUMERIC_STD package produces an error message when compiling
with Modelsim PE:
No feasible entries for infix operator "+".

What syntax should I use to perform a std_logic_vector add with NUMERIC_STD?

Thanks,
Chris
 
M

Mike Treseler

Chris said:
I have belatedly switched to the IEEE.NUMERIC_STD package after years of
using STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED. In the past, I would implement
a counter using the following method:

count <= UNSIGNED(count) + '1';

count <= UNSIGNED(count) + 1 ;

args must be unsigned or natural

-- Mike Treseler
 
C

Chris

Hi Mike

Thanks for the help. Your suggestion did the trick, though I had to make an
additional change:

count <= std_logic_vector(unsigned(count) + 1);

Thanks,
Chris
 
A

Andy

count <= UNSIGNED(count) + 1 ;

args must be unsigned or natural

-- Mike Treseler

Mike is right, but also the return type of the operator is unsigned in
this expression. Try:

signal count : std_logic_vector(7 downto 0);

count <= std_logic_vector(unsigned(count) + 1);

Or if you define an abbreviated subtype name:

subtype slv is std_logic_vector; -- abbreviation

At least the typing gets easier:

count <= slv(unsigned(count) + 1);

If you really don't need count to be slv, then consider defining it as
unsigned in the first place (and perhaps converting to slv only when
loading/reading out the counter).

signal count : unsigned(input'range);

count <= unsigned(input);
count <= count + 1;
output <= slv(count);

Or define count as a natural:

signal count : natural range 0 to 2**input'length-1;

count <= count + 1; -- much faster rtl simulation

output <= slv(to_unsigned(count, output'length));

count <= to_integer(unsigned(input));

Andy
 
M

Mike Treseler

Chris said:
Thanks for the help. Your suggestion did the trick, though I had to make an
additional change:

count <= std_logic_vector(unsigned(count) + 1);

You've got it.
Sorry I missed your cast.
But like Andy said, you don't really need it.

-- Mike Treseler
 
C

Chris

Hi Andy

I have started defining all my counters "internally" as natural or integer,
then converting them to std_logic_vector as needed.

Do you have any sense as to the impact of an integer-coded counter on
synthesis? I could see one potential annoyance if the integer counters were
all synthesized as 32-bit. I'll have to read through the Precision doc to
see how integer counters are handled.

Thanks for the info,
Chris
 
P

Peter

Hi Andy

I have started defining all my counters "internally" as natural or integer,
then converting them to std_logic_vector as needed.

Do you have any sense as to the impact of an integer-coded counter on
synthesis? I could see one potential annoyance if the integer counters were
all synthesized as 32-bit. I'll have to read through the Precision doc to
see how integer counters are handled.

Counters etc could be limited in size e.g.

Variable count_v : Integer range 0 to 511;

/Peter
 
A

Andy

Counters etc could be limited in size e.g.

Variable count_v : Integer range 0 to 511;

/Peter

Peter is correct, integer variables and signals should be limited in
size by declaring an appropriate range:

signal count : natural range 0 to 2**numbits-1; -- numbits wide count

However, it is important to realize that the operations are still 32
bit signed; the limiting only happens when it is assigned to a limited
variable or signal. Synthesis has no problem optimizing out the unused
bits in intermediate expressions.

Thus count - 1 < 0 is still possible, even though count < 0 is not.
This is an easy way to extract the carry condition in a down counter:

if count - 1 < 0 then -- carry bit set
count <= start_value; -- reload
else
count <= count - 1; -- update
end if;

The synthesizer (XST, Quartus, Synplify-Pro, Precision, even the old
synopsys DCFPGA) will automatically share the decrement between the
comparison and the update, and use the next bit (the sign bit) to
control the reload or update.

The same sort of trick works for overflow in an up counter too.

Andy
 
D

Duane Clark

Andy said:
...
However, it is important to realize that the operations are still 32
bit signed; the limiting only happens when it is assigned to a limited
variable or signal. Synthesis has no problem optimizing out the unused
bits in intermediate expressions.

Thus count - 1 < 0 is still possible, even though count < 0 is not.
This is an easy way to extract the carry condition in a down counter:

if count - 1 < 0 then -- carry bit set
count <= start_value; -- reload
else
count <= count - 1; -- update
end if;

The synthesizer (XST, Quartus, Synplify-Pro, Precision, even the old
synopsys DCFPGA) will automatically share the decrement between the
comparison and the update, and use the next bit (the sign bit) to
control the reload or update.

So I synthesized a couple versions to see what XST (ISE8.2) does (into
an XC2VP7), checking the results with fpga_editor. I first had to use
fairly large counters or it would not necessarily use the carry chain,
and I wanted to see how that was used.

So the above mentioned:
if count - 1 < 0 then -- carry bit set
count <= start_value; -- reload
else
count <= count - 1; -- update
end if;
That created two parallel sets of LUTs, one with the counter itself, and
one that simply calculates count-1 using a carry chain. It is the carry
output of this second chain that triggers reloading of the counter.

Next:
if count = 0 then -- carry bit set
count <= start_value; -- reload
else
count <= count - 1; -- update
end if;
That created a single chain for the counter, and then in LUTs it
implemented ~count1*~count2*~count3... , with the output of that
triggering the load.

The second method actually uses less logic than the first, but neither
was ideal. I must say, I am not impressed with XST synthesis of
something so basic as a counter :-(
 
D

David Bishop

Chris said:
Hi All

I have belatedly switched to the IEEE.NUMERIC_STD package after years of
using STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED. In the past, I would implement
a counter using the following method:

count <= UNSIGNED(count) + '1';

where count is type std_logic_vector.

However, the NUMERIC_STD package produces an error message when compiling
with Modelsim PE:
No feasible entries for infix operator "+".

What syntax should I use to perform a std_logic_vector add with NUMERIC_STD?

In the numeric_std package there is a type called "unsigned" (and
another called "signed") for doing math. This allows you keep the
concept of a signed and unsigned number separate. You would do it like
this:

signal count : unsigned ( 7 downto 0);
....
count <= count + 1;

If you really need it in std_logic_vector you can say:
countslv <= std_logic_vector (count);
 
C

Chris

Thanks for the suggestions. I had figured that constraining integer range
would be the way to improve counter efficiency.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top