Forum Discussion

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

Counter Problems

Hi,

im trying to implement a counter which counts positive, negative, or both edges of an incoming signal. It works, but if I give 10000pulses to it it counts only between 9980...9997. The internal FPGA clk is 10MHz and the signal to count comes along with 1kHz and a ontime of 50usec.

Here is the counter part:

Detect_Edges : FOR i IN 1 TO nbr_of_Counters GENERATE

PROCESS(Clk_I, reset_I, Enable_S, CntEdge_S, DIO_Stati_I, CountPort_S)

VARIABLE was_on : boolean;

VARIABLE cnt : integer;

BEGIN

IF reset_I = '1' THEN

cnt := 0;

was_on := TRUE;

ELSIF rising_edge(clk_I) THEN

IF ResetCounter_S(i) = '1' THEN

cnt := 0;

was_on := TRUE;

ELSIF Set_Counter_S(i) = '1' THEN

cnt := CONV_INTEGER(unsigned(CntSet_value_S));

ELSIF Enable_S(i) = '0' THEN

NULL;

ELSIF DIO_Stati_I(CountPort_S(i)) = '1' AND was_on = FALSE THEN

was_on := TRUE;

IF CntEdge_S(i) /= COUNT_ON_FALLING_EDGE THEN

IF CntDir_S(i) = '1' THEN

cnt := cnt + 1;

ELSE

cnt := cnt - 1;

END IF;

END IF;

ELSIF DIO_Stati_I(CountPort_S(i)) = '0' AND was_on = TRUE THEN

was_on := FALSE;

IF CntEdge_S(i) /= COUNT_ON_RISING_EDGE THEN

IF CntDir_S(i) = '1' THEN

cnt := cnt + 1;

ELSE

cnt := cnt - 1;

END IF;

END IF;

END IF;

CntValues_S(i) <= CONV_STD_LOGIC_VECTOR(cnt,32);

END IF;

END PROCESS;

END GENERATE;

Has anyone an idea?

If i count the pulses with an other counter the# is correct

5 Replies

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

    Your code is too nested and complicated...

    the following idea of counting may help

    
     
    signal count : signed(32 downto 0);
    signal temp : signed(1 downto 0);
     
    process(reset,clk)
    begin
    if reset = '1' then
        in_signal_d <= '0';
        temp <= "00";
        count <= (others => '0');
    elsif rising_edge(clk) then
     
       in_signal_d <= in_signal;  -- your incoming signal
     
       if count_up = '1' then
            temp <= "01";        --   +1
       else
           temp <= "11";         --   -1
       end if;
     
       if in_signal /= in_signal_d then   -- either edge
          count <= count + temp;
       end if;
     
    end if;
    end process;
     
    cnt <= std_logic_vector(count);
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I'd add to Kaz's reply by saying that I'd pass in_signal through two registers and not present the "raw" unsynchronised signal to any logic, in order to avoid metastability:

    in_signal_d <= in_signal;
    in_signal_dd <= in_signal_d;

    and then:

    if in_signal_d /= in_signal_dd then
    ...

    (I'd also probably separate the code out into two processes but that's just my personal preference).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    thanks for your fast response!

    The Signal which i want to count is asynchrounous!

    I'll test the process you wrote.

    Thanks,

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

    Now it works. The problem was the unsynchronised signal. When i register it, as batfink wrote there ar no more problems!

    Thanks again