3

I have this simple VHDL Code aufg4.vhd:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity aufg4 is
    Port ( 
        clock : in  std_logic
            );
end aufg4;

architecture Behavioral of aufg4 is

    signal tut_counter : integer range 0 to 90 := 0; -- counts tutorial time

begin

    do_process :process(clock)
        begin
            if(rising_edge(clock)) then
                report "tut_counter " & integer'image(tut_counter);
                if(tut_counter >= 90) then
                    tut_counter <= 0;   
                    report "tut_counter reset";
                end if;
                tut_counter <= tut_counter + 1;
            end if;
        end process;

end Behavioral;

And the testbench aufg4_tb.vhd:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY aufg4_tb IS
END aufg4_tb;

ARCHITECTURE behavior OF aufg4_tb IS 

     COMPONENT aufg4
     PORT(
        clock : IN  std_logic
          );
     END COMPONENT;

    --Inputs
    signal clock : std_logic := '0';

    -- Clock period definitions
    constant clock_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
    uut: aufg4 PORT MAP (
    clock => clock
          );

    -- Clock process definitions
    clock_process :process
    begin
        clock <= '0';
        wait for clock_period/2;
        clock <= '1';
        wait for clock_period/2;
    end process;

END;

When I simulate the Behavioral Model report outputs:

 ...
at 885 ns(1): Note: tut_counter 88 (/aufg4_tb/uut/).
at 895 ns(1): Note: tut_counter 89 (/aufg4_tb/uut/).
at 905 ns(1): Note: tut_counter 90 (/aufg4_tb/uut/).
at 905 ns(1): Note: tut_counter reset (/aufg4_tb/uut/).
at 915 ns(1): Note: tut_counter 91 (/aufg4_tb/uut/).
at 915 ns(1): Note: tut_counter reset (/aufg4_tb/uut/).
at 925 ns(1): Note: tut_counter 92 (/aufg4_tb/uut/).
at 925 ns(1): Note: tut_counter reset (/aufg4_tb/uut/).
at 935 ns(1): Note: tut_counter 93 (/aufg4_tb/uut/).
...

So the if-statement works properly, but the reassignment of the signal tut_counter does not work.

So why is that?

And why does the simulation do not through an error because tut_counter just has a range from 0 to 90?

goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • 1
    http://stackoverflow.com/questions/13954193/is-process-in-vhdl-reentrant/13956532#13956532 –  Nov 06 '16 at 13:37
  • 2
    +1 for a well asked question by the way. As to why it doesn't report an error - at a wild guess, you're using Xilinx ISIM. It's broken by default, and been that way for years, but there's a "properties" option (under the "advanced" tab I think) to turn range checking on and fix it.. –  Nov 06 '16 at 13:40
  • @BrianDrummond How can I get this kind of reassignment `event` to work properly ? – goulashsoup Nov 06 '16 at 14:04
  • remember "last assignment wins" and also there's an `else` keyword. –  Nov 06 '16 at 14:16
  • @BrianDrummond ok thanks! Just to make sure I understand it right: 1. All `events` in VHDL occur at the same time, so there is no order for commands of any kind but the "last assignment wins"? 2. It is possible to simulate an order by using wait statements which is not possible in my case, because I use a sensitivity list, right? – goulashsoup Nov 06 '16 at 14:23
  • Not quite. Commands happen in a strict order but in zero time, but signal assignments only happen when the process suspends (so a later one overrides the earlier ones). Wait just suspends the process at the Wait instead of at the end. –  Nov 06 '16 at 15:36
  • 1
    Just to clarify Brian's answer about "last assignment wins". This is the case for **sequential** processes. Concurrent assignments occur at the "same time" (roughly, each happens at different delta cycles--but the same time value (ps, ns, etc). – PlayDough Nov 07 '16 at 20:21

1 Answers1

-1

Using a else instead solves the problem quite well!

do_process :process(clock)
    begin
        if(rising_edge(clock)) then
            report "tut_counter " & integer'image(tut_counter);
            if(tut_counter >= 90) then
                tut_counter := 0;   
                report "tut_counter reset";
            else
                tut_counter := tut_counter + 1;
            end if;
        end if;
    end process;

Otherwise you could use a variable: variable tut_counter : integer range 0 to 90 := 0; -- counts tutorial time

goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • Sorta. This would reset the counter to 1, not 0. So you are going to get 0, 1, 2, ..., 90, 1, 2, 3, ...., 90, 1, 2, .... Note Brian's point about the `else` statement. – PlayDough Nov 07 '16 at 20:19
  • Besides the bit where this doesn't actually solve the problem, using variables where signals will work perfectly fine is a great way to produce inefficient synthesized hardware and hard to identify bugs. Had you just moved the line "`tut_counter <= tut_counter + 1;`" into an `else` clause of "`if(tut_counter >= 90) then`" it would have worked fine (avoiding overwriting an assignment too). – QuantumRipple Nov 07 '16 at 21:00
  • Yes I know... @QuantumRipple Why does VHDL does have variables if it is not allowed to use them? – goulashsoup Nov 08 '16 at 19:44
  • 1
    @goulashsoup The same reason C has pointers/dynamic allocation that you can easily cause memory leaks with; they have valid uses. There are places where variables can greatly simplify the representation and some hardware can't be described in a modular (paramaterized) fashion without variables. They're also great for use in simulation-only code where you can treat VHDL more like software instead of describing hardware. Yet, like pointers, they are dangerous and probably shouldn't be used where they aren't needed. – QuantumRipple Nov 08 '16 at 19:49