Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17039 Discussions

simple VHDL program --> need help please

Altera_Forum
Honored Contributor II
1,608 Views

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

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.

0 Kudos
Altera_Forum
Honored Contributor II
868 Views

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

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 !
0 Kudos
Altera_Forum
Honored Contributor II
868 Views

TO_BE_DONE

0 Kudos
Altera_Forum
Honored Contributor II
868 Views

thank you !  

 

my input signal comes from rotary encoder which generates pulses while rotating...
0 Kudos
Altera_Forum
Honored Contributor II
868 Views

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

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;
0 Kudos
Reply