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

Subversion Repositories i2s_interface

[/] [i2s_interface/] [trunk/] [rtl/] [vhdl/] [i2s_codec.vhd] - Blame information for rev 7

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

Line No. Rev Author Line
1 7 gedra
----------------------------------------------------------------------
2
----                                                              ----
3
---- WISHBONE I2S Interface IP Core                               ----
4
----                                                              ----
5
---- This file is part of the I2S Interface project               ----
6
---- http://www.opencores.org/cores/i2s_interface/                ----
7
----                                                              ----
8
---- Description                                                  ----
9
---- I2S encoder/decoder.                                         ----
10
----                                                              ----
11
----                                                              ----
12
---- To Do:                                                       ----
13
---- -                                                            ----
14
----                                                              ----
15
---- Author(s):                                                   ----
16
---- - Geir Drange, gedra@opencores.org                           ----
17
----                                                              ----
18
----------------------------------------------------------------------
19
----                                                              ----
20
---- Copyright (C) 2004 Authors and OPENCORES.ORG                 ----
21
----                                                              ----
22
---- This source file may be used and distributed without         ----
23
---- restriction provided that this copyright statement is not    ----
24
---- removed from the file and that any derivative work contains  ----
25
---- the original copyright notice and the associated disclaimer. ----
26
----                                                              ----
27
---- This source file is free software; you can redistribute it   ----
28
---- and/or modify it under the terms of the GNU General          ----
29
---- Public License as published by the Free Software Foundation; ----
30
---- either version 2.0 of the License, or (at your option) any   ----
31
---- later version.                                               ----
32
----                                                              ----
33
---- This source is distributed in the hope that it will be       ----
34
---- useful, but WITHOUT ANY WARRANTY; without even the implied   ----
35
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ----
36
---- PURPOSE. See the GNU General Public License for more details.----                                          
37
----                                                              ----
38
---- You should have received a copy of the GNU General           ----
39
---- Public License along with this source; if not, download it   ----
40
---- from http://www.gnu.org/licenses/gpl.txt                     ----
41
----                                                              ----
42
----------------------------------------------------------------------
43
--
44
-- CVS Revision History
45
--
46
-- $Log: not supported by cvs2svn $
47
--
48
--
49
 
50
library ieee;
51
use ieee.std_logic_1164.all;
52
use ieee.numeric_std.all;
53
 
54
entity i2s_codec is
55
  generic (DATA_WIDTH: integer;
56
           ADDR_WIDTH: integer;
57
           IS_MASTER: integer range 0 to 1;
58
           IS_RECEIVER: integer range 0 to 1);
59
  port (
60
    wb_clk_i: in std_logic;             -- wishbone clock
61
    conf_res: in std_logic_vector(5 downto 0);  -- sample resolution
62
    conf_ratio: in std_logic_vector(7 downto 0); -- clock divider ratio
63
    conf_swap: in std_logic;            -- left/right sample order
64
    conf_inten: in std_logic;           -- interrupt enable
65
    conf_en: in std_logic;              -- transmitter/recevier enable
66
    i2s_sd_i: in std_logic;             -- I2S serial data input
67
    i2s_sck_i: in std_logic;            -- I2S clock input
68
    i2s_ws_i: in std_logic;             -- I2S word select input
69
    sample_dat_i: in std_logic_vector(DATA_WIDTH - 1 downto 0);  -- audio data
70
    sample_dat_o: out std_logic_vector(DATA_WIDTH - 1 downto 0);  -- audio data
71
    mem_rdwr: out std_logic;            -- sample buffer read/write
72
    sample_addr: out std_logic_vector(ADDR_WIDTH - 2 downto 0);  -- address
73
    evt_hsbf: out std_logic;            -- higher sample buf empty event
74
    evt_lsbf: out std_logic;            -- lower sample buf empty event
75
    i2s_sd_o: out std_logic;            -- I2S serial data output
76
    i2s_sck_o: out std_logic;           -- I2S clock output
77
    i2s_ws_o: out std_logic);           -- I2S word select output
78
end i2s_codec;
79
 
80
architecture rtl of i2s_codec is
81
 
82
  signal i2s_clk_en, zsck, zzsck, zzzsck, imem_rd : std_logic;
83
  signal clk_cnt : integer range 0 to 255;
84
  signal adr_cnt : integer range 0 to 2**(ADDR_WIDTH - 1) - 1;
85
  type srx_states is (IDLE, WAIT_CLK, TRX_DATA, RX_WRITE, SYNC);
