| 
    
       ---------------------------------------------------------------------------
 
     | 
  
  
     | 
    
       -- (c) 2018 mark watson
 
     | 
  
  
     | 
    
       -- I am happy for anyone to use this for non-commercial use.
 
     | 
  
  
     | 
    
       -- If my vhdl files are used commercially or otherwise sold,
 
     | 
  
  
     | 
    
       -- please contact me for explicit permission at scrameta (gmail).
 
     | 
  
  
     | 
    
       -- This applies for source and binary form and derived works.
 
     | 
  
  
     | 
    
       ---------------------------------------------------------------------------
 
     | 
  
  
     | 
    
       LIBRARY ieee;
 
     | 
  
  
     | 
    
       USE ieee.std_logic_1164.all;
 
     | 
  
  
     | 
    
       use ieee.numeric_std.all;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       ENTITY phi_mult IS
 
     | 
  
  
     | 
    
       PORT 
 
     | 
  
  
     | 
    
       ( 
 
     | 
  
  
     | 
    
       	clkin : IN STD_LOGIC; -- 55 to 116MHz
 
     | 
  
  
     | 
    
       	phi2 : IN STD_LOGIC;  -- about 1.8MHz
 
     | 
  
  
     | 
    
       	clkout : OUT STD_LOGIC -- about 6x phi2, in sync with phi2!
 
     | 
  
  
     | 
    
       );
 
     | 
  
  
     | 
    
       END phi_mult;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       ARCHITECTURE vhdl OF phi_mult IS
 
     | 
  
  
     | 
    
       	signal measure_next : std_logic_vector(5 downto 0); -- we do not know osc frequency, measure how many cycles in 1 cycle
 
     | 
  
  
     | 
    
       	signal measure_reg : std_logic_vector(5 downto 0);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	signal target_next : std_logic_vector(3 downto 0);  -- this is 1/6 of the cycle length, flip our output every time
 
     | 
  
  
     | 
    
       	signal target_reg : std_logic_vector(3 downto 0);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	signal counter_next : std_logic_vector(3 downto 0);  
 
     | 
  
  
     | 
    
       	signal counter_reg : std_logic_vector(3 downto 0);	
 
     | 
  
  
     | 
    
       	
 
     | 
  
  
     | 
    
       	signal output_next : std_logic;
 
     | 
  
  
     | 
    
       	signal output_reg : std_logic;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	signal phi2_next : std_logic;
 
     | 
  
  
     | 
    
       	signal phi2_reg : std_logic;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	signal phi2_sync : std_logic;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	signal flip : std_logic;
 
     | 
  
  
     | 
    
       begin
 
     | 
  
  
     | 
    
       	phi2_next <= phi2_sync;
 
     | 
  
  
     | 
    
       	process(clkin)
 
     | 
  
  
     | 
    
       	begin
 
     | 
  
  
     | 
    
       		if (clkin'event and clkin='1') then
 
     | 
  
  
     | 
    
       			phi2_reg <= phi2_next;
 
     | 
  
  
     | 
    
       			measure_reg <= measure_next;
 
     | 
  
  
     | 
    
       			target_reg <= target_next;
 
     | 
  
  
     | 
    
       			counter_reg <= counter_next;
 
     | 
  
  
     | 
    
       			output_reg <= output_next;
 
     | 
  
  
     | 
    
       		end if;
 
     | 
  
  
     | 
    
       	end process;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	sync_clk : entity work.synchronizer
 
     | 
  
  
     | 
    
       	port map
 
     | 
  
  
     | 
    
       	(
 
     | 
  
  
     | 
    
       		CLK => clkin,
 
     | 
  
  
     | 
    
       		RAW => phi2,
 
     | 
  
  
     | 
    
       		SYNC => phi2_sync
 
     | 
  
  
     | 
    
       	);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	process(phi2_reg, phi2_sync,measure_reg,target_reg,counter_reg)
 
     | 
  
  
     | 
    
       		variable sum : std_logic_vector(10 downto 0);
 
     | 
  
  
     | 
    
       	begin
 
     | 
  
  
     | 
    
       		measure_next <= std_logic_vector(unsigned(measure_reg) + 1);
 
     | 
  
  
     | 
    
       		target_next <= target_reg;
 
     | 
  
  
     | 
    
       		counter_next  <= std_logic_vector(unsigned(counter_reg) +1);
 
     | 
  
  
     | 
    
       		flip <= '0';
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if (phi2_sync = '1' and phi2_reg = '0') then
 
     | 
  
  
     | 
    
       			measure_next <= "000000";
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       			-- *21/128 to get 1/6
 
     | 
  
  
     | 
    
       			-- 10101 is 20...
 
     | 
  
  
     | 
    
       			sum := std_logic_vector(unsigned("00000"&measure_reg)+unsigned("000"&measure_reg&"00")+unsigned("0"&measure_reg&"0000"));
 
     | 
  
  
     | 
    
       			target_next <= sum(10 downto 7);
 
     | 
  
  
     | 
    
       			counter_next <= "0011";
 
     | 
  
  
     | 
    
       		end if;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if (counter_reg=target_reg) then
 
     | 
  
  
     | 
    
       			counter_next <= (others=>'0');
 
     | 
  
  
     | 
    
       			flip <= '1';
 
     | 
  
  
     | 
    
       		end if;
 
     | 
  
  
     | 
    
       	end process;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       	process(phi2_reg, phi2_sync, flip, output_reg)
 
     | 
  
  
     | 
    
       	begin
 
     | 
  
  
     | 
    
       		output_next <= output_reg;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if (phi2_sync = '1' and phi2_reg = '0') then
 
     | 
  
  
     | 
    
       			output_next <= '1'; -- put in sync (should already be one...)
 
     | 
  
  
     | 
    
       		end if;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       		if (flip='1') then
 
     | 
  
  
     | 
    
       			output_next <= not(output_reg); -- next! 
 
     | 
  
  
     | 
    
       		end if;
 
     | 
  
  
     | 
    
       	end process;
 
     | 
  
  
     | 
    
       	
 
     | 
  
  
     | 
    
       	CLKOUT <= output_reg;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       end vhdl;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     |