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 23

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 17 gedra
---- PURPOSE. See the GNU General Public License for more details.----
37 7 gedra
----                                                              ----
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 23 gedra
-- Revision 1.2  2004/08/06 18:55:05  gedra
48
-- Removed conf_inten, and fixed bug in transmitter master mode.
49
--
50 17 gedra
-- Revision 1.1  2004/08/03 18:49:43  gedra
51
-- I2S encoder/decoder.
52 7 gedra
--
53
--
54 17 gedra
--
55 7 gedra
 
56
library ieee;
57
use ieee.std_logic_1164.all;
58
use ieee.numeric_std.all;
59
 
60
entity i2s_codec is
61
  generic (DATA_WIDTH: integer;
62
           ADDR_WIDTH: integer;
63
           IS_MASTER: integer range 0 to 1;
64
           IS_RECEIVER: integer range 0 to 1);
65
  port (
66
    wb_clk_i: in std_logic;             -- wishbone clock
67
    conf_res: in std_logic_vector(5 downto 0);  -- sample resolution
68
    conf_ratio: in std_logic_vector(7 downto 0); -- clock divider ratio
69
    conf_swap: in std_logic;            -- left/right sample order
70
    conf_en: in std_logic;              -- transmitter/recevier enable
71
    i2s_sd_i: in std_logic;             -- I2S serial data input
72
    i2s_sck_i: in std_logic;            -- I2S clock input
73
    i2s_ws_i: in std_logic;             -- I2S word select input
74
    sample_dat_i: in std_logic_vector(DATA_WIDTH - 1 downto 0);  -- audio data
75
    sample_dat_o: out std_logic_vector(DATA_WIDTH - 1 downto 0);  -- audio data
76
    mem_rdwr: out std_logic;            -- sample buffer read/write
77
    sample_addr: out std_logic_vector(ADDR_WIDTH - 2 downto 0);  -- address
78
    evt_hsbf: out std_logic;            -- higher sample buf empty event
79
    evt_lsbf: out std_logic;            -- lower sample buf empty event
80
    i2s_sd_o: out std_logic;            -- I2S serial data output
81
    i2s_sck_o: out std_logic;           -- I2S clock output
82
    i2s_ws_o: out std_logic);           -- I2S word select output
83
end i2s_codec;
84
 
85
architecture rtl of i2s_codec is
86
 
87
  signal i2s_clk_en, zsck, zzsck, zzzsck, imem_rd : std_logic;
88
  signal clk_cnt : integer range 0 to 255;
89
  signal adr_cnt : integer range 0 to 2**(ADDR_WIDTH - 1) - 1;
90
  type srx_states is (IDLE, WAIT_CLK, TRX_DATA, RX_WRITE, SYNC);
91
  signal sd_ctrl : srx_states;
92
  signal bit_cnt, bits_to_trx : integer range 0 to 63;
93
  signal toggle, master, neg_edge, ws_pos_edge, ws_neg_edge : std_logic;
94
  signal data_in : std_logic_vector(DATA_WIDTH - 1 downto 0);
95
  signal zws, zzws, zzzws, i2s_ws, new_word, last_bit: std_logic;
96
  signal imem_rdwr, receiver : std_logic;
97
  signal ws_cnt : integer range 0 to 31;
98
 
99
begin
100
 
101
-- Create signals that reflect generics
102
  SGM: if IS_MASTER = 1 generate
103
    master <= '1';
104
  end generate SGM;
105
  SGS: if IS_MASTER = 0 generate
106
    master <= '0';
107
  end generate SGS;
108
  SGRX: if IS_RECEIVER = 1 generate
109
    receiver <= '1';
110
  end generate SGRX;
111
  SGTX: if IS_RECEIVER = 0 generate
112
    receiver <= '0';
113
  end generate SGTX;
114
 
115
-- I2S clock enable generation, master mode. The clock is a fraction of the
116
-- Wishbone bus clock, determined by the conf_ratio value.
117
  CGM: if IS_MASTER = 1 generate
118
    CGEN: process (wb_clk_i)
119
    begin
120
      if rising_edge(wb_clk_i) then
121
        if conf_en = '0' then           -- disabled