86
  signal sd_ctrl : srx_states;
87
  signal bit_cnt, bits_to_trx : integer range 0 to 63;
88
  signal toggle, master, neg_edge, ws_pos_edge, ws_neg_edge : std_logic;
89
  signal data_in : std_logic_vector(DATA_WIDTH - 1 downto 0);
90
  signal zws, zzws, zzzws, i2s_ws, new_word, last_bit: std_logic;
91
  signal imem_rdwr, receiver : std_logic;
92
  signal ws_cnt : integer range 0 to 31;
93
 
94
begin
95
 
96
-- Create signals that reflect generics
97
  SGM: if IS_MASTER = 1 generate
98
    master <= '1';
99
  end generate SGM;
100
  SGS: if IS_MASTER = 0 generate
101
    master <= '0';
102
  end generate SGS;
103
  SGRX: if IS_RECEIVER = 1 generate
104
    receiver <= '1';
105
  end generate SGRX;
106
  SGTX: if IS_RECEIVER = 0 generate
107
    receiver <= '0';
108
  end generate SGTX;
109
 
110
-- I2S clock enable generation, master mode. The clock is a fraction of the
111
-- Wishbone bus clock, determined by the conf_ratio value.
112
  CGM: if IS_MASTER = 1 generate
113
    CGEN: process (wb_clk_i)
114
    begin
115
      if rising_edge(wb_clk_i) then
116
        if conf_en = '0' then           -- disabled
117
          i2s_clk_en <= '0';
118
          clk_cnt <= 0;
119
          neg_edge <= '0';
120
          toggle <= '0';
121
        else                              -- enabled
122
          if clk_cnt < to_integer(unsigned(conf_ratio)) + 1 then
123
            clk_cnt <= (clk_cnt + 1) mod 256;
124
            i2s_clk_en <= '0';
125
          else
126
            clk_cnt <= 0;
127
            i2s_clk_en <= '1';
128
            neg_edge <= not neg_edge;
129
          end if;
130
          toggle <= neg_edge;
131
        end if;
132
      end if;
133
    end process CGEN;
134
  end generate CGM;
135
 
136
-- I2S clock enable generation, slave mode. The input clock signal is sampeled
137
-- and the negative edge is located.
138
  CGS: if IS_MASTER = 0 generate
139
    CGEN: process (wb_clk_i)
140
    begin
141
      if rising_edge(wb_clk_i) then
142
        if conf_en = '0' then           -- disabled
143
          i2s_clk_en <= '0';
144
          zsck <= '0';
145
          zzsck <= '0';
146
          zzzsck <= '0';
147
          toggle <= '0';
148
          neg_edge <= '0';
149
        else                            -- enabled
150
          -- synchronize input clock to Wishbone clock domaine
151
          zsck <= i2s_sck_i;
152
          zzsck <= zsck;
153
          zzzsck <= zzsck;
154
          -- look for edges
155
          if zzzsck = '1' and zzsck = '0' then
156
            i2s_clk_en <= '1';
157
            neg_edge <= '1';
158
          elsif zzzsck = '0' and zzsck = '1' then
159
            i2s_clk_en <= '1';
160
            neg_edge <= '0';
161
          else
162
            i2s_clk_en <= '0';
163
          end if;
164
          toggle <= neg_edge;
165
        end if;
166
      end if;
167
    end process CGEN;
168
  end generate CGS;
169
 
170
-- Process to generate word select signal, master mode
171
  WSM: if IS_MASTER = 1 generate
172
    i2s_ws_o <= i2s_ws;
173
    WSG: process (wb_clk_i)
174
    begin
175
      if rising_edge(wb_clk_i) then
176
        if conf_en = '0' then
177
          i2s_ws <= '0';
178
          ws_cnt <= 0;
179
          ws_pos_edge <= '0';
180
          ws_neg_edge <= '0';
181
        else
182
          if i2s_clk_en = '1' and toggle = '1' then
183
            if ws_cnt < bits_to_trx then
184
              ws_cnt <= ws_cnt + 1;
185
            else
186
              i2s_ws <= not i2s_ws;
187
              ws_cnt <= 0;
188
              if i2s_ws = '1' then
189
                ws_neg_edge <= '1';
190
              else
191
                ws_pos_edge <= '1';
192
              end if;
193
            end if;
194
          else
195
            ws_pos_edge <= '0';
196
            ws_neg_edge <= '0';
197
          end if;
198
        end if;
199
      end if;
200
    end process WSG;
201
  end generate WSM;
202
 
