Project

General

Profile

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


(34-34/79)