library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity codec_dac is generic ( system_frequency : real := 50.0E6; -- 50 MHz sample_rate : real := 48.0E3; -- 48 kHz data_width : positive := 16; -- 16 bits channel_num : positive := 2 -- dual channel ); port ( clk : in std_logic; -- resetn : in std_logic; -- go : in std_logic; data_in : in std_logic_vector(data_width-1 downto 0); -- codec tempo_dac : out std_logic; end_dac : out std_logic; codec_dac_bclk : out std_logic; -- B4 codec_dac_data : out std_logic; -- A4 codec_dac_lrck : out std_logic -- C6 ); end entity; architecture rtl of codec_dac is constant mod_bclk : positive := integer(system_frequency/(2.0*sample_rate*real(data_width)*real(channel_num))); constant mod_lrck : positive := data_width*channel_num/2; type state is (wait_for_go, tx); signal current_state : state; signal next_state : state; signal ctr_bclk : natural range 0 to mod_bclk-1; signal ctr_lrck : natural range 0 to mod_lrck-1; signal reg_data : std_logic_vector(data_in'range); signal cmd_data : std_logic_vector(1 downto 0); signal bclk : std_logic; signal lrck : std_logic; signal end_bit : std_logic; begin codec_dac_bclk <= bclk; codec_dac_lrck <= lrck; codec_dac_data <= reg_data(reg_data'low); tempo_dac <= end_bit; end_bit <= '0' when (ctr_bclk< mod_bclk-1) or bclk='0' else '1'; -- registers and counters process(clk, resetn) is begin if resetn ='0' then bclk <= '0'; lrck <= '0'; reg_data <= (others => '0'); ctr_bclk <= 0; ctr_lrck <= 0; current_state <= wait_for_go; elsif rising_edge(clk) then current_state <= next_state; if ctr_bclk< mod_bclk-1 then ctr_bclk <= ctr_bclk+1; else ctr_bclk <= 0; bclk <=not bclk; end if; -- data register case cmd_data is when "10" => reg_data <= data_in; when "11" => reg_data <= '0'®_data(reg_data'high downto 1); when others => null; end case; if end_bit = '1' then if ctr_lrck < mod_lrck-1 then ctr_lrck <= ctr_lrck +1; else ctr_lrck <= 0; lrck <= not lrck; end if; end if; end if; end process; process(current_state,go,end_bit, ctr_lrck) is begin next_state <= current_state; cmd_data <= "00"; end_dac <= '1'; case current_state is when wait_for_go => if go = '1' then next_state <= tx; cmd_data <= "10"; end if; when tx => if end_bit='1' then if ctr_lrck >= mod_lrck-1 then if go ='0' then next_state <= wait_for_go; else cmd_data <= "10"; end if; else cmd_data <= "11"; end if; end if; end_dac <= '0'; end case; end process; end architecture;