-- Johnson counter (4-bit); synchronous circuit with asynchronous reset

library ieee;
use ieee.std_logic_1164.all;

entity JohnsonCounter is
  port (
    CLK:        in STD_LOGIC; -- system clock
    CLK_ENABLE: in STD_LOGIC; -- clock enable
    RESET:      in STD_LOGIC; -- asynchronous reset
    HOLD:       in STD_LOGIC; -- hold the present register value
    DIR:        in STD_LOGIC; -- shift direction
    Q:          out STD_LOGIC_VECTOR (3 downto 0) -- counter output
);
end JohnsonCounter;

architecture JohnsonCounter_arch of JohnsonCounter is
signal IQ: STD_LOGIC_VECTOR (3 downto 0);
begin
process (CLK,CLK_ENABLE,RESET,HOLD,DIR,IQ)
  begin
    if (RESET='1') then 
      IQ <= (others=>'0'); -- asynchronous clear
    elsif (CLK'event and CLK='1' and CLK_ENABLE='1') then
      if HOLD='1' then
        IQ <= IQ; -- hold current value
      elsif DIR='1' then
        IQ <= (not IQ(0)) & IQ(3 downto 1); -- shift right
      else
        IQ <= IQ(2 downto 0) & (not IQ(3)); -- shift left
      end if;
    end if;
    Q <= IQ;
  end process;
end JohnsonCounter_arch;
