Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

up down counter problem

hi everyone

i try to make a project to count people entering or going out from a hall

using VHDL and altera board DE0

i made two clocks one for counting up (clku) it come from a trigger outside board

and one for counting down (clkd) also come from a trigger outside board .

but when doing this Error 10820 appear that says "can't infer register for count because its behavior depends on the edges of multiple distinct clocks"

the Full Code is here

ENTITY mod_ten_ud ISPORT(

clku,clkd, enable :IN BIT ;

q :OUT INTEGER RANGE 0 TO 9);END mod_ten_ud;

ARCHITECTURE a OF mod_ten_ud

ISBEGIN

PROCESS (clku ,clkd)

VARIABLE count :INTEGER RANGE 0 TO 9;

BEGIN

IFenable = '1'

THEN

IF( clku = '1' AND clku'EVENT )

THEN count := count + 1;

ELSIF( clkd = '1' AND clkd'EVENT )

THEN count := count - 1;

END IF;

END IF;

q <= count;

END PROCESS;

END a;

please help me because it is my final study project and thanks a lot

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    First: Please use the CODE-Tags for Code. (obvious, isn't it?)

    ENTITY mod_ten_ud ISPORT(
    clku,clkd, enable :IN BIT ;
    q :OUT INTEGER RANGE 0 TO 9);END mod_ten_ud;
    ARCHITECTURE a OF mod_ten_ud
    ISBEGIN
    PROCESS (clku ,clkd)
    VARIABLE count :INTEGER RANGE 0 TO 9;
    BEGIN
    IFenable = '1'
    THEN
    IF( clku = '1' AND clku'EVENT )
    THEN count := count + 1;
    ELSIF( clkd = '1' AND clkd'EVENT )
    THEN count := count - 1;
    END IF;
    END IF;
    q <= count;
    END PROCESS;
    END a;

    Second: You can't use two clock edges in one process. And it is rather bad style to declare a simple signal as clock and count on the clock edges.

    Better is:

    You create one very fast clock to sample your two input signals. Like this:

    
    if (rising_edge(fast_clk)) then
       prev_sig1   <= sig1;
       prev_sig2   <= sig2;
       if ((prev_sig1 = '0') and (sig1 = '1')) then
          {count up}
       end if;
       if ((prev_sig2 = '0') and (sig2 = '1')) then
          {count down}
       end if;
    end if;
    

    This will also give you something like an edge-detect on your signals. But without the meaning that these are clocks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    As the signals are asynchronous (external to the board) they need to pass each a double FF synchronizer before entering the edge detection. Otherwise you should expect a certain amount of counting errors (missed or double counted events).

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I've had a little play and this is how I would do an up down counter:

    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity people_count is
    generic 
         (
           COUNTER_WIDTH: integer := 8
         );
    port (
            in_clk      : in std_logic;
            in_reset    : in std_logic;
            in_incCount : in std_logic;
            in_decCount : in std_logic;
            
            out_count : out std_logic_vector(COUNTER_WIDTH-1 downto 0)
            );
    end entity people_count;
    architecture arch_people_count of people_count is
    signal count: unsigned(COUNTER_WIDTH-1 downto 0);
    signal count_up: std_logic;
    signal count_down: std_logic;
    begin
       
      count_up <= '1' when in_incCount ='1' and in_decCount = '0' else '0';
      count_down <= '1' when in_incCount ='0' and in_decCount = '1' else '0';
      
      process(in_clk, in_reset)
      begin
        if in_reset = '1' then
           count <= (others => '0');
        elsif rising_edge(in_clk) then 
           if (count_up = '1') then
            count <= count + 1;
            elsif (count_down = '1') then
              count <= count - 1;
            end if;
        end if;
      end process;
      
      out_count <= std_logic_vector(count);
      
    end architecture arch_people_count;
    

    but you would need to synchronize the inputs, debounce the switch and put an edge detector on the input!

    have fun :)

    geobyjmh

    http://geobyjmhembeddedengineer.blogspot.co.uk/