122
          i2s_clk_en <= '0';
123
          clk_cnt <= 0;
124
          neg_edge <= '0';
125
          toggle <= '0';
126
        else                              -- enabled
127
          if clk_cnt < to_integer(unsigned(conf_ratio)) + 1 then
128
            clk_cnt <= (clk_cnt + 1) mod 256;
129
            i2s_clk_en <= '0';
130
          else
131
            clk_cnt <= 0;
132
            i2s_clk_en <= '1';
133
            neg_edge <= not neg_edge;
134
          end if;
135
          toggle <= neg_edge;
136
        end if;
137
      end if;
138
    end process CGEN;
139
  end generate CGM;
140
 
141
-- I2S clock enable generation, slave mode. The input clock signal is sampeled
142
-- and the negative edge is located.
143
  CGS: if IS_MASTER = 0 generate
144
    CGEN: process (wb_clk_i)
145
    begin
146
      if rising_edge(wb_clk_i) then
147
        if conf_en = '0' then           -- disabled
148
          i2s_clk_en <= '0';
149
          zsck <= '0';
150
          zzsck <= '0';
151
          zzzsck <= '0';
152
          toggle <= '0';
153
          neg_edge <= '0';
154
        else                            -- enabled
155
          -- synchronize input clock to Wishbone clock domaine
156
          zsck <= i2s_sck_i;
157
          zzsck <= zsck;
158
          zzzsck <= zzsck;
159
          -- look for edges
160
          if zzzsck = '1' and zzsck = '0' then
161
            i2s_clk_en <= '1';
162
            neg_edge <= '1';
163
          elsif zzzsck = '0' and zzsck = '1' then
164
            i2s_clk_en <= '1';
165
            neg_edge <= '0';
166
          else
167
            i2s_clk_en <= '0';
168
          end if;
169
          toggle <= neg_edge;
170
        end if;
171
      end if;
172
    end process CGEN;
173
  end generate CGS;
174
 
175
-- Process to generate word select signal, master mode
176
  WSM: if IS_MASTER = 1 generate
177
    i2s_ws_o <= i2s_ws;
178
    WSG: process (wb_clk_i)
179
    begin
180
      if rising_edge(wb_clk_i) then
181
        if conf_en = '0' then
182
          i2s_ws <= '0';
183
          ws_cnt <= 0;
184
          ws_pos_edge <= '0';
185
          ws_neg_edge <= '0';
186
        else
187
          if i2s_clk_en = '1' and toggle = '1' then
188
            if ws_cnt < bits_to_trx then
189
              ws_cnt <= ws_cnt + 1;
190
            else
191
              i2s_ws <= not i2s_ws;
192
              ws_cnt <= 0;
193
              if i2s_ws = '1' then
194
                ws_neg_edge <= '1';
195
              else
196
                ws_pos_edge <= '1';
197
              end if;
198
            end if;
199
          else
200
            ws_pos_edge <= '0';
201
            ws_neg_edge <= '0';
202
          end if;
203
        end if;
204
      end if;
205
    end process WSG;
206
  end generate WSM;
207
 
208
-- Process to detect word select edges, slave mode
209
  WSD: if IS_MASTER = 0 generate
210
    i2s_ws <= i2s_ws_i;
211
    WSDET: process (wb_clk_i)
212
    begin
213
      if rising_edge(wb_clk_i) then
214
        if conf_en = '0' then
215
          ws_pos_edge <= '0';
216
          ws_neg_edge <= '0';
217
          zws <= i2s_ws;
218
          zzws <= i2s_ws;
219
          zzzws <= i2s_ws;
220
        else
221
          -- sync i2s_ws_io to our clock domaine
222
          zws <= i2s_ws;
223
          zzws <= zws;
224
          zzzws <= zzws;
225
          -- detect negative edge
226
          if zzzws = '1' and zzws = '0' then
227
            ws_neg_edge <= '1';
228
          else
229
            ws_neg_edge <= '0';
230
          end if;
231
          -- detect positive edge
232
          if zzzws = '0' and zzws = '1' then
233
            ws_pos_edge <= '1';
234
          else
235
            ws_pos_edge <= '0';
