0
\$\begingroup\$

I want my component to receive data, and store it into an array, only if it isn't already in the array. Should be simple right?

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity repetition is
  port(
    data_in: in unsigned(6 downto 0);
    start  : in std_logic;
    output  : out unsigned(6 downto 0));
end entity;

architecture arh of repetition is
signal i: integer := 0;
type niz is array (6 downto 0) of unsigned(6 downto 0);
signal niz1: niz;
signal repeat: std_logic := '0';
begin
process(start, repeat)
variable ind : std_logic := '0';
begin
if( to_integer(data_in) < 100) then
    if (start='0' or repeat = '1') then

        for j in 0 to 6 loop
            if(j<i) then
                if(data_in = niz1(j)) then
                    ind := '1';
                end if;
            end if;
        end loop;   
        if (ind = '0') then
            niz1(i)<=data_in;
            i<=i+1;
            output<=data_in;
            repeat <= '0';
        else
            repeat <= '1';
        end if;
    end if;
end if;
end process;
end arh;

i is an integer which tells us how far we have gottent into an array (of length 7), repeat is in the process sensitivity list, used to restart the process if an element is already present in the array and output outputs the newest unique input. When I run this, output is all 0s.

The thing that's really interesting is if I put if(ind = '1'), it takes the branch always, i.e., I believe it is somehow in advance updating i and the array, before the loop finishes, so it always finds that data it checks for is in the array.

How do I correct this?

\$\endgroup\$
  • \$\begingroup\$ How are you running this? In a simulator? In an FPGA? The thing that's tricky about VHDL is it's not software and you have to think about it very differently from software. \$\endgroup\$ – kjgregory Jan 12 '18 at 22:23
  • 4
    \$\begingroup\$ Make this an [MCVE]. (oops that's a Stack Overflow thing). See stackoverflow.com/help/mcve \$\endgroup\$ – Brian Drummond Jan 12 '18 at 22:55
  • \$\begingroup\$ @kjgregory It's a simulation. It certainly is tricky. \$\endgroup\$ – rkcepelin Jan 12 '18 at 23:08
  • \$\begingroup\$ "I want my component to receive data, and store it into an array, only if it isn't already in the array." - why? \$\endgroup\$ – Bruce Abbott Jan 13 '18 at 7:54
  • \$\begingroup\$ @BruceAbbott The main goal is to have seven unique outputs. So on every input I check it against the elements of the array (up to a certain index) and see if it was in already. \$\endgroup\$ – rkcepelin Jan 13 '18 at 7:56
3
\$\begingroup\$

Sorry to say but there are so many error here I don't know where to begin. Basically you make the common error I see with most beginners in VHDl/Verilog: You write code as if it is a computer program. It is not a computer program. It is a hardware simulation language. The most common errors I see (also here) are:

  • Not initializing variable using a reset
  • Re-using a variable multiple times
  • Mixing combinatorial and register sections
  • Thinking that modules/processes/architectures are some sort of functions which are called each time.

The last is the most common and biggest error which you have to get out of your mind. Code represent hardware which will be 'instanced' and then needs to be fed data into and you have to catch what comes out. And all your hardware in all your files works at the same time.

I am not going to rewrite the code. I can give you some tips and guidance:

  1. Find VHDL code from others and study what they do. Try to understand why they do things that way.
  2. Add a clock and a reset, you have neither.
  3. Stop initialing your variables: "signal i: integer := 0;" works only in test benches. In fact I deplore the whole idea and would like to see in removed from VHDL.
  4. Separate your control from your data. Thus split the code into two parts. One part checks if the data is already in the array. The other part which stores the data if it is not. Hint: The part which compares has a single output: hit/miss.
  5. Now that you have a clock decide how fast your compare should be. One clock cycle, two clock cycles, 8 clock cycles? It will depend on your data flow. How often does a new data item arrive.
  6. Building on that you have to implement code for 8, 4 or one compare at a time.

Post edit: initialisation
There are some comment about initialisation. Let me elaborate on that a bit more.
As mentioned initialisation in behavioral code is fine. It will work in most FPGAs if you use zero but it will never work in ASIC (my background). But in all cases the user must be very carefull and realise what they are doing. Now let me take an example based on the above code:

process(...)
variable found_it std_logic := '0';

The misconception is that this is equivalent to C:

void proces(...)
{ int found_it = 0;

But it is in fact closer to:

void proces(...)
{ static int found_it = 0;

The variable is set to zero once and once only: when the code is instanced. If you then set it to '1' in a loop it does not get reset again. It is a potential pitfall for programmers who come from a software background.

\$\endgroup\$
  • \$\begingroup\$ Initialisation has worked on altera fpgas when I used quartus 2. But yea it's still always better to do it in reset. \$\endgroup\$ – Mitu Raj Jan 13 '18 at 10:12
  • \$\begingroup\$ Initialisation have always worker for me too. I will see what gives. \$\endgroup\$ – rkcepelin Jan 13 '18 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.