Search code examples
vhdlincrementunsigned

I can't increment an unsigned number in VHDL


So I tried the main method that I came across on internet and it never worked, I tried many different things but can't seem to make it work. When it is supposed to do the first increment, the unsigned counter will go from 000000 to 00000X and then on the second increment it will go to XXXXXX.

My code just below :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Horloge_3s is
    Port ( rst_n : in STD_LOGIC;
           clk : in STD_LOGIC;
           start_3s : in STD_LOGIC;
           etat_systeme : in STD_LOGIC_VECTOR (1 downto 0);
           end_3s : out STD_LOGIC);
end Horloge_3s;

architecture Behavioral of Horloge_3s is

type states is (notCounting, counting, newGame);
signal current_state, future_state : states;
signal counter, counterInc : unsigned (28 downto 0) := (others => '0');

begin

registre : process(clk, rst_n)
begin
    if rst_n = '0' then
        counter <= "00000000000000000000000000000";
        current_state <= notCounting;
    elsif rising_edge(clk) then
        --if current_state = counting then
            --counter <= counter + 1;
       -- end if; 
        current_state <= future_state;
    end if;
end process;

compteur : process(current_state, counter)
begin
        
    if current_state = counting then
        if counter = "10001111000011010001100000000" then
            end_3s <= '1';
        else
            end_3s <= '0';
            counter <= counterInc + 1;
        end if;
    elsif current_state = notCounting then
        counter <= "00000000000000000000000000000";
        end_3s <= '0';
    elsif current_state = newGame then
        counter <= "00000000000000000000000000000";
        end_3s <= '0';
    end if;

end process;

combiEtats : process(current_state, start_3s, etat_systeme)
begin
    
    if etat_systeme = "00" then
        future_state <= newGame;
    else
        case current_state is
            when notCounting => 
                if start_3s = '1' then
                    future_state <= counting;
                else
                    future_state <= notCounting;
                end if;
            when counting =>
                if counter = "10001111000011010001100000000" then
                    future_state <= notCounting;
                else
                    future_state <= counting;
                end if;
            when newGame => 
                future_state <= notCounting;
            when others => 
                future_state <= notCounting;
        end case;
    end if;
         
end process;      

end Behavioral;

Solution

  • You have counter assigned in multiple processes, hence it has multiple drivers. Initially this works as they are both driving '0' on counter as you initialised it to 0, but when you add one, process registre is driving 0 from the reset and process compteur is now driving 1, hence you have a 0 and 1 driving against each other causing 'X'. Solution is to only drive counter from a single process.

    As this is a counter, you really should be driving it from a clcoked process, not a combinatorial one. Having a counter in a combinatorial process will cause it to count up in an infinite loop in 0 time.