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 29

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

powered by: WebSVN 2.1.0

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