Gen bit clock.vhd

From Hamsterworks Wiki!

Jump to: navigation, search

This is the magic bit of the SPDIF_Thru FPGA project.

A 20 bit value is added to a total, and when a carry occurs ce_out is asserted.

The constant is 00001110011xxxxxxxxx, where "xxxxxxxxx" is a nine bit trim value that can be altered in response to the adj_* signals to trim the rate at which bits are generated.

Clocked at 100MHz, carry is generated every 1048576/58880 to 1048576/59391 clock cycles, or 178.1ns to 176.5ns, or 5,614,823Hz to 5,665,722Hz, allowing it to match sample rates of 43,865Hz through 44,263Hz.

----------------------------------------------------------------------------------
-- Engineer: Mike Field (hamster@snap.net.nz)
-- 
-- Create Date:    17:02:59 09/04/2011 
-- Module Name:    fractional_clock - Behavioral 
--
-- Description:  Generates a pulse at around 44100*64Hz.
--               There are four trim signals that allow the speed to be
--               adjusted within a few % in steps of about 1/(2^20)th of a second 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity fractional_clock is
    Port ( clock100 : in  STD_LOGIC;
           ce_out : out  STD_LOGIC;
           adj_quicker_lots : in  STD_LOGIC;
           adj_quicker : in  STD_LOGIC;
           adj_slower : in  STD_LOGIC;
           adj_slower_lots : in  STD_LOGIC);
end fractional_clock;

architecture Behavioral of fractional_clock is
   type reg is record
      trim     : std_logic_vector(8 downto 0);
      ce_out    : std_logic;
      total    : std_logic_vector(19 downto 0);
   end record;
   signal r : reg := ("100000000", '0', (others => '0'));
   signal n : reg;
   signal nextsum : std_logic_vector(20 downto 0);
   constant wrap : natural := 35;
begin
   ce_out <= r.ce_out;
   nextsum <= ('0'&r.total) + ("00001110011"&r.trim);
   
   process(r, nextsum, adj_quicker_lots, adj_quicker, adj_slower, adj_slower_lots)
   begin
      n          <= r;
      n.total   <= nextsum(19 downto 0);
      n.ce_out <= nextsum(20);
      
      -- Process any trimming singal that may have arrived
      if adj_quicker_lots = '1' then
         if r.trim > 503 then
            n.trim <= (others => '1');
         else
            n.trim <= r.trim + 8;
         end if;
      elsif adj_quicker = '1' then
         if r.trim < 511 then
            n.trim <= r.trim + 1;
         end if;
      elsif adj_slower = '1' then
         if r.trim > 0  then
            n.trim <= r.trim - 1;
         end if;
      elsif adj_slower_lots = '1' then
         if r.trim < 8 then
            n.trim <= (others => '0');
         else
            n.trim <= r.trim - 8;
         end if;
      else
         n.trim <= r.trim;
      end if;
   end process;

   process(n, clock100)
   begin
      if rising_edge(clock100) then
         r <= n;
      end if;
   end process;
end Behavioral;

Personal tools