-- https://ackspace.nl/wiki/SP/DIF_transmitter_project -- (c) Danny Witberg library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity spdif_transmitter is port( bit_clock : in std_logic; -- 128x Fsample (6.144MHz for 48K samplerate) data_in : in std_logic_vector(23 downto 0); address_out : out std_logic := '0'; -- 1 address bit means stereo only spdif_out : out std_logic ); end entity spdif_transmitter; architecture behavioral of spdif_transmitter is signal data_in_buffer : std_logic_vector(23 downto 0); signal bit_counter : std_logic_vector(5 downto 0) := (others => '0'); signal frame_counter : std_logic_vector(8 downto 0) := (others => '0'); signal data_biphase : std_logic := '0'; signal data_out_buffer : std_logic_vector(7 downto 0); signal parity : std_logic; signal channel_status_shift : std_logic_vector(23 downto 0); signal channel_status : std_logic_vector(23 downto 0) := "001000000000000001000000"; begin bit_clock_counter : process (bit_clock) begin if bit_clock'event and bit_clock = '1' then bit_counter <= bit_counter + 1; end if; end process bit_clock_counter; data_latch : process (bit_clock) begin if bit_clock'event and bit_clock = '1' then parity <= data_in_buffer(23) xor data_in_buffer(22) xor data_in_buffer(21) xor data_in_buffer(20) xor data_in_buffer(19) xor data_in_buffer(18) xor data_in_buffer(17) xor data_in_buffer(16) xor data_in_buffer(15) xor data_in_buffer(14) xor data_in_buffer(13) xor data_in_buffer(12) xor data_in_buffer(11) xor data_in_buffer(10) xor data_in_buffer(9) xor data_in_buffer(8) xor data_in_buffer(7) xor data_in_buffer(6) xor data_in_buffer(5) xor data_in_buffer(4) xor data_in_buffer(3) xor data_in_buffer(2) xor data_in_buffer(1) xor data_in_buffer(0) xor channel_status_shift(23); if bit_counter = "000011" then data_in_buffer <= data_in; end if; if bit_counter = "111111" then if frame_counter = "101111111" then frame_counter <= (others => '0'); else frame_counter <= frame_counter + 1; end if; end if; end if; end process data_latch; data_output : process (bit_clock) begin if bit_clock'event and bit_clock = '1' then if bit_counter = "111111" then if frame_counter = "101111111" then -- next frame is 0, load preamble Z address_out <= '0'; channel_status_shift <= channel_status; data_out_buffer <= "10011100"; else if frame_counter(0) = '1' then -- next frame is even, load preamble X channel_status_shift <= channel_status_shift(22 downto 0) & '0'; data_out_buffer <= "10010011"; address_out <= '0'; else -- next frame is odd, load preable Y data_out_buffer <= "10010110"; address_out <= '1'; end if; end if; else if bit_counter(2 downto 0) = "111" then -- load new part of data into buffer case bit_counter(5 downto 3) is when "000" => data_out_buffer <= '1' & data_in_buffer(0) & '1' & data_in_buffer(1) & '1' & data_in_buffer(2) & '1' & data_in_buffer(3); when "001" => data_out_buffer <= '1' & data_in_buffer(4) & '1' & data_in_buffer(5) & '1' & data_in_buffer(6) & '1' & data_in_buffer(7); when "010" => data_out_buffer <= '1' & data_in_buffer(8) & '1' & data_in_buffer(9) & '1' & data_in_buffer(10) & '1' & data_in_buffer(11); when "011" => data_out_buffer <= '1' & data_in_buffer(12) & '1' & data_in_buffer(13) & '1' & data_in_buffer(14) & '1' & data_in_buffer(15); when "100" => data_out_buffer <= '1' & data_in_buffer(16) & '1' & data_in_buffer(17) & '1' & data_in_buffer(18) & '1' & data_in_buffer(19); when "101" => data_out_buffer <= '1' & data_in_buffer(20) & '1' & data_in_buffer(21) & '1' & data_in_buffer(22) & '1' & data_in_buffer(23); when "110" => data_out_buffer <= "10101" & channel_status_shift(23) & "1" & parity; when others => end case; else data_out_buffer <= data_out_buffer(6 downto 0) & '0'; end if; end if; end if; end process data_output; biphaser : process (bit_clock) begin if bit_clock'event and bit_clock = '1' then if data_out_buffer(data_out_buffer'left) = '1' then data_biphase <= not data_biphase; end if; end if; end process biphaser; spdif_out <= data_biphase; end behavioral;