Forum Discussion

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

simple VHDL program --> need help please

i have an external asynchronious signal (called "sig") which i have to count its rising or falling edges. i wrote a program which somehow ends very quickly --> after 2 rising edges, req_dist = 32 --> req_dist(8 downto 1)=16 .

is someone can see what is my problem ? thank you very much for help...

library IEEE;

use IEEE.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;

entity encoder is

port(

CLK : in std_logic;

sig : in std_logic ;

reset : in std_logic;

req_dist: in std_logic_vector(8 downto 0); --required distance

arrived : out std_logic

);

end entity encoder;

architecture arc_encoder of encoder is

signal counter : std_logic_vector(8 downto 0) := "000000000";

signal distance : std_logic_vector(8 downto 0);

signal flag : bit := '1' ;

begin

process(CLK,reset)

begin

if (reset = '1') then

counter <= (others => '0');

arrived <= '0';

flag <='1';

elsif(rising_edge(CLK)) then

if(req_dist /= "0") then

if (sig = '0' or flag = '0') then

flag <='0';

if (sig ='1') then

if (counter < req_dist(8 downto 1)) then

counter <= counter + '1';

flag <='1';

else

arrived <= '1';

counter <= (others => '0');

flag <='1';

end if;

end if;

end if;

end if;

end if;

end process;

end architecture;

7 Replies

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

    if sig is asynchronous, you need to synchronoise it otherwise you're potentially sampling it on a transition. You need at least a double register to avoid any metastability.

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

    Hi,

    Please Quote your code with [ code]...[ /code]

    You don't need "use ieee.std_logic_arith.all;"

    if(req_dist /= "0") then

    req_dist is a vector, i don't know how it is interpreted.

    Maybe you have metastability events. Put at least 2 D-FlipFlop on your signal "sig".

    Quite complicated to count signal edges.

    I suggest (not complete) :

    
         process (reset, clk)
          variable detect      : STD_ULOGIC_VECTOR(1 downto 0);
          variable count       : UNSIGNED(8 downto 0);
       begin
          if reset_n = '1' then
             detect := "00";
             count := 0;
              arrived <= '0';
             
          elsif rising_edge(clk) then
                
                detect(1) := detect(0);
                detect(0) := sig; -- sig after 2 DFF to avoid metastibility
             
                if (detect = "01") or (detect = "10") then -- detecting rising edge or falling edge
                   
                   if count < req_dist(8 downto 1) then 
                      count := count + 1;
                   else
                      arrived <= '1';
                      counter <= (others => '0');             
                   
                end if; 
          end if;
       end process;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i can really see the metastabillity situation in signal tap.

    i understood how to implement a rising/falling edge by "detect" variable. but how do i combine 2 DFF to this program ?

    very appriciate your help !
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thank you !

    my input signal comes from rotary encoder which generates pulses while rotating...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    [ code]...[ /code]

    thats what i done : (its does not work , still the same situation ... maybe the incoming signal ("sig") is bouncing like you sayed...)

    what do you suggest to try ?

    process (reset, clk)

    variable detect : STD_ULOGIC_VECTOR(1 downto 0);

    variable count : UNSIGNED(8 downto 0);

    begin

    if reset= '1' then

    detect := "00";

    counter <= (others => '0');

    arrived <= '0';

    final_sig <= '0';

    sig1 <= '0';

    sig2 <= '0';

    count_flag<= (others => '0');

    elsif rising_edge(CLK) then

    sig1 <= sig;

    sig2 <= sig1;

    final_sig <= sig2;

    -- rising_edge <= sig2 and not(final_sig);

    -- count_flag<= count_flag+1;

    -- if(count_flag > 3) then

    detect(1) := detect(0);

    detect(0) := sig2 and not(final_sig); -- sig after 2 DFF to avoid metastibility

    if (detect = "01") or (detect = "10") then -- detecting rising edge or falling edge

    if (counter < req_dist(8 downto 1)) then

    counter <= counter + 1;

    else

    arrived <= '1';

    counter <= (others => '0');

    count_flag<= (others => '0');

    end if;

    end if;

    -- end if;

    end if;

    end process;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    first debounce significantly your 'sig' signal : very quite easy to write with other process with counter

    * that counts to a fixed value if no 'sig' event happens

    * that be cleared if a 'sig' event happens.

    For example, clk is 20ns-periode (50MHz) and you want to not consider pulse < 100us. So counter for this will count to (100us/20ns = 5000) if no event happens.

    Just little but important corrections here :

    
    process (reset, clk)
       variable detect : STD_ULOGIC_VECTOR(1 downto 0);
       -- variable count : UNSIGNED(8 downto 0); -- not used here
    begin
    if reset= '1' then
       detect := "00";
       counter <= (others => '0');
       arrived <= '0';
       final_sig <= '0';
       sig1 <= '0';
       sig2 <= '0';
       count_flag<= (others => '0');
    elsif rising_edge(CLK) then
       sig1 <= sig;
       sig2 <= sig1;
       final_sig <= sig2;
       -- rising_edge <= sig2 and not(final_sig); -- one way to detect rising_edge
       -- count_flag<= count_flag+1;
       -- if(count_flag > 3) then
       detect(1) := detect(0); -- other way to detect edges
       detect(0) := sig2 ; -- sig2 only !!
       if (detect = "01") or (detect = "10") then -- detecting rising edge or falling edge
          if (counter < req_dist(8 downto 1)) then
             counter <= counter + 1;
          else
             arrived <= '1';
             counter <= (others => '0');
             count_flag<= (others => '0');
          end if;
       end if;
       -- end if;
       end if;
    end process;