203
-- Process to detect word select edges, slave mode
204
  WSD: if IS_MASTER = 0 generate
205
    i2s_ws <= i2s_ws_i;
206
    WSDET: process (wb_clk_i)
207
    begin
208
      if rising_edge(wb_clk_i) then
209
        if conf_en = '0' then
210
          ws_pos_edge <= '0';
211
          ws_neg_edge <= '0';
212
          zws <= i2s_ws;
213
          zzws <= i2s_ws;
214
          zzzws <= i2s_ws;
215
        else
216
          -- sync i2s_ws_io to our clock domaine
217
          zws <= i2s_ws;
218
          zzws <= zws;
219
          zzzws <= zzws;
220
          -- detect negative edge
221
          if zzzws = '1' and zzws = '0' then
222
            ws_neg_edge <= '1';
223
          else
224
            ws_neg_edge <= '0';
225
          end if;
226
          -- detect positive edge
227
          if zzzws = '0' and zzws = '1' then
228
            ws_pos_edge <= '1';
229
          else
230
            ws_pos_edge <= '0';
231
          end if;
232
        end if;
233
      end if;
234
    end process WSDET;
235
  end generate WSD;
236
 
237
-- Logic to generate clock signal, master mode
238
  SCKM: if IS_MASTER = 1 generate
239
    i2s_sck_o <= toggle;
240
  end generate SCKM;
241
 
242
-- Process to receive data on i2s_sd_i, or transmit data on i2s_sd_o
243
  sample_addr <= std_logic_vector(to_unsigned(adr_cnt, ADDR_WIDTH - 1));
244
  mem_rdwr <= imem_rdwr;
245
  sample_dat_o <= data_in;
246
 
247
  SDRX: process (wb_clk_i)
248
  begin
249
    if rising_edge(wb_clk_i) then
250
      if conf_en = '0' then           -- codec disabled
251
        imem_rdwr <= '0';
252
        sd_ctrl <= IDLE;
253
        data_in <= (others => '0');
254
        bit_cnt <= 0;
255
        bits_to_trx <= 0;
256
        new_word <= '0';
257
        last_bit <= '0';
258
        adr_cnt <= 0;
259
        evt_lsbf <= '0';
260
        evt_hsbf <= '0';
261
        i2s_sd_o <= '0';
262
      else
263
        case sd_ctrl is
264
          when IDLE =>
265
            imem_rdwr <= '0';
266
            if to_integer(unsigned(conf_res)) > 15 and
267
              to_integer(unsigned(conf_res)) < 33 then
268
              bits_to_trx <= to_integer(unsigned(conf_res)) - 1;
269
            else
270
              bits_to_trx <= 15;
271
            end if;
272
            if conf_en = '1' then
273
              if (ws_pos_edge = '1' and conf_swap = '1') or
274
                (ws_neg_edge = '1' and conf_swap = '0') then
275
                if receiver = '1' then    -- recevier
276
                  sd_ctrl <= WAIT_CLK;
277
                else
278
                  imem_rdwr <= '1';       -- read first data if transmitter
279
                  sd_ctrl <= TRX_DATA;
280
                end if;
281
              end if;
282
            end if;
283
          when WAIT_CLK =>              -- wait for first bit after WS
284
            adr_cnt <= 0;
285
            bit_cnt <= 0;
286
            new_word <= '0';
287
            last_bit <= '0';
288
            data_in <= (others => '0');
289
            if i2s_clk_en = '1' and neg_edge = '0' then
290
              sd_ctrl <= TRX_DATA;
291
            end if;
292
          when TRX_DATA =>              -- transmit/receive serial data 
293
            imem_rdwr <= '0';
294
            evt_hsbf <= '0';
295
            evt_lsbf <= '0';
296
            if master = '0' then
297
              if zzzws /= zzws then
298
                new_word <= '1';
299
              end if;
300
            else
301
              if ws_pos_edge = '1' or ws_neg_edge = '1' then
302
                new_word <= '1';
303
              end if;
304
            end if;
305
            if new_word = '1' and i2s_clk_en = '1' and neg_edge = '0' then
306
              last_bit <= '1';
307
            end if;
308
            -- recevier operation
309
            if receiver = '1' then
310
              if i2s_clk_en = '1' and neg_edge = '1' then
311
                if master = '1' then    -- master mode
312
                  if bit_cnt < bits_to_trx and new_word = '0' then
313
                    bit_cnt <= bit_cnt + 1;
314
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
315
                  else
316
                    imem_rdwr <= '1';
