Recover clock.vhd

From Hamsterworks Wiki!

Jump to: navigation, search

Looks at the flips in the input stream and decides when to clock bits into the shift register for S/PDIF capture. Used for the SPDIF_Thru FPGA project.

----------------------------------------------------------------------------------
-- Engineer: Mike Field (hasmter@snap.net.nz)
-- 
-- Create Date:    20:04:52 09/06/2011 
-- Module Name:    cllock_recovery - Behavioral 
--
-- Description: Looks for the shortest time between transistions, and then generates
--              the "sampleNow" pulse at 0.5t, 1.5t and 2.5t.
--
--              If a transistion does not occur in 4t then it starts again.
--
--              255 transistions in the expected range are required before sampleNow
--              is sent out.
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity clock_recovery is
    Port ( clock100   : in  STD_LOGIC;
           transition : in  STD_LOGIC;
           sampleNow  : out STD_LOGIC);
end clock_recovery;

architecture Behavioral of clock_recovery is
   type reg is record
      pulseLen      : std_logic_vector(6 downto 0);
      minPulse    : std_logic_vector(6 downto 0);
      validCount  : std_logic_vector(6 downto 0);
      pulse1pt5   : std_logic_vector(7 downto 0);
      pulse2pt5   : std_logic_vector(8 downto 0);
      valid       : std_logic;
      sampleNow   : std_logic;
   end record;
   
   signal r : reg := ((others => '0'),(others => '0'),(others => '0'),(others => '0'),(others => '0'),'0','0');
   signal n : reg;

begin
   sampleNow <= r.sampleNow;
   process(r, transition)
   begin
      n <= r;

      n.pulse1pt5 <=( "00"&r.minPulse(6 downto 1)) + r.minPulse;
      n.pulse2pt5 <=( "00"&r.minPulse(6 downto 1)) + ("0"&r.minPulse&"0");
      
      -- Output the recovered sample clock
      n.sampleNow <= '0';
      -- is it time to sample (0.5 pulse)?
      if r.pulseLen = "0"&r.minPulse(6 downto 1) then
         n.sampleNow <= r.valid;
      end if;

      -- is it time to sample (1.5 pulse)?
      if ("0" & r.pulseLen) =  r.pulse1pt5 then
         n.sampleNow <= r.valid;
      end if;

      -- is it time to sample (2.5 pulse)?
      if ("0" & r.pulseLen) = r.pulse2pt5 then
         n.sampleNow <= r.valid;
      end if;
      
      if transition = '1' then
         -- start timing the pulse and check if we have a new minimum.
         n.pulseLen <= (others => '0');
         if r.pulseLen < r.minPulse then
            -- If this is the shortest pulse so far then we need to remove the valid bit
            n.minPulse <= r.pulseLen;
            n.validCount <= (others => '0');
            n.valid <= '0';
         else
            -- We need 255 valid pulses before we declare that the recovered clock is valid
            if r.validCount = "1111111" then
               n.valid <= '1';
            else
               n.validCount <= r.validCount + 1;
               n.valid <= '0';
            end if;
         end if;
      else
         -- If the pulse is 2.55us long it's invalid
         if r.pulseLen = "1111111" then
              n.pulseLen   <= r.pulseLen;            
            n.validCount <= (others => '0');
            n.valid        <= '0';
         else
              n.pulseLen <= r.pulseLen + 1;
         end if;
         
         -- If the pulse is longer than 4x the minimum pulse length it's invalid
         if r.pulseLen > (r.minPulse & "00") then
            n.minPulse   <= r.pulseLen;
            n.validCount <= (others => '0');
            n.valid      <= '0';
         end if;
      end if;
   end process;
   
   process(r, clock100)
   begin
      if rising_edge(clock100) then
         r <= n;
      end if;
   end process;

end Behavioral;

Personal tools