Better rotary encoder input

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA project was completed in November 2015.

My original Rotary encoder project pmodenc was fine for most things, but it passed any noise / bounces of the rotary encoder encoder through to the downstream modules.

With a bit of thinking I came up with this improved design. After synchronizing the inputs, it keeps track of the last three states, and only generates a output signal if all of these states differ.

So where as an input of .... 00, 00, 00, 01, 00, 01, 00, 01, 11, 11, 11, 11..... would output up, down, up, down, up, up signals, this design just generates one or two 'up' pulses (depending on the initial state of the system).

I really like it as it doesn't need any debounce timers or lots of resources.

Source

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pmod_enc_v2 is
    Port ( clk        : in  STD_LOGIC;
           enc_a      : in  STD_LOGIC;
           enc_b      : in  STD_LOGIC;
           count_en   : out  STD_LOGIC;
           count_dir : out  STD_LOGIC);
end pmod_enc_v2;

architecture Behavioral of pmod_enc_v2 is
   signal enc_quad_sr : std_logic_vector(7 downto 0) := (others => '0');
   attribute keep : string;
   attribute keep of enc_quad_sr: signal is "true";  
begin
   
process(clk)
   begin
      if rising_edge(clk) then
         count_en  <= '0';
         count_dir <= '0';         
         case enc_quad_sr(5 downto 0) is
             when "010010" => count_en <= '1'; 
             when "001011" => count_en <= '1';
             when "101101" => count_en <= '1';
             when "110100" => count_en <= '1';
             when "100001" => count_en <= '1'; count_dir <= '1';
             when "000111" => count_en <= '1'; count_dir <= '1';
             when "011110" => count_en <= '1'; count_dir <= '1';
             when "111000" => count_en <= '1'; count_dir <= '1';
             when others => NULL;
         end case;
         -- Last two pairs in enc_quad_sr only shift when synchronised input has changed
         if enc_quad_sr(5 downto 4) /=  enc_quad_sr(3 downto 2) then 
            enc_quad_sr(3 downto 0) <= enc_quad_sr(5 downto 2);
         end if;
         -- First two pairs act as a synchroniser for the encoder
         enc_quad_sr(7 downto 4) <= enc_b & enc_a & enc_quad_sr(7 downto 6);            
      end if;
   end process;
end Behavioral;

Personal tools