236
          end if;
237
        end if;
238
      end if;
239
    end process WSDET;
240
  end generate WSD;
241
 
242
-- Logic to generate clock signal, master mode
243
  SCKM: if IS_MASTER = 1 generate
244
    i2s_sck_o <= toggle;
245
  end generate SCKM;
246
 
247
-- Process to receive data on i2s_sd_i, or transmit data on i2s_sd_o
248
  sample_addr <= std_logic_vector(to_unsigned(adr_cnt, ADDR_WIDTH - 1));
249
  mem_rdwr <= imem_rdwr;
250
  sample_dat_o <= data_in;
251
 
252
  SDRX: process (wb_clk_i)
253
  begin
254
    if rising_edge(wb_clk_i) then
255
      if conf_en = '0' then           -- codec disabled
256
        imem_rdwr <= '0';
257
        sd_ctrl <= IDLE;
258
        data_in <= (others => '0');
259
        bit_cnt <= 0;
260
        bits_to_trx <= 0;
261
        new_word <= '0';
262
        last_bit <= '0';
263
        adr_cnt <= 0;
264
        evt_lsbf <= '0';
265
        evt_hsbf <= '0';
266
        i2s_sd_o <= '0';
267
      else
268
        case sd_ctrl is
269
          when IDLE =>
270
            imem_rdwr <= '0';
271
            if to_integer(unsigned(conf_res)) > 15 and
272
              to_integer(unsigned(conf_res)) < 33 then
273
              bits_to_trx <= to_integer(unsigned(conf_res)) - 1;
274
            else
275
              bits_to_trx <= 15;
276
            end if;
277
            if conf_en = '1' then
278
              if (ws_pos_edge = '1' and conf_swap = '1') or
279
                (ws_neg_edge = '1' and conf_swap = '0') then
280
                if receiver = '1' then    -- recevier
281
                  sd_ctrl <= WAIT_CLK;
282
                else
283
                  imem_rdwr <= '1';       -- read first data if transmitter
284
                  sd_ctrl <= TRX_DATA;
285
                end if;
286
              end if;
287
            end if;
288
          when WAIT_CLK =>              -- wait for first bit after WS
289
            adr_cnt <= 0;
290
            bit_cnt <= 0;
291
            new_word <= '0';
292
            last_bit <= '0';
293
            data_in <= (others => '0');
294
            if i2s_clk_en = '1' and neg_edge = '0' then
295
              sd_ctrl <= TRX_DATA;
296
            end if;
297
          when TRX_DATA =>              -- transmit/receive serial data 
298
            imem_rdwr <= '0';
299
            evt_hsbf <= '0';
300
            evt_lsbf <= '0';
301
            if master = '0' then
302
              if zzzws /= zzws then
303
                new_word <= '1';
304
              end if;
305
            else
306
              if ws_pos_edge = '1' or ws_neg_edge = '1' then
307
                new_word <= '1';
308
              end if;
309
            end if;
310
            if new_word = '1' and i2s_clk_en = '1' and neg_edge = '0' then
311
              last_bit <= '1';
312
            end if;
313
            -- recevier operation
314
            if receiver = '1' then
315
              if i2s_clk_en = '1' and neg_edge = '1' then
316
                if master = '1' then    -- master mode
317
                  if bit_cnt < bits_to_trx and new_word = '0' then
318
                    bit_cnt <= bit_cnt + 1;
319
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
320
                  else
321
                    imem_rdwr <= '1';
322
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
323
                    sd_ctrl <= RX_WRITE;
324
                  end if;
325
                else                    -- slave mode
326
                  if bit_cnt <= bits_to_trx and new_word = '0' then
327
                    bit_cnt <= bit_cnt + 1;
328
                    data_in(bits_to_trx - bit_cnt) <= i2s_sd_i;
329
                  else
330
                    imem_rdwr <= '1';
331
                    sd_ctrl <= RX_WRITE;
332
                  end if;
333
                end if;
334
              end if;
335
            end if;
336
            -- transmitter operation
337
            if receiver = '0' then
338
              if master = '1' then      -- master mode
339
                if i2s_clk_en = '1' and neg_edge = '0' then
