+ Post New Thread
Results 1 to 11 of 11
  1. #1
    Member level 2
    Points: 1,726, Level: 9
    Achievements:
    7 years registered
    shahulakthar's Avatar
    Join Date
    Oct 2009
    Location
    Chennai, India
    Posts
    45
    Helped
    12 / 12
    Points
    1,726
    Level
    9

    Asynchronous pulse counter on fpga

    I need to count the external pulse coming on to FPGA.
    Total time i take to count pulse is 5 sec.

    internal clock is 50mhz.

    external pulse duration is around 0.5 sec to 1.5 sec. so i am calculating number of pulses for 5 sec.

    last 5sec pulses needs to be updated on 8 bit LED's.

    not working as expected. output always shows "11110100" or "00000001"

    Here is the VHDL code

    Code:
    library IEEE;
    use IEEE.std_logic_1164.ALL;
    use IEEE.numeric_std.ALL;
    
    entity fcnt is
        port (
    	C : in std_logic;
    	S : in std_logic;
    	Q : out unsigned(7 downto 0));
    end entity;
    
    architecture RTL of fcnt is
    
        constant MAX_CLK : integer := 250000000;
        constant MAX_CNT : integer := 500;
    
        signal count : unsigned(Q'range) := (others => '0');
        signal toggle : std_logic := '0';
    
    begin
    
        clk_proc : process (C)
    	variable cnt_v : natural range 0 to MAX_CLK := 0;
        begin
    	if rising_edge(C) then
    	    if cnt_v = MAX_CLK then
    		Q <= count;
    		toggle <= not toggle;
    		cnt_v := 0;
    	    else
    		cnt_v := cnt_v + 1;
    	    end if;
    	end if;
        end process;
    
        cnt_proc : process (S, toggle)
    	variable cnt_v : natural range 0 to MAX_CNT := 0;
    	variable last_v : std_logic := '0';
        begin
    	if toggle /= last_v then 
    	    last_v := toggle;
    	    cnt_v := 0;
    
    	elsif rising_edge(S) then
    	    if cnt_v < MAX_CNT then
    		cnt_v := cnt_v + 1;
    	    end if;
    	    count <= to_unsigned(cnt_v, count'length);
    	end if;
        end process;
    
    end RTL;
    Regards,
    shahul

  2. #2
    Advanced Member level 5
    Points: 21,049, Level: 35
    barry's Avatar
    Join Date
    Mar 2005
    Location
    California, USA
    Posts
    4,053
    Helped
    881 / 881
    Points
    21,049
    Level
    35

    Re: Asynchronous pulse counter on fpga

    So many questions:
    Which signal is your external pulse?
    Which one is your internal clock?
    Why do you have those variables in the second process outside the clock ?
    It's really not clear what you're trying to do here.



    •   AltAdvertisment

        
       

  3. #3
    Member level 2
    Points: 1,726, Level: 9
    Achievements:
    7 years registered
    shahulakthar's Avatar
    Join Date
    Oct 2009
    Location
    Chennai, India
    Posts
    45
    Helped
    12 / 12
    Points
    1,726
    Level
    9

    Re: Asynchronous pulse counter on fpga

    Which signal is your external pulse?
    S is the external pulse

    Which one is your internal clock?
    C is the internal 50 Mhz clock

    Why do you have those variables in the second process outside the clock ?
    second process is based on toggle and external pulse. not based on the internal clock.

    It's really not clear what you're trying to do here.
    I want to count the number of asynchronous pulse (S) for 5 seconds.



    •   AltAdvertisment

        
       

  4. #4
    Super Moderator
    Points: 61,891, Level: 60
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    12,614
    Helped
    2924 / 2924
    Points
    61,891
    Level
    60

    Re: Asynchronous pulse counter on fpga

    Hi,

    From hardware view...

    I'd simply synchronize the async input signal to the internal clock with a DFF.
    And to detect the rising edge I'd add a second DFF in series...an AND with one inverting input detects the edge
    And this signal may directely act as ENA signal for a counter.

    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



    •   AltAdvertisment

        
       

  5. #5
    Super Moderator
    Points: 245,674, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,678
    Helped
    13007 / 13007
    Points
    245,674
    Level
    100

    Re: Asynchronous pulse counter on fpga

    not working as expected. output always shows "11110100" or "00000001"
    Observed how? What's the test bench?

    In any case, there's no proper synchronization in domain crossing. We would normally synchronize the asynchronous signal into the 50 MHz clock domain.

    The really bad asynchronous code is here
    Code VHDL - [expand]
    1
    2
    3
    
    if toggle /= last_v then 
            last_v := toggle;
            cnt_v := 0;



  6. #6
    Member level 2
    Points: 1,726, Level: 9
    Achievements:
    7 years registered
    shahulakthar's Avatar
    Join Date
    Oct 2009
    Location
    Chennai, India
    Posts
    45
    Helped
    12 / 12
    Points
    1,726
    Level
    9

    Re: Asynchronous pulse counter on fpga

    Quote Originally Posted by KlausST View Post
    Hi,

    From hardware view...

    I'd simply synchronize the async input signal to the internal clock with a DFF.
    And to detect the rising edge I'd add a second DFF in series...an AND with one inverting input detects the edge
    And this signal may directely act as ENA signal for a counter.

    Klaus
    I updated the code with synchronize process. Please let me know is it the right way of synchronize.

    Code:
    library IEEE;
    use IEEE.std_logic_1164.ALL;
    use IEEE.numeric_std.ALL;
    
    entity fcnt is
        port (
    	C : in std_logic;                         --- clock 50mhz
    	S : in std_logic;                         --- external pulse
    	Q : out unsigned(7 downto 0));  ---  pulse count in 5 sec 
    end entity;
    
    architecture RTL of fcnt is
    
        constant MAX_CLK : integer := 250000000;   --- 5 sec duration for pulse count
        constant MAX_CNT : integer := 256;              
    
        signal count : unsigned(Q'range) := (others => '0');
        signal toggle : std_logic := '0';
    	 
    	 signal reg1 :std_logic;
    	 signal reg2 :std_logic;
    	 signal edge :std_logic;
    
    begin
    
        clk_proc : process (C)
    	variable cnt_v : natural range 0 to MAX_CLK := 0;
        begin
    	if rising_edge(C) then
    	    if cnt_v = MAX_CLK then
    		Q <= count;
    		toggle <= not toggle;
    		cnt_v := 0;
    	    else
    		cnt_v := cnt_v + 1;
    	    end if;
    	end if;
        end process;
    	 
    	reg: process(C)
    	begin
    		if rising_edge(C) then
    			reg1  <= S;
    			reg2  <= reg1;
    	  end if;
    	end process;
    
    	edge <= reg1 and (not reg2);
    
    
        cnt_proc : process (edge, toggle)
    	variable cnt_v : natural range 0 to MAX_CNT := 0;
    	variable last_v : std_logic := '0';
        begin
    	if toggle /= last_v then 
    	    last_v := toggle;
    	    cnt_v := 0;
    
    	elsif rising_edge(edge) then
    	    if cnt_v < MAX_CNT then
    		cnt_v := cnt_v + 1;
    	    end if;
    	    count <= to_unsigned(cnt_v, count'length);
    	end if;
        end process;
    	 
    end RTL;
    Above code is not working as expected.



  7. #7
    Super Moderator
    Points: 245,674, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,678
    Helped
    13007 / 13007
    Points
    245,674
    Level
    100

    Re: Asynchronous pulse counter on fpga

    Execute everything under rising_edge(C).



  8. #8
    Member level 2
    Points: 1,726, Level: 9
    Achievements:
    7 years registered
    shahulakthar's Avatar
    Join Date
    Oct 2009
    Location
    Chennai, India
    Posts
    45
    Helped
    12 / 12
    Points
    1,726
    Level
    9

    Re: Asynchronous pulse counter on fpga

    Quote Originally Posted by FvM View Post
    Execute everything under rising_edge(C).
    I am not sure how to execute this process with rising_edge(C)

    Code:
    cnt_proc : process (edge, toggle)
    	variable cnt_v : natural range 0 to MAX_CNT := 0;
    	variable last_v : std_logic := '0';
        begin
    	if toggle /= last_v then 
    	    last_v := toggle;
    	    cnt_v := 0;
    
    	elsif rising_edge(edge) then
    	    if cnt_v < MAX_CNT then
    		cnt_v := cnt_v + 1;
    	    end if;
    	    count <= to_unsigned(cnt_v, count'length);
    	end if;
        end process;



    •   AltAdvertisment

        
       

  9. #9
    Super Moderator
    Points: 61,891, Level: 60
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    12,614
    Helped
    2924 / 2924
    Points
    61,891
    Level
    60

    Re: Asynchronous pulse counter on fpga

    Hi,

    With the "AND" ...EDGE indeed us the rising edge,
    Therefore you don't need an extra "RISING" statement.

    Pseudo code:
    On every rising edge of C:
    ... reg1 = S
    ... reg2 = reg1
    ... if (reg1 and not reg2) then increment counter
    ...

    For sure the timing is delayed by a clock...
    So maybe it's more clear if the order is this way:
    On every rising edge of C:
    ... if (reg1 and not reg2) then increment counter
    ... reg2 = reg1
    ... reg1 = S

    But the result will be exactly the same

    Klaus
    Please donīt contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  10. #10
    Advanced Member level 4
    Points: 7,488, Level: 20
    Achievements:
    7 years registered Created Blog entry
    dpaul's Avatar
    Join Date
    Jan 2008
    Location
    Germay
    Posts
    1,100
    Helped
    244 / 244
    Points
    7,488
    Level
    20
    Blog Entries
    1

    Re: Asynchronous pulse counter on fpga

    Please let me know is it the right way of synchronize.
    Do some further reading on how to synchronize signals crossing from one clock domain to the other. This is a very good paper: http://www.sunburst-design.com/paper...Boston_CDC.pdf

    I am not sure how to execute this process with rising_edge(C)
    Indicates that you also need to brush up your VHDL knowledge.
    .....yes, I do this for fun!



  11. #11
    Super Moderator
    Points: 29,150, Level: 41
    ads-ee's Avatar
    Join Date
    Sep 2013
    Location
    USA
    Posts
    6,721
    Helped
    1604 / 1604
    Points
    29,150
    Level
    41

    Re: Asynchronous pulse counter on fpga

    Code VHDL - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    reg: process(C)
        begin
            if rising_edge(C) then
                reg1  <= S; -- synchronizer FF
                reg2  <= reg1; -- edge detection FF
          end if;
        end process;
     
        edge <= reg1 and (not reg2);
    This is a 1 register synchronizer.
    You need two FFs and then a third to do the edge detection to have a proper 2 stage synchronizer.



--[[ ]]--