- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 !- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
TO_BE_DONE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thank you !
my input signal comes from rotary encoder which generates pulses while rotating...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[ 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;- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page