Forum Discussion
Altera_Forum
Honored Contributor
17 years agoCounter 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 correct5 Replies
- Altera_Forum
Honored Contributor
Now it works. The problem was the unsynchronised signal. When i register it, as batfink wrote there ar no more problems!
Thanks again - Altera_Forum
Honored 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
Honored Contributor
Yes indeed, but I have assumed the signal is synchronised already
- Altera_Forum
Honored 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:
and then:in_signal_d <= in_signal; in_signal_dd <= in_signal_d;
(I'd also probably separate the code out into two processes but that's just my personal preference).if in_signal_d /= in_signal_dd then ... - Altera_Forum
Honored Contributor
Your code is too nested and complicated...
the following idea of counting may helpsignal 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);