repo2/atari_chips/sally/phi_mult.vhdl
714 | markw | ---------------------------------------------------------------------------
|
|
-- (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;
|
|||
716 | markw | ||
signal flip : std_logic;
|
|||
714 | markw | 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
|
|||
);
|
|||
716 | markw | process(phi2_reg, phi2_sync,measure_reg,target_reg,counter_reg)
|
|
714 | markw | 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);
|
|||
716 | markw | flip <= '0';
|
|
714 | markw | ||
if (phi2_sync = '1' and phi2_reg = '0') then
|
|||
measure_next <= "000000";
|
|||
-- *21/128 to get 1/6
|
|||
716 | markw | -- 10101 is 20...
|
|
714 | markw | 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;
|
|||
716 | markw | ||
if (counter_reg=target_reg) then
|
|||
counter_next <= (others=>'0');
|
|||
flip <= '1';
|
|||
end if;
|
|||
714 | markw | end process;
|
|
716 | markw | process(phi2_reg, phi2_sync, flip, output_reg)
|
|
714 | markw | 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;
|
|||
716 | markw | if (flip='1') then
|
|
714 | markw | output_next <= not(output_reg); -- next!
|
|
end if;
|
|||
end process;
|
|||
CLKOUT <= output_reg;
|
|||
end vhdl;
|
|||