OpenCores
URL https://opencores.org/ocsvn/a-z80/a-z80/trunk

Subversion Repositories a-z80

[/] [a-z80/] [trunk/] [host/] [zxspectrum_de1/] [ula/] [i2s_intf.vhd] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 gdevic
-- ZX Spectrum for Altera DE1
2
--
3
-- Copyright (c) 2009-2010 Mike Stirling
4
--
5
-- All rights reserved
6
--
7
-- Redistribution and use in source and synthezised forms, with or without
8
-- modification, are permitted provided that the following conditions are met:
9
--
10
-- * Redistributions of source code must retain the above copyright notice,
11
--   this list of conditions and the following disclaimer.
12
--
13
-- * Redistributions in synthesized form must reproduce the above copyright
14
--   notice, this list of conditions and the following disclaimer in the
15
--   documentation and/or other materials provided with the distribution.
16
--
17
-- * Neither the name of the author nor the names of other contributors may
18
--   be used to endorse or promote products derived from this software without
19
--   specific prior written permission.
20
--
21
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
25
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
-- POSSIBILITY OF SUCH DAMAGE.
32
--
33
 
34
library IEEE;
35
use IEEE.STD_LOGIC_1164.ALL;
36
use IEEE.STD_LOGIC_ARITH.ALL;
37
use IEEE.STD_LOGIC_UNSIGNED.ALL;
38
 
39
entity i2s_intf is
40
generic(
41
    mclk_rate : positive := 12000000;
42
    sample_rate : positive := 8000;
43
    preamble : positive := 1; -- I2S
44
    word_length : positive := 16
45
    );
46
 
47
port (
48
    -- 2x MCLK in (e.g. 24 MHz for WM8731 USB mode)
49
    CLK         :   in  std_logic;
50
    nRESET      :   in  std_logic;
51
 
52
    -- Parallel IO
53
    PCM_INL     :   out std_logic_vector(word_length - 1 downto 0);
54
    PCM_INR     :   out std_logic_vector(word_length - 1 downto 0);
55
    PCM_OUTL    :   in  std_logic_vector(word_length - 1 downto 0);
56
    PCM_OUTR    :   in  std_logic_vector(word_length - 1 downto 0);
57
 
58
    -- Codec interface (right justified mode)
59
    -- MCLK is generated at half of the CLK input
60
    I2S_MCLK    :   out std_logic;
61
    -- LRCLK is equal to the sample rate and is synchronous to
62
    -- MCLK.  It must be related to MCLK by the oversampling ratio
63
    -- given in the codec datasheet.
64
    I2S_LRCLK   :   out std_logic;
65
 
66
    -- Data is shifted out on the falling edge of BCLK, sampled
67
    -- on the rising edge.  The bit rate is determined such that
68
    -- it is fast enough to fit preamble + word_length bits into
69
    -- each LRCLK half cycle.  The last cycle of each word may be
70
    -- stretched to fit to LRCLK.  This is OK at least for the
71
    -- WM8731 codec.
72
    -- The first falling edge of each timeslot is always synchronised
73
    -- with the LRCLK edge.
74
    I2S_BCLK    :   out std_logic;
75
    -- Output bitstream
76
    I2S_DOUT    :   out std_logic;
77
    -- Input bitstream
78
    I2S_DIN     :   in  std_logic
79
    );
80
end i2s_intf;
81
 
82
architecture i2s_intf_arch of i2s_intf is
83
constant ratio_mclk_fs : positive := (mclk_rate / sample_rate);
84
constant lrdivider_top : positive := (ratio_mclk_fs / 2) - 1;
85
constant bdivider_top : positive := (ratio_mclk_fs / 8 / (preamble + word_length) * 2) - 1;
86
constant nbits : positive := preamble + word_length;
87
 
88
subtype lrdivider_t is integer range 0 to lrdivider_top;
89
subtype bdivider_t is integer range 0 to bdivider_top;
90
subtype bitcount_t is integer range 0 to nbits;
91
 