317
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
318
                    sd_ctrl <= RX_WRITE;
319
                  end if;
320
                else                    -- slave mode
321
                  if bit_cnt <= bits_to_trx and new_word = '0' then
322
                    bit_cnt <= bit_cnt + 1;
323
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
324
                  else
325
                    imem_rdwr <= '1';
326
                    sd_ctrl <= RX_WRITE;
327
                  end if;
328
                end if;
329
              end if;
330
            end if;
331
            -- transmitter operation
332
            if receiver = '0' then
333
              if master = '1' then      -- master mode
334
                if i2s_clk_en = '1' and neg_edge = '0' then
335
                  if bit_cnt < bits_to_trx and new_word = '0' then
336
                    bit_cnt <= bit_cnt + 1;
337
                    i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
338
                  else
339
                    bit_cnt <= bit_cnt + 1;
340
                    if bit_cnt > bits_to_trx then
341
                      i2s_sd_o <= '0';
342
                    end if;
343
                    -- transmitter address counter
344
                    imem_rdwr <= '1';
345
                    adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
346
                    if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
347
                      evt_lsbf <= '1';
348
                    else
349
                      evt_lsbf <= '0';
350
                    end if;
351
                    if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
352
                      evt_hsbf <= '1';
353
                    else
354
                      evt_hsbf <= '0';
355
                    end if;
356
                    sd_ctrl <= SYNC;
357
                  end if;
358
                end if;
359
              else                     -- slave mode
360
                if i2s_clk_en = '1' and neg_edge = '1' then
361
                  if bit_cnt < bits_to_trx and new_word = '0' then
362
                    bit_cnt <= bit_cnt + 1;
363
                    i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
364
                  else
365
                    bit_cnt <= bit_cnt + 1;
366
                    if bit_cnt > bits_to_trx then
367
                      i2s_sd_o <= '0';
368
                    else
369
                      i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
370
                    end if;
371
                    if new_word = '1' then  -- transmitter address counter
372
                      imem_rdwr <= '1';
373
                      adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
374
                      if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
375
                        evt_lsbf <= '1';
376
                      else
377
                        evt_lsbf <= '0';
378
                      end if;
379
                      if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
380
                        evt_hsbf <= '1';
381
                      else
382
                        evt_hsbf <= '0';
383
                      end if;
384
                      sd_ctrl <= SYNC;
385
                    end if;
386
                  end if;
387
                end if;
388
              end if;
389
            end if;
390
          when RX_WRITE =>             -- write received word to sample buffer
391
            imem_rdwr <= '0';
392
            adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
393
            if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
394
              evt_lsbf <= '1';
395
            else
396
              evt_lsbf <= '0';
397
            end if;
398
            if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
399
              evt_hsbf <= '1';
400
            else
401
              evt_hsbf <= '0';
402
            end if;
403
            sd_ctrl <= SYNC;
404
          when SYNC =>                  -- synchronise with next word
405
            imem_rdwr <= '0';
406
            evt_hsbf <= '0';
407
            evt_lsbf <= '0';
408
            bit_cnt <= 0;
409
            if ws_pos_edge = '1' or ws_neg_edge = '1' then
410
              new_word <= '1';
411
            end if;
412
            if new_word = '1' and i2s_clk_en = '1' and neg_edge = '0' then
413
              last_bit <= '1';
414
            end if;
415
            if receiver = '1' then      -- receive mode
416
              if master = '1' then
417
                new_word <= '0';
418
                last_bit <= '0';
419
                data_in <= (others => '0');
420
                sd_ctrl <= TRX_DATA;
421
              else
422
                if i2s_clk_en = '1' and neg_edge = '0' and new_word = '1' then
423
                  new_word <= '0';
424
                  last_bit <= '0';
425
                  data_in <= (others => '0');
426
                  sd_ctrl <= TRX_DATA;
427
                end if;
428
              end if;
429
            else                        -- transmit mode
430
              if master = '1' then
431
                new_word <= '0';
432
                last_bit <= '0';
433
                data_in <= (others => '0');
434
                sd_ctrl <= TRX_DATA;
435
              elsif i2s_clk_en = '1' and neg_edge = '0' then
436
                new_word <= '0';
437
                last_bit <= '0';
438
                data_in <= (others => '0');
439
                sd_ctrl <= TRX_DATA;
440
              end if;
441
            end if;
442
          when others => null;
443
        end case;
444
      end if;
445
    end if;
446
  end process SDRX;
447
 
448
end rtl;

powered by: WebSVN 2.1.0

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