OpenCores
URL https://opencores.org/ocsvn/i2s_to_parallel/i2s_to_parallel/trunk

Subversion Repositories i2s_to_parallel

[/] [i2s_to_parallel/] [trunk/] [i2s_to_parallel.vhd] - Blame information for rev 6

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

Line No. Rev Author Line
1 2 primiano
---------------------------------------------------------------------------------
2
-- Engineer:      Fabio Gravina <fabio.gravina@gmail.com>
3
--                                                       http://www.fgravina.net
4
--                Primiano Tucci <p.tucci@gmail.com>
5
--                                                  http://www.primianotucci.com
6
--
7
-- Create Date:   17:26:41 12/19/2008
8
-- Design Name:   i2s_to_parallel
9
--
10
-- Description:   
11
-- 
12
-- This module provides a bridge between an I2S serial device (audio ADC, S/PDIF 
13
-- Decoded data) and a parallel device (microcontroller, IP block).
14
--
15
-- It's coded as a generic VHDL entity, so developer can choose the proper signal
16
-- width (8/16/24 bit)
17
--
18
-- Input takes:
19
-- -I2S Bit Clock
20
-- -I2S LR Clock (Left/Right channel indication)
21
-- -I2S Data
22
--
23
-- Output provides:
24
-- -DATA_L / DATA_R parallel outputs
25
-- -STROBE and STROBE_LR output ready signals.
26
-- 
27
-- As soon as data is read from the serial I2S line, it's written on the proper
28
-- parallel output and a rising edge of the STROBE signal indicates that new
29
-- data is ready.
30
-- STROBE_LR signal tells if the strobe signal was relative to the
31
-- Left or Right channel.
32
--
33
--------------------------------------------------------------------------------
34
-- I2S Waveform summary
35
--
36
-- BIT_CK     __    __   __    __    __            __    __    __    __   
37
--           | 1|__| 2|_| 3|__| 4|__| 5|__... ... |32|__| 1|__| 2|__| 3| ...
38
--
39
-- LR_CK                                  ... ...      _________________
40
--           ____________R_Channel_Data______________|   L Channel Data ...
41
--
42
-- DATA      x< 00 ><D24><D22><D21><D20>  ... ...     < 00 ><D24><D23>  ...
43
--
44
--
45
-- Each time enough ('width' bits of) data is collected from the serial input
46
-- it is outputed on the corresponding DATA_R/L port and the proper
47
-- STROBE signals are emitted
48
-- A rising edge of the STROBE signal tells that parallel data is ready
49
-- STROBE_LR signal tells which of the DATA_L / DATA_R has been generated
50
-- DATA_L/R remain valid for the whole cycle (until next data is processed)
51
--------------------------------------------------------------------------------
52
library ieee;
53
use ieee.std_logic_1164.all;
54
 
55
entity i2s_to_parallel is
56
-- width: How many bits (from MSB) are gathered from the serial I2S input
57
generic(width : integer := 16);
58
port(
59
        --  I2S Input ports
60
        LR_CK : in std_logic;    --Left/Right indicator clock
61
        BIT_CK : in std_logic;   --Bit clock
62
        DIN : in std_logic;      --Data Input
63
        -- Control ports
64
        RESET : in std_logic;    --Asynchronous Reset (Active Low)
65
        -- Parallel Output ports
66
        DATA_L : out std_logic_vector(width-1 downto 0);
67
        DATA_R : out std_logic_vector(width-1 downto 0);
68
        -- Output status ports
69
        STROBE : out std_logic;  --Rising edge means data is ready
70
        STROBE_LR : out std_logic
71
);
72
end i2s_to_parallel;
73
 
74
architecture Behavioral of i2s_to_parallel  is
75
        signal current_lr : std_logic;
76
        signal counter : integer range 0 to width;
77
        signal shift_reg : std_logic_vector(width-1 downto 0);
78
        signal output_strobed : std_logic;
79
 
80
begin
81
        process(RESET, BIT_CK, LR_CK, DIN)
82
        begin
83
                if(RESET = '0') then
84
                        DATA_L <= (others => '0');
85
                        DATA_R <= (others => '0');
86
                        shift_reg <= (others => '0');
87
                        current_lr <= '0';
88
                        STROBE_LR <= '0';
89
                        STROBE <= '0';
90
                        counter <= width;
91
                        output_strobed <= '0';
92
                elsif rising_edge(BIT_CK) then
93
                        -- Note: LRCK changes on the falling edge of BCK
94
                        -- We notice of the first LRCK transition only on the
95
                        -- next rising edge of BCK
96
                        -- In this way we discard the first data bit as we start pushing
97
                        -- data into the shift register only on the next BCK rising edge
98
                        -- This is right for I2S standard (data starts on the 2nd clock)
99
                        if(LR_CK /= current_lr) then
100
                                current_lr <= LR_CK;
101
                                counter <= width;
102
                                --clear the shift register
103
                                shift_reg <= (others => '0');
104
                                STROBE <= '0';
105
                                output_strobed <= '0';
106
                        elsif(counter > 0) then
107
                                -- Push data into the shift register
108
                                shift_reg <= shift_reg(width-2 downto 0) & DIN;
109
                                -- Decrement counter
110
                                counter <= counter - 1;
111
                        elsif(counter = 0) then
112
                                --TODO Optimization
113
                                -- Data could be written one clock behind
114
                                -- when counter = 1 (step down counter)
115
                                -- We're wasting a cycle here
116
                                if(output_strobed = '0') then
117
                                        if(current_lr = '1') then
118
                                                --Output Right Channel
119
                                                DATA_R <= shift_reg;
120
                                        else
121
                                                --Output Left Channel                                   
122
                                                DATA_L <= shift_reg;
123
                                        end if;
124
                                        STROBE_LR <= current_lr;
125
                                        output_strobed <= '1';
126
                                else
127
                                        STROBE <= '1';
128
                                end if; --(output_strobed = '0')
129
                        end if; -- (counter = 0)
130
 
131
                end if; -- reset / rising_edge
132
 
133
        end process;
134
 
135
end Behavioral;

powered by: WebSVN 2.1.0

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