92
signal lrdivider : lrdivider_t;
93
signal bdivider : bdivider_t;
94
signal bitcount : bitcount_t;
95
 
96
signal mclk_r : std_logic;
97
signal lrclk_r : std_logic;
98
signal bclk_r : std_logic;
99
 
100
-- Shift register is long enough for the number of data bits
101
-- plus the preamble, plus an extra bit on the right to register
102
-- the incoming data
103
signal shiftreg : std_logic_vector(nbits downto 0);
104
begin
105
    I2S_MCLK <= mclk_r;
106
    I2S_LRCLK <= lrclk_r;
107
    I2S_BCLK <= bclk_r;
108
    I2S_DOUT <= shiftreg(nbits); -- data goes out MSb first
109
 
110
    process(nRESET,CLK)
111
    begin
112
        if nRESET = '0' then
113
            PCM_INL <= (others => '0');
114
            PCM_INR <= (others => '0');
115
 
116
            -- Preload down-counters for clock generation
117
            lrdivider <= lrdivider_top;
118
            bdivider <= bdivider_top;
119
            bitcount <= nbits;
120
 
121
            mclk_r <= '0';
122
            lrclk_r <= '0';
123
            bclk_r <= '0';
124
            shiftreg <= (others => '0');
125
        elsif rising_edge(CLK) then
126
            -- Generate MCLK at half input clock rate
127
            mclk_r <= not mclk_r;
128
 
129
            -- Generate LRCLK at rate specified by codec configuration
130
            if lrdivider = 0 then
131
                -- LRCLK divider has reached 0 - start again from the top
132
                lrdivider <= lrdivider_top;
133
 
134
                -- Generate LRCLK edge and sync the BCLK counter
135
                lrclk_r <= not lrclk_r;
136
                bclk_r <= '0';
137
                bitcount <= nbits; -- 1 extra required for setup
138
                bdivider <= bdivider_top;
139
 
140
                -- Load shift register with output data padding preamble
141
                -- with 0s.  Load output buses with input word from the
142
                -- previous timeslot.
143
                shiftreg(nbits downto nbits - preamble + 1) <= (others => '0');
144
                if lrclk_r = '0' then
145
                    -- Previous channel input is LEFT.  This is available in the
146
                    -- shift register at the end of a cycle, right justified
147
                    PCM_INL <= shiftreg(word_length - 1 downto 0);
148
                    -- Next channel to output is RIGHT.  Load this into the
149
                    -- shift register at the start of a cycle, left justified
150
                    shiftreg(word_length downto 1) <= PCM_OUTR;
151
                else
152
                    -- Previous channel input is RIGHT
153
                    PCM_INR <= shiftreg(word_length - 1 downto 0);
154
                    -- Next channel is LEFT
155
                    shiftreg(word_length downto 1) <= PCM_OUTL;
156
                end if;
157
            else
158
                -- Decrement the LRCLK counter
159
                lrdivider <= lrdivider - 1;
160
 
161
                -- Generate BCLK at a suitable rate to fit the required number
162
                -- of bits into each timeslot.  Data is changed on the falling edge,
163
                -- sampled on the rising edge
164
                if bdivider = 0 then
165
                    -- If all bits have been output for this phase then
166
                    -- stop and wait to sync back up with LRCLK
167
                    if bitcount > 0 then
168
                        -- Reset
169
                        bdivider <= bdivider_top;
170
 
171
                        -- Toggle BCLK
172
                        bclk_r <= not bclk_r;
173
                        if bclk_r = '0' then
174
                            -- Rising edge - shift in current bit and decrement bit counter
175
                            bitcount <= bitcount - 1;
176
                            shiftreg(0) <= I2S_DIN;
177
                        else
178
                            -- Falling edge - shift out next bit
179
                            shiftreg(nbits downto 1) <= shiftreg(nbits - 1 downto 0);
180
                        end if;
181
                    end if;
182
                else
183
                    -- Decrement the BCLK counter
184
                    bdivider <= bdivider - 1;
185
                end if;
186
            end if;
187
 
188
        end if;
189
    end process;
190
end i2s_intf_arch;
191
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.