Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Counter Problems

Altera_Forum
Honored Contributor II
1,533 Views

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
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
618 Views

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);
0 Kudos
Altera_Forum
Honored Contributor II
618 Views

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).
0 Kudos
Altera_Forum
Honored Contributor II
618 Views

Yes indeed, but I have assumed the signal is synchronised already

0 Kudos
Altera_Forum
Honored Contributor II
618 Views

Hi, 

 

thanks for your fast response!  

The Signal which i want to count is asynchrounous! 

I'll test the process you wrote. 

 

Thanks, 

 

Patrick
0 Kudos
Altera_Forum
Honored Contributor II
618 Views

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

 

Thanks again
0 Kudos
Reply