simple and annoying

D

David Binnie

I have no idea why this doesn't work,
The output counts up regardless of the value of datain(i),
any help out there ?

architecture algorithm of ones_counter is
signal temp: std_logic_vector (0 to 3);
begin

process(datain)

begin
temp <= "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp <= temp + '1';
else null;
end if;
end loop;
end process;

count <= temp;

end algorithm;
 
S

Shannon

I have no idea why this doesn't work,
The output counts up regardless of the value of datain(i),
any help out there ?

architecture algorithm of ones_counter is
signal temp: std_logic_vector (0 to 3);
begin

process(datain)

begin
temp <= "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp <= temp + '1';
else null;
end if;
end loop;
end process;

count <= temp;

end algorithm;

You didn't say much about what datain is or what width is but from the
looks of it, this will count up if datain is any non-zero number.

Shannon
 
D

David Binnie

Thanks,

datain is an slv and width is just to make the slv generic.

It is meant to count the number of 1s in the slv. i.e. 0111 would return 3

But it just counts up regardless of the value of datain.

I think there is something I don't understand in the loop statement.


David
 
D

David Binnie

The RTL schematic shows that each bit is of datain is compared with '1'
i.e. the implemetation is that if any bit of datain is '1' then temp will
count.

So it's a zero number detector.

I don't think the logic implies this !

David
 
B

Brad Smallridge

The output counts up regardless of the value of datain(i),
any help out there ?

architecture algorithm of ones_counter is
signal temp: std_logic_vector (0 to 3);
begin

process(datain)

begin
temp <= "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp <= temp + '1';
else null;
end if;
end loop;
end process;

count <= temp;

end algorithm;

I think the problem has to do with the way VHDL schedules
signals rather than updates them like variables in program
code. I got it to work by using variables instead of
std_logic_vector inside the loop. There are probably better
ways.

Brad Smallridge
AiVision

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity top is
Port (
datain : in std_logic_vector(7 downto 0));
end top;

architecture algorithm of top is

signal count : std_logic_vector(3 downto 0);
constant width : positive := 8;

begin

process(datain)
variable temp : std_logic_vector(3 downto 0);
begin
temp := "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp := temp + '1';
-- else null;
end if;
end loop;
count <= std_logic_vector(unsigned(temp));
end process;


end algorithm;
 
K

KJ

David Binnie said:
I have no idea why this doesn't work,
The output counts up regardless of the value of datain(i),
any help out there ?
Processes only update signals when they exit or when they encounter a wait
statement. Your process gets trigerred when datain changes and then it
enters the loop. Since 'temp' is a signal it won't get updated until the
process completes (i.e. after going through the entire 'width' loops). So
what happens is that if any of the bits in datain is '1', then temp will
increment by '1'. Variables however get updated immediately so if temp were
a variable it would increment once for each bit in datain that is a '1'.
Since variables are only visible from within the process that declares them,
the assignment to count must be put inside the process. Modified code with
my annotations below .

As an aside, since you're trying to add '1' to a std_logic_vector I'm
assuming that you're using std_logic_arith which is a poor practice, use
numeric_std instead.

use ieee.numeric_std.all; -- KJ added, remove std_logic_arith

architecture algorithm of ones_counter is
-- signal temp: std_logic_vector (0 to 3); KJ commented out
begin

process(datain)
variable temp: unsigned(0 to 3); KJ added, use unsigned instead of slv
begin
temp := "0000"; -- KJ change to variable assignment
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp := temp + 1; -- KJ change to variable assign and add 1
else null; -- KJ 'else null' not really needed, doesn't hurt anything
though
end if;
end loop;
count <= std_logic_vector(temp); -- KJ moved inside process, add type
conversion
end process;
end algorithm;

KJ
 
A

ast

David Binnie said:
I have no idea why this doesn't work,
The output counts up regardless of the value of datain(i),
any help out there ?

architecture algorithm of ones_counter is
signal temp: std_logic_vector (0 to 3);
begin

process(datain)

begin
temp <= "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp <= temp + '1';
else null;
end if;
end loop;
end process;

count <= temp;

end algorithm;

You simply dont know how signals are handled in VHDL.

If a signal is set many times in a process, only the last setting is done.

ie suppose signal S (type integer) is 0 and then enter the following process

process
begin
for i in 0 to 5 loop
S <= S+1;
end loop;
end;

At the end of the process, S is 1 and not 6 as expected

You need to use a variable (instead of a signal) if you want to work in a process

try this code:

architecture algorithm of ones_counter is
variable temp: std_logic_vector (0 to 3);
begin

process(datain)

begin
temp := "0000";
for i in 0 to (width-1) loop
if datain(i) = '1' then
temp := temp + '1';
end if;
end loop;
end process;

count <= temp;
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top