Search code examples
arraysvhdl

VHDL weird behavoir of an array of unsigneds


basically I have a array of unsigneds and a process that increments the first value of in the array by one. This worked fine untill I implemented an asynchronos reset, that sets the elements of the array to 0. The weird thing is, even when the code of the asynchronos reset is never reached, it makes the rest of my code not work anymore. Here is my code:

use work.datentyp.all;

library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.numeric_std.all;
entity vektoruhr is
    port (

        clk, reset : in std_logic ;
    );
end vektoruhr;
architecture v1 of vektoruhr is

    signal internal_stamp : vektor := (others => (others => '0'));

begin

process(clk)
    begin
        if(rising_edge(clk)) then
            internal_stamp(0) <= internal_stamp(0) + 1;
        end if;
    end process;

    process(reset)
    begin
    if(rising_edge(reset)) then
        report "reset triggered"; 
        -- internal_stamp <= (others => (others => '0'));
        alarm <= '0';
    end if;
    end process;
end v1;

As you can see, the line

 -- internal_stamp <= (others => (others => '0'));

is commented out. Like this, everything works fine. But if I delete the --, the value of the first element is 00 first, then gets changed to 0x after the first incrementation and to xx after the second one. After that it stay at xx. The reset input is set to '0' from the begining and is never changed.


Solution

  • VHDL is a hardware description language. Each process represents a piece of hardware. You are driving the signal internal_stamp from two processes.; you have a short circuit. When you comment out the line

     internal_stamp <= (others => (others => '0'));
    

    this results in internal_stamp being driven from only one process. Hence no short circuit and no 'X' values.

    If you're coding sequential logic, you should stick to a template. Here is one such template for sequential logic with an asynchronous reset, which all synthesis tools should understand:

    process(clock, async_reset)  -- nothing else should go in the sensitivity list
    begin
        -- never put anything here
        if async_reset ='1' then  -- or '0' for an active low reset
            -- set/reset the flip-flops here
            -- ie drive the signals to their initial values
        elsif rising_edge(clock) then  -- or falling_edge(clock)
            -- put the synchronous stuff here
            -- ie the stuff that happens on the rising or falling edge of the clock
        end if;
         -- never put anything here
    end process;        
    

    Here is a template for sequential logic without an asynchronous reset:

    process(clock)  -- nothing else should go in the sensitivity list
    begin
        if rising_edge(clock) then  -- or falling_edge(clock)
            -- put the synchronous stuff here (including the reset)
            -- ie the stuff that happens on the rising or falling edge of the clock
        end if;
         -- never put anything here
    end process;        
    

    So, you should code your logic using one process, not two. Assuming you want an asynchronous reset:

    process(clk, reset)
        begin
            if reset = '1' then
              report "reset triggered"; 
              internal_stamp <= (others => (others => '0'));
              alarm <= '0';
            elsif(rising_edge(clk)) then
              internal_stamp(0) <= internal_stamp(0) + 1;
            end if;
        end process;
    

    However, if you want a synchronous reset:

    process(clk)
        begin
          if(rising_edge(clk)) then
            if reset = '1' then
              report "reset triggered"; 
              internal_stamp <= (others => (others => '0'));
              alarm <= '0';
            else
              internal_stamp(0) <= internal_stamp(0) + 1;
            end if;
        end process;