340
                  if bit_cnt < bits_to_trx and new_word = '0' then
341
                    bit_cnt <= bit_cnt + 1;
342
                    i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
343
                  else
344
                    bit_cnt <= bit_cnt + 1;
345
                    if bit_cnt > bits_to_trx then
346
                      i2s_sd_o <= '0';
347 17 gedra
                    else
348
                      i2s_sd_o <= sample_dat_i(0);
349 7 gedra
                    end if;
350
                    -- transmitter address counter
351
                    imem_rdwr <= '1';
352
                    adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
353
                    if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
354
                      evt_lsbf <= '1';
355
                    else
356
                      evt_lsbf <= '0';
357
                    end if;
358
                    if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
359
                      evt_hsbf <= '1';
360
                    else
361
                      evt_hsbf <= '0';
362
                    end if;
363
                    sd_ctrl <= SYNC;
364
                  end if;
365
                end if;
366
              else                     -- slave mode
367
                if i2s_clk_en = '1' and neg_edge = '1' then
368
                  if bit_cnt < bits_to_trx and new_word = '0' then
369
                    bit_cnt <= bit_cnt + 1;
370
                    i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
371
                  else
372
                    bit_cnt <= bit_cnt + 1;
373
                    if bit_cnt > bits_to_trx then
374
                      i2s_sd_o <= '0';
375
                    else
376 23 gedra
                      i2s_sd_o <= sample_dat_i(bits_to_trx - bit_cnt);
377 7 gedra
                    end if;
378
                    if new_word = '1' then  -- transmitter address counter
379
                      imem_rdwr <= '1';
380
                      adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
381
                      if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
382
                        evt_lsbf <= '1';
383
                      else
384
                        evt_lsbf <= '0';
385
                      end if;
386
                      if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
387
                        evt_hsbf <= '1';
388
                      else
389
                        evt_hsbf <= '0';
390
                      end if;
391
                      sd_ctrl <= SYNC;
392
                    end if;
393
                  end if;
394
                end if;
395
              end if;
396
            end if;
397
          when RX_WRITE =>             -- write received word to sample buffer
398
            imem_rdwr <= '0';
399
            adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
400
            if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
401
              evt_lsbf <= '1';
402
            else
403
              evt_lsbf <= '0';
404
            end if;
405
            if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
406
              evt_hsbf <= '1';
407
            else
408
              evt_hsbf <= '0';
409
            end if;
410
            sd_ctrl <= SYNC;
411
          when SYNC =>                  -- synchronise with next word
412
            imem_rdwr <= '0';
413
            evt_hsbf <= '0';
414
            evt_lsbf <= '0';
415
            bit_cnt <= 0;
416
            if ws_pos_edge = '1' or ws_neg_edge = '1' then
417
              new_word <= '1';
418
            end if;
419
            if new_word = '1' and i2s_clk_en = '1' and neg_edge = '0' then
420
              last_bit <= '1';
421
            end if;
422
            if receiver = '1' then      -- receive mode
423
              if master = '1' then
424
                new_word <= '0';
425
                last_bit <= '0';
426
                data_in <= (others => '0');
427
                sd_ctrl <= TRX_DATA;
428
              else
429
                if i2s_clk_en = '1' and neg_edge = '0' and new_word = '1' then
430
                  new_word <= '0';
431
                  last_bit <= '0';
432
                  data_in <= (others => '0');
433
                  sd_ctrl <= TRX_DATA;
434
                end if;
435
              end if;
436
            else                        -- transmit mode
437
              if master = '1' then
438
                new_word <= '0';
439
                last_bit <= '0';
440
                data_in <= (others => '0');
441
                sd_ctrl <= TRX_DATA;
442
              elsif i2s_clk_en = '1' and neg_edge = '0' then
443
                new_word <= '0';
444
                last_bit <= '0';
445
                data_in <= (others => '0');
446
                sd_ctrl <= TRX_DATA;
447
              end if;
448
            end if;
449
          when others => null;
450
        end case;
451
      end if;
452
    end if;
453
  end process SDRX;
454
 
455
end rtl;

powered by: WebSVN 2.1.0

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