diff --git a/libs/GrayCounter.vhd b/libs/GrayCounter.vhd
new file mode 100644
index 0000000..5e81837
--- /dev/null
+++ b/libs/GrayCounter.vhd
@@ -0,0 +1,119 @@
+----------------------------------------------------------------------------------
+--@ - Name: **Gray Counter**
+--@ - Version: 0.0.2
+--@ - Author: __Maximilian Passarello ([Blog](mpassarello.de))__
+--@ - License: [MIT](LICENSE)
+--@ A synchronous Gray counter with reset and enable
+--@ History:
+-- - 0.0.2 (2024-03-27) Refactored code to use conventions
+-- - 0.0.1 (2009-04-02) Initial version
+----------------------------------------------------------------------------------
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+
+entity GrayCounter is
+ generic (
+ --@ Width of the counter
+ G_Width : integer := 4;
+ --@ Initial value of the counter
+ G_InitialValue : integer := 0;
+ --@ Reset value of the counter
+ G_ResetValue : integer := 0;
+ --@ Counting direction: "UP" or "DOWN"
+ G_CountingDirection : string := "UP";
+ --@ Look ahead value
+ G_LookAhead : integer := 0
+ );
+ port (
+ --@ Clock input; rising edge
+ I_CLK : in std_logic := '0';
+ --@ Clock enable; active high
+ I_CE : in std_logic := '1';
+ --@ Reset input; active high; synchronous
+ I_RST : in std_logic := '0';
+ --@ Count enable; active high
+ I_CountEnable : in std_logic := '0';
+ --@ Gray counter value
+ O_Value : out std_logic_vector(G_Width - 1 downto 0) := (others => '-');
+ --@ Look ahead value
+ O_LAValue : out std_logic_vector(G_Width - 1 downto 0) := (others => '-')
+ );
+end GrayCounter;
+
+architecture Behavioral of GrayCounter is
+ -- Functions
+ --@ Convert Binary to Gray code
+ function BinaryToGray(I_BinaryValue : std_logic_vector)
+ return std_logic_vector is
+ constant K_Width : integer := I_BinaryValue'Length;
+ variable V_GrayValue : std_logic_vector(K_Width - 1 downto 0);
+ begin
+ V_GrayValue(K_Width - 1) := I_BinaryValue(K_Width - 1);
+ for i in 1 to K_Width - 1 loop
+ V_GrayValue((K_Width - 1) - i) := I_BinaryValue((K_Width - 1) - i) xor I_BinaryValue(((K_Width - 1) - i) + 1);
+ end loop;
+ return V_GrayValue(K_Width - 1 downto 0);
+ end function BinaryToGray;
+
+ --@ Convert Gray code to binary
+ function GrayToBinary(I_GrayValue : std_logic_vector)
+ return std_logic_vector is
+ constant K_Width : integer := I_GrayValue'Length;
+ variable V_BinaryValue : std_logic_vector(K_Width - 1 downto 0);
+ begin
+ V_BinaryValue(K_Width - 1) := I_GrayValue(K_Width - 1);
+ for i in 1 to K_Width - 1 loop
+ V_BinaryValue((K_Width - 1) - i) := V_BinaryValue(K_Width - i) xor I_GrayValue((K_Width - 1) - i);
+ end loop;
+ return V_BinaryValue(K_Width - 1 downto 0);
+ end function GrayToBinary;
+
+ function CountingStep(I_BinaryValue : std_logic_vector; I_Step : integer := 1)
+ return std_logic_vector is
+ begin
+ if G_CountingDirection = "DOWN" then
+ return std_logic_vector(unsigned(I_BinaryValue) - I_Step);
+ else
+ return std_logic_vector(unsigned(I_BinaryValue) + I_Step);
+ end if;
+ end function CountingStep;
+
+ -- Constants
+ constant K_InitialValue : std_logic_vector(G_Width - 1 downto 0) := std_logic_vector(to_unsigned(G_InitialValue, G_Width));
+ constant K_InitialLookAhead : std_logic_vector(G_Width - 1 downto 0) := std_logic_vector(to_unsigned(G_InitialValue + G_LookAhead, G_Width));
+ constant K_ResetValue : std_logic_vector(G_Width - 1 downto 0) := std_logic_vector(to_unsigned(G_ResetValue, G_Width));
+ constant K_ResetLookAhead : std_logic_vector(G_Width - 1 downto 0) := std_logic_vector(to_unsigned(G_ResetValue + G_LookAhead, G_Width));
+
+ signal R_CounterValue : std_logic_vector(G_Width - 1 downto 0) := K_InitialValue;
+ signal R_GrayValue : std_logic_vector(G_Width - 1 downto 0) := BinaryToGray(K_InitialValue);
+ signal R_LookAheadValue : std_logic_vector(G_Width - 1 downto 0) := BinaryToGray(K_InitialLookAhead);
+begin
+
+ O_Value <= R_GrayValue;
+ O_LAValue <= R_LookAheadValue;
+
+ Counter : process (I_CLK)
+ variable V_Counter : std_logic_vector(G_Width - 1 downto 0);
+ variable V_LookAhead : std_logic_vector(G_Width - 1 downto 0);
+ begin
+ if rising_edge(I_CLK) then
+ if I_RST = '1' then
+ V_Counter := (others => '0');
+ R_GrayValue <= BinaryToGray(K_ResetValue);
+ R_LookAheadValue <= BinaryToGray(K_ResetLookAhead);
+ R_CounterValue <= K_ResetValue;
+ elsif I_CE = '1' then
+ if I_CountEnable = '1' then
+ V_Counter := CountingStep(R_CounterValue);
+
+ R_CounterValue <= V_Counter;
+ R_GrayValue <= BinaryToGray(V_Counter);
+
+ V_LookAhead := CountingStep(V_Counter, G_LookAhead);
+ R_LookAheadValue <= BinaryToGray(V_LookAhead);
+ end if;
+ end if;
+ end if;
+ end process;
+end Behavioral;
diff --git a/tests/GrayCounter_tb.vhd b/tests/GrayCounter_tb.vhd
new file mode 100644
index 0000000..90c5bc5
--- /dev/null
+++ b/tests/GrayCounter_tb.vhd
@@ -0,0 +1,46 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity GrayCounter_tb is
+end;
+
+architecture bench of GrayCounter_tb is
+ -- Clock period
+ constant clk_period : time := 10 ns;
+ -- Generics
+ constant G_Width : integer := 6;
+ constant G_InitialValue : integer := 0;
+ constant G_ResetValue : integer := 0;
+ constant G_CountingDirection : string := "UP";
+ constant G_LookAhead : integer := 1;
+ -- Ports
+ signal I_CLK : std_logic := '0';
+ signal I_CE : std_logic := '1';
+ signal I_RST : std_logic := '0';
+ signal I_CountEnable : std_logic := '1';
+ signal O_Value : std_logic_vector(G_Width - 1 downto 0);
+ signal O_LookAheadValue : std_logic_vector(G_Width - 1 downto 0);
+begin
+
+ GrayCounter_inst : entity work.GrayCounter
+ generic map (
+ G_Width => G_Width,
+ G_InitialValue => G_InitialValue,
+ G_ResetValue => G_ResetValue,
+ G_CountingDirection => G_CountingDirection,
+ G_LookAhead => G_LookAhead
+ )
+ port map (
+ I_CLK => I_CLK,
+ I_CE => I_CE,
+ I_RST => I_RST,
+ I_CountEnable => I_CountEnable,
+ O_Value => O_Value,
+ O_LAValue => O_LookAheadValue
+ );
+
+ I_CLK <= not I_CLK after clk_period/2;
+
+end;
\ No newline at end of file