top of page

MicroZed Chronicles: Glitch Filtering

Our programmable logic designs are often deployed in applications which can be electrically noisy. This noise can affect the signals that are received by the design implemented in programmable logic. For example, it could cause glitches on the signal or bouncing which if not addressed properly, can lead to issues in the design and operation.


Glitches will be of random duration and are not synchronous to the clock edge. As a result, they can result in corruption of downstream information.


The most common way of dealing with this is to use a glitch filter used to filter out glitches and bounce. We implement a glitch filter on many of our designs if we think the application is going to be noisy and needs IO filtering.


Our glitch filter uses a selectable length shift register into which the noisy signal is applied. This is then shifted in until all values of the shift register agree. At that point, the signal can be seen as stable. We do, of course, have to determine how long the potential glitches and bounce could be to ensure the correct sizing of the register for the clock period. This is why our glitch filter is flexible and uses generics to ensure it can be sized appropriately for each application requirement.


The filter should be able to take a noisy input and filter out glitches with a duration of multiple clock pulses.

Since we use VHDL, we will leverage some VHDL 2008 features in the development of the glitch filter. We want to be able to simulate this in all conditions e.g., when using I2C interfaces where we might use H for example to indicate the pull ups on SCL, SDA. Using the to_01 function provided by numeric std ensures that each element of the resultant vector is 0 or 1. We can then use simple signal attributes to ensure all the elements of the array are either one or zero.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity glitch_filter is
    generic(
        G_FILER_LEN     : integer := 8                                          
    );
    port(
        i_clk                 : in std_ulogic;                                     
        i_noisy               : in std_ulogic;                                  
        o_clean               : out std_ulogic                                  
    );
end glitch_filter;

architecture behaviour of glitch_filter is

    signal s_delay_line   : std_ulogic_vector(G_FILER_LEN - 1 downto 0);
    signal s_delay_and    : std_ulogic;
    signal s_delay_nor    : std_ulogic;
    signal s_output_clean : std_ulogic;

begin

    o_clean <= s_output_clean;

    --Delay disctete using delay line
    synchroniser_process : process (i_clk) begin
        if rising_edge(i_clk) then
            s_delay_line <= s_delay_line(G_FILER_LEN - 2 downto 0) & 
                            i_noisy;
        end if;
    end process;

    --Generate AND and NOR of delay line bits
    s_delay_and <= '1' when to_01(s_delay_line) = 
                            (s_delay_line'range => '1') else '0';
    s_delay_nor <= '1' when to_01(s_delay_line) = 
                            (s_delay_line'range => '0') else '0';

    --Set discrete based on delay line
    output_process : process (i_clk) begin
        if rising_edge(i_clk) then
            if s_delay_nor = '1' then
                s_output_clean <= '0';
            elsif s_delay_and = '1' then
                s_output_clean <= '1';
            end if;
        end if;
    end process;

end behaviour;

To test this module, I have created a simple test bench which injects a random number of glitches into the signal. The test bench is driving either one or zero into the module. A number of random glitches are input onto the signal just after the signal changes state. If the filter is performing correctly, these are not visible on the output clean signal generated by the glitch filter.


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

entity glitch_filter_tb is
end;

architecture bench of glitch_filter_tb is

  component glitch_filter
    generic (
      G_FILER_LEN : integer
    );
      port (
      i_clk : in std_ulogic;
      i_noisy : in std_ulogic;
      o_clean : out std_ulogic
    );
  end component;

  -- Clock period
  constant clk_period : time := 10 ns;
  -- Generics
  constant G_FILER_LEN : integer := 8;

  -- Ports
  signal i_clk : std_ulogic :='0';
  signal i_noisy : std_ulogic;
  signal o_clean : std_ulogic;

begin

  i_clk <= not i_clk after (clk_period/2);

  glitch_filter_inst : glitch_filter
    generic map (
      G_FILER_LEN => G_FILER_LEN
    )
    port map (
      i_clk => i_clk,
      i_noisy => i_noisy,
      o_clean => o_clean
    );

uut : process

    variable glitch_duration : integer;
    variable seed1 : positive := 1;
    variable seed2 : positive := 283647823;

    impure function integer_random(min, max : integer) return integer is
        variable random : real;
      begin
        uniform(seed1, seed2, random);
        return integer(round(random * real(max - min) + real(min)));
    end function;

begin
    i_noisy <= '0';
    wait until rising_edge(i_clk);
    wait for G_FILER_LEN * clk_period;
    test: for i in 0 to 1 loop
        i_noisy <= '1';
        wait until rising_edge(i_clk);
        glitch_duration := integer_random(1,5);
        for x in 0 to glitch_duration loop
            i_noisy <= not i_noisy;
            wait until rising_edge(i_clk);
        end loop;
        i_noisy <= '1';
        wait for 20 * clk_period;
        report "loop high completed" severity note;
        i_noisy <= '0';
        wait until rising_edge(i_clk);
        glitch_duration := integer_random(1,5);
        for x in 0 to glitch_duration loop
            i_noisy <= not i_noisy;
            wait until rising_edge(i_clk);
        end loop;
        i_noisy <= '0';
        wait for 20 * clk_period;
        report "loop low completed" severity note;
    end loop;
    report "Simulation complete" severity failure;
    
end process;

end;

Running the test bench shows a random number of pulses being applied after the change of state of the signal. However, examining the output signals show that the filter has correctly filtered out the glitches which might be present on the input signal.


As I said at the beginning, filters like this are very useful to deploy in environments which might be electrically noisy. Combined with other mitigation strategies such as EDAC on BRAMs etc., this is one of the key methods that can be used to implement design resilience.


Hopefully this technique is useful when you design your system for a noisy operation.


Workshops and Webinars


If you enjoyed the blog why not take a look at the free webinars, workshops and training courses we have created over the years. Highlights include

Embedded System Book Do you want to know more about designing embedded systems from scratch? Check out our book on creating embedded systems. This book will walk you through all the stages of requirements, architecture, component selection, schematics, layout, and FPGA / software design. We designed and manufactured the board at the heart of the book! The schematics and layout are available in Altium here Learn more about the board (see previous blogs on Bring up, DDR validation, USB, Sensors) and view the schematics here.



Sponsored by AMD Xilinx

0 comments

Comments


bottom of page