---------------------------------------------------------------------------------- --@ - 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;