summaryrefslogtreecommitdiff
path: root/FPGA/vhdl/codec_dac.vhd
blob: 0cfd8586447ed3c83b09598bd830283c551d7068 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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'&reg_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;