Search code examples
vhdlfpgamodelsimquartus

VHDL integers counting all over the place when incremented or decremented


I've written a simple VHDL clock-gated process containing two variables, an integer counting up (counter_up) and an integer counting down (counter_down), tied to an LED output each.

The goal of this test system is to simply have the outputs asserted whenever the counters reach a target value from a set starting value. counter_up starts at 10 and outputs its LED at 20. counter_down starts at 25 and outputs its LED at 5. These will continue to count and over/under flow respectively. Both counters range from 0 to 31 (5 bits).

The 'counting all over the place' happens when I test this on modelsim with a simulated clock as shown below:

simulation results

The counters do give an output after 10 and 20 steps respectively, but nothing along the way seems to make any sense and I'm not sure how it would behave if I were to try any arithmetic on the counter values (eg. with the numeric_std library).

What is the cause of this issue and is it possible to force them to be simulated with expected values?

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY test IS PORT(

    clk: IN STD_LOGIC;
    led_1,led_2: OUT STD_LOGIC
    );
END;

ARCHITECTURE arch_test OF test IS

BEGIN
    PROCESS(clk)
        VARIABLE counter_up: INTEGER RANGE 0 TO 31 := 10;
        VARIABLE counter_down: INTEGER RANGE 0 TO 31 := 25;
    BEGIN
        IF clk'EVENT AND clk = '1' THEN

            counter_up := counter_up + 1;

            IF counter_up = 20 THEN
                led_1 <= '1';
            ELSE
                led_1 <= '0';
            END IF;

            counter_down := counter_down - 1;

            IF counter_down = 5 THEN
                led_2 <= '1';
            ELSE
                led_2 <= '0';
            END IF;

        END IF;
    END PROCESS;
END;

Solution

  • They're not exactly all over the place, note that if you invert counter_up bits 1, 3 and 4 you'll get a perfect sequence of incremental values and something similar seemingly happens with counter_down. It's as if the tool interpreted a constrained range of integers as an enumeration and then decided to encode it on this weird pattern, but like @Brian said, this is not something a simulator would do, so I'm guessing this is likely a post synth simulation.

    Try using unsigned(4 downto 0) instead of integers, you'll need to change the initial value of conter_up and counter_down to to_unsigned(10, 5) and to_unsigned(25, 5) respectively.