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

Subversion Repositories spdif_interface

[/] [spdif_interface/] [trunk/] [rtl/] [vhdl/] [tx_encoder.vhd] - Blame information for rev 73

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 56 gedra
----------------------------------------------------------------------
2
----                                                              ----
3
---- WISHBONE SPDIF IP Core                                       ----
4
----                                                              ----
5
---- This file is part of the SPDIF project                       ----
6
---- http://www.opencores.org/cores/spdif_interface/              ----
7
----                                                              ----
8
---- Description                                                  ----
9
---- SPDIF transmitter signal encoder. Reads out samples from the ----
10
---- sample buffer, assembles frames and subframes and encodes    ----
11
---- serial data as bi-phase mark code.                           ----
12
----                                                              ----
13
---- To Do:                                                       ----
14
---- -                                                            ----
15
----                                                              ----
16
---- Author(s):                                                   ----
17
---- - Geir Drange, gedra@opencores.org                           ----
18
----                                                              ----
19
----------------------------------------------------------------------
20
----                                                              ----
21
---- Copyright (C) 2004 Authors and OPENCORES.ORG                 ----
22
----                                                              ----
23
---- This source file may be used and distributed without         ----
24
---- restriction provided that this copyright statement is not    ----
25
---- removed from the file and that any derivative work contains  ----
26
---- the original copyright notice and the associated disclaimer. ----
27
----                                                              ----
28
---- This source file is free software; you can redistribute it   ----
29
---- and/or modify it under the terms of the GNU Lesser General   ----
30
---- Public License as published by the Free Software Foundation; ----
31
---- either version 2.1 of the License, or (at your option) any   ----
32
---- later version.                                               ----
33
----                                                              ----
34
---- This source is distributed in the hope that it will be       ----
35
---- useful, but WITHOUT ANY WARRANTY; without even the implied   ----
36
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ----
37
---- PURPOSE. See the GNU Lesser General Public License for more  ----
38
---- details.                                                     ----
39
----                                                              ----
40
---- You should have received a copy of the GNU Lesser General    ----
41
---- Public License along with this source; if not, download it   ----
42
---- from http://www.opencores.org/lgpl.shtml                     ----
43
----                                                              ----
44
----------------------------------------------------------------------
45
--
46
-- CVS Revision History
47
--
48
-- $Log: not supported by cvs2svn $
49 72 gedra
-- Revision 1.2  2005/03/27 14:02:51  gedra
50
-- evt_hsbf and evt_lsbf signals stayed high too long
51
--
52 68 gedra
-- Revision 1.1  2004/07/19 16:59:08  gedra
53
-- Transmitter SPDIF encoder.
54 56 gedra
--
55
--
56 68 gedra
--
57 56 gedra
 
58
library ieee;
59 72 gedra
use ieee.std_logic_1164.all;
60 56 gedra
use ieee.numeric_std.all;
61
 
62 72 gedra
entity tx_encoder is
63
   generic (DATA_WIDTH : integer range 16 to 32;
64
            ADDR_WIDTH : integer range 8 to 64);
65
   port (
66
      wb_clk_i     : in  std_logic;     -- clock
67
      conf_mode    : in  std_logic_vector(3 downto 0);    -- sample format
68
      conf_ratio   : in  std_logic_vector(7 downto 0);    -- clock divider
69
      conf_udaten  : in  std_logic_vector(1 downto 0);    -- user data control
70
      conf_chsten  : in  std_logic_vector(1 downto 0);    -- ch. status control
71
      conf_txdata  : in  std_logic;     -- sample data enable
72
      conf_txen    : in  std_logic;     -- spdif signal enable
73
      user_data_a  : in  std_logic_vector(191 downto 0);  -- ch. a user data
74
      user_data_b  : in  std_logic_vector(191 downto 0);  -- ch. b user data
75
      ch_stat_a    : in  std_logic_vector(191 downto 0);  -- ch. a status
76
      ch_stat_b    : in  std_logic_vector(191 downto 0);  -- ch. b status
77
      chstat_freq  : in  std_logic_vector(1 downto 0);    -- sample freq.
78
      chstat_gstat : in  std_logic;     -- generation status
79
      chstat_preem : in  std_logic;     -- preemphasis status
80
      chstat_copy  : in  std_logic;     -- copyright bit
81
      chstat_audio : in  std_logic;     -- data format
82
      sample_data  : in  std_logic_vector(DATA_WIDTH - 1 downto 0);  -- audio data
83
      mem_rd       : out std_logic;     -- sample buffer read
84
      sample_addr  : out std_logic_vector(ADDR_WIDTH - 2 downto 0);  -- address
85
      evt_lcsbf    : out std_logic;     -- lower ch.st./user data buf empty 
86
      evt_hcsbf    : out std_logic;     -- higher ch.st/user data buf empty 
87
      evt_hsbf     : out std_logic;     -- higher sample buf empty event
88
      evt_lsbf     : out std_logic;     -- lower sample buf empty event
89
      spdif_tx_o   : out std_logic);
90 56 gedra
end tx_encoder;
91
 
92
architecture rtl of tx_encoder is
93
 
94 72 gedra
   signal spdif_clk_en, spdif_out            : std_logic;
95
   signal clk_cnt                            : integer range 0 to 511;
96
   type buf_states is (IDLE, READ_CHA, READ_CHB, CHA_RDY, CHB_RDY);
97
   signal bufctrl                            : buf_states;
98
   signal adr_cnt                            : integer range 0 to 2**(ADDR_WIDTH - 1) - 1;
99
   signal cha_samp_ack, chb_samp_ack         : std_logic;
100
   type frame_states is (IDLE, BLOCK_START, CHANNEL_A, CHANNEL_B);
101
   signal framest                            : frame_states;
102
   signal frame_cnt                          : integer range 0 to 191;
103
   signal bit_cnt, par_cnt                   : integer range 0 to 31;
104
   signal inv_preamble, toggle, valid        : std_logic;
105
   signal def_user_data, def_ch_status       : std_logic_vector(191 downto 0);
106
   signal active_user_data, active_ch_status : std_logic_vector(191 downto 0);
107
   signal audio                              : std_logic_vector(23 downto 0);
108
   signal par_vector                         : std_logic_vector(26 downto 0);
109
   signal send_audio, imem_rd                : std_logic;
110 56 gedra
 
111 72 gedra
   constant X_PREAMBLE : std_logic_vector(0 to 7) := "11100010";
112
   constant Y_PREAMBLE : std_logic_vector(0 to 7) := "11100100";
113
   constant Z_PREAMBLE : std_logic_vector(0 to 7) := "11101000";
114 56 gedra
 
115 72 gedra
   function encode_bit (
116
      signal bit_cnt    : integer;          -- sub-frame bit position
117
      signal valid      : std_logic;        -- validity bit
118
      signal frame_cnt  : integer;          -- frame counter
119
      signal par_cnt    : integer;          -- parity counter
120
      signal user_data  : std_logic_vector(191 downto 0);
121
      signal ch_status  : std_logic_vector(191 downto 0);
122
      signal audio      : std_logic_vector(23 downto 0);
123
      signal toggle     : std_logic;
124
      signal prev_spdif : std_logic)        -- prev. value of spdif signal
125
      return std_logic is
126
      variable spdif, next_bit : std_logic;
127
   begin
128
      if bit_cnt > 3 and bit_cnt < 28 then  -- audio part
129
         next_bit := audio(bit_cnt - 4);
130
      elsif bit_cnt = 28 then               -- validity bit
131
         next_bit := valid;
132
      elsif bit_cnt = 29 then               -- user data
133
         next_bit := user_data(frame_cnt);
134
      elsif bit_cnt = 30 then
135
         next_bit := ch_status(frame_cnt);  -- channel status
136
      elsif bit_cnt = 31 then
137
         if par_cnt mod 2 = 1 then
138
            next_bit := '1';
139
         else
140
            next_bit := '0';
141
         end if;
142 56 gedra
      end if;
143 72 gedra
      -- bi-phase mark encoding:
144
      if next_bit = '0' then
145
         if toggle = '0' then
146
            spdif := not prev_spdif;
147
         else
148
            spdif := prev_spdif;
149
         end if;
150 56 gedra
      else
151 72 gedra
         spdif := not prev_spdif;
152 56 gedra
      end if;
153 72 gedra
      return(spdif);
154
   end encode_bit;
155
 
156 56 gedra
begin
157
 
158
-- SPDIF clock enable generation. The clock is a fraction of the Wishbone bus
159
-- clock, determined by the conf_ratio value.
160 72 gedra
   CGEN : process (wb_clk_i)
161
   begin
162
      if rising_edge(wb_clk_i) then
163
         if conf_txen = '0' then        -- transmitter disabled
164
            spdif_clk_en <= '0';
165
            clk_cnt      <= 0;
166
         else                           -- transmitter enabled
167
            if clk_cnt < to_integer(unsigned(conf_ratio)) then  -- <= ?
168
               clk_cnt      <= clk_cnt + 1;
169
               spdif_clk_en <= '0';
170
            else
171
               clk_cnt      <= 0;
172
               spdif_clk_en <= '1';
173
            end if;
174
         end if;
175 56 gedra
      end if;
176 72 gedra
   end process CGEN;
177 56 gedra
 
178
-- Sample memory read process. Enabled by the conf_txdata bit.
179
-- Buffer address is reset when disabled. Also generates events for
180
-- lower and upper buffer empty conditions
181 72 gedra
   sample_addr <= std_logic_vector(to_unsigned(adr_cnt, ADDR_WIDTH - 1));
182
   mem_rd      <= imem_rd;
183 56 gedra
 
184 72 gedra
   SRD : process (wb_clk_i)
185
   begin
186
      if rising_edge(wb_clk_i) then
187
         if conf_txdata = '0' then
188
            bufctrl  <= IDLE;
189
            imem_rd  <= '0';
190
            adr_cnt  <= 0;
191
            evt_lsbf <= '0';
192
            evt_hsbf <= '0';
193
         else
194
            case bufctrl is
195
               when IDLE =>
196
                  adr_cnt <= 0;
197
                  imem_rd <= '0';
198
                  if conf_txdata = '1' then
199
                     bufctrl <= READ_CHA;
200
                     imem_rd <= '1';
201 56 gedra
                  end if;
202 72 gedra
               when READ_CHA =>
203
                  imem_rd <= '0';
204
                  adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
205
                  bufctrl <= CHA_RDY;
206
               when CHA_RDY =>
207
                  if cha_samp_ack = '1' then
208
                     imem_rd <= '1';
209
                     bufctrl <= READ_CHB;
210 56 gedra
                  end if;
211 72 gedra
               when READ_CHB =>
212
                  imem_rd <= '0';
213
                  adr_cnt <= (adr_cnt + 1) mod 2**(ADDR_WIDTH - 1);
214
                  bufctrl <= CHB_RDY;
215
               when CHB_RDY =>
216
                  if chb_samp_ack = '1' then
217
                     imem_rd <= '1';
218
                     bufctrl <= READ_CHA;
219 56 gedra
                  end if;
220 72 gedra
               when others =>
221
                  bufctrl <= IDLE;
222
            end case;
223
            -- generate lower/upper buffer empty events
224
            if imem_rd = '1' then
225
               if adr_cnt = 2**(ADDR_WIDTH - 2) - 1 then
226
                  evt_lsbf <= '1';
227
               end if;
228
               if adr_cnt = 2**(ADDR_WIDTH - 1) - 1 then
229
                  evt_hsbf <= '1';
230
               end if;
231
            else
232
               evt_lsbf <= '0';
233
               evt_hsbf <= '0';
234
            end if;
235
         end if;
236 56 gedra
      end if;
237 72 gedra
   end process SRD;
238 56 gedra
 
239 72 gedra
-- State machine that generates sub-frames and blocks
240
   spdif_tx_o <= spdif_out;
241
 
242
   FRST : process (wb_clk_i)
243
   begin
244 56 gedra
      if rising_edge(wb_clk_i) then
245 72 gedra
         if conf_txen = '0' then
246
            framest      <= IDLE;
247
            frame_cnt    <= 0;
248
            bit_cnt      <= 0;
249
            spdif_out    <= '0';
250
            inv_preamble <= '0';
251
            toggle       <= '0';
252
            valid        <= '1';
253
            send_audio   <= '0';
254
            cha_samp_ack <= '0';
255
            chb_samp_ack <= '0';
256
            evt_lcsbf    <= '0';
257
            evt_hcsbf    <= '0';
258
         else
259
            if spdif_clk_en = '1' then  -- SPDIF clock is twice the bit rate
260
               case framest is
261
                  when IDLE =>
262
                     bit_cnt      <= 0;
263
                     frame_cnt    <= 0;
264
                     inv_preamble <= '0';
265
                     toggle       <= '0';
266
                     framest      <= BLOCK_START;
267
                  when BLOCK_START =>   -- Start of channels status block/Ch. A
268
                     evt_lcsbf    <= '0';
269
                     evt_hcsbf    <= '0';
270
                     chb_samp_ack <= '0';
271
                     toggle       <= not toggle;  -- Each bit uses two clock enables,
272
                     if toggle = '1' then         -- counted by the toggle bit.
273
                        if bit_cnt < 31 then
274
                           bit_cnt <= bit_cnt + 1;
275
                        else
276
                           bit_cnt <= 0;
277
                           if send_audio = '1' then
278
                              cha_samp_ack <= '1';
279
                           end if;
280
                           framest <= CHANNEL_B;
281
                        end if;
282
                     end if;
283
                     -- Block start uses preamble Z.
284
                     if bit_cnt < 4 then
285
                        if toggle = '0' then
286
                           spdif_out <= Z_PREAMBLE(2 * bit_cnt) xor inv_preamble;
287
                        else
288
                           spdif_out <= Z_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble;
289
                        end if;
290
                        par_cnt <= 0;
291
                     elsif bit_cnt > 3 and bit_cnt <= 31 then
292
                        spdif_out <= encode_bit(bit_cnt, valid, frame_cnt,
293
                                                par_cnt, active_user_data,
294
                                                active_ch_status,
295
                                                audio, toggle, spdif_out);
296
                        if bit_cnt = 31 then
297
                           inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt,
298
                                                      par_cnt, active_user_data,
299
                                                      active_ch_status,
300
                                                      audio, toggle, spdif_out);
301
                        end if;
302
                        if toggle = '0' then
303
                           if bit_cnt > 3 and bit_cnt < 31 and
304
                              par_vector(bit_cnt - 4) = '1' then
305
                              par_cnt <= par_cnt + 1;
306
                           end if;
307
                        end if;
308
                     end if;
309
                  when CHANNEL_A =>     -- Sub-frame: channel A.
310
                     evt_lcsbf    <= '0';
311
                     evt_hcsbf    <= '0';
312
                     chb_samp_ack <= '0';
313
                     toggle       <= not toggle;
314
                     if toggle = '1' then
315
                        if bit_cnt < 31 then
316
                           bit_cnt <= bit_cnt + 1;
317
                        else
318
                           bit_cnt <= 0;
319
                           if spdif_out = '1' then
320
                              inv_preamble <= '1';
321
                           else
322
                              inv_preamble <= '0';
323
                           end if;
324
                           if send_audio = '1' then
325
                              cha_samp_ack <= '1';
326
                           end if;
327
                           framest <= CHANNEL_B;
328
                        end if;
329
                     end if;
330
                     -- Channel A uses preable X.
331
                     if bit_cnt < 4 then
332
                        if toggle = '0' then
333
                           spdif_out <= X_PREAMBLE(2 * bit_cnt) xor inv_preamble;
334
                        else
335
                           spdif_out <= X_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble;
336
                        end if;
337
                        par_cnt <= 0;
338
                     elsif bit_cnt > 3 and bit_cnt <= 31 then
339
                        spdif_out <= encode_bit(bit_cnt, valid, frame_cnt,
340
                                                par_cnt, active_user_data,
341
                                                active_ch_status,
342
                                                audio, toggle, spdif_out);
343
                        if bit_cnt = 31 then
344
                           inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt,
345
                                                      par_cnt, active_user_data,
346
                                                      active_ch_status,
347
                                                      audio, toggle, spdif_out);
348
                        end if;
349
                        if toggle = '0' then
350
                           if bit_cnt > 3 and bit_cnt < 31 and
351
                              par_vector(bit_cnt - 4) = '1' then
352
                              par_cnt <= par_cnt + 1;
353
                           end if;
354
                        end if;
355
                     end if;
356
                  when CHANNEL_B =>     -- Sub-frame: channel B.
357
                     cha_samp_ack <= '0';
358
                     toggle       <= not toggle;
359
                     if toggle = '1' then
360
                        if bit_cnt < 31 then
361
                           bit_cnt <= bit_cnt + 1;
362
                        else
363
                           bit_cnt <= 0;
364
                           valid   <= not conf_txdata;
365
                           if spdif_out = '1' then
366
                              inv_preamble <= '1';
367
                           else
368
                              inv_preamble <= '0';
369
                           end if;
370
                           send_audio <= conf_txdata;  -- 1 if audio samples sohuld be sent
371
                           if send_audio = '1' then
372
                              chb_samp_ack <= '1';
373
                           end if;
374
                           if frame_cnt < 191 then  -- One block is 192 frames
375
                              frame_cnt <= frame_cnt + 1;
376
                              if frame_cnt = 96 then
377
                                 evt_lcsbf <= '1';
378
                              end if;
379
                              framest <= CHANNEL_A;
380
                           else
381
                              frame_cnt <= 0;
382
                              evt_hcsbf <= '1';
383
                              framest   <= BLOCK_START;
384
                           end if;
385
                        end if;
386
                     end if;
387
                     -- Channel B uses preable Y.
388
                     if bit_cnt < 4 then
389
                        if toggle = '0' then
390
                           spdif_out <= Y_PREAMBLE(2 * bit_cnt) xor inv_preamble;
391
                        else
392
                           spdif_out <= Y_PREAMBLE(2 * bit_cnt + 1) xor inv_preamble;
393
                        end if;
394
                        par_cnt <= 0;
395
                     elsif bit_cnt > 3 and bit_cnt <= 31 then
396
                        spdif_out <= encode_bit(bit_cnt, valid, frame_cnt,
397
                                                par_cnt, active_user_data,
398
                                                active_ch_status,
399
                                                audio, toggle, spdif_out);
400
                        if bit_cnt = 31 then
401
                           inv_preamble <= encode_bit(bit_cnt, valid, frame_cnt,
402
                                                      par_cnt, active_user_data,
403
                                                      active_ch_status,
404
                                                      audio, toggle, spdif_out);
405
                        end if;
406
                        if toggle = '0' then
407
                           if bit_cnt > 3 and bit_cnt < 31 and
408
                              par_vector(bit_cnt - 4) = '1' then
409
                              par_cnt <= par_cnt + 1;
410
                           end if;
411
                        end if;
412
                     end if;
413
                  when others =>
414
                     framest <= IDLE;
415
               end case;
416
            end if;
417
         end if;
418 56 gedra
      end if;
419 72 gedra
   end process FRST;
420 56 gedra
 
421 72 gedra
-- Audio data latching
422
   DA32 : if DATA_WIDTH = 32 generate
423
      ALAT : process (wb_clk_i)
424
      begin
425
         if rising_edge(wb_clk_i) then
426
            if send_audio = '0' then
427
               audio(23 downto 0) <= (others => '0');
428
            else
429
               case to_integer(unsigned(conf_mode)) is
430
                  when 0 =>             -- 16 bit audio
431
                     audio(23 downto 8) <= sample_data(15 downto 0);
432
                     audio(7 downto 0)  <= (others => '0');
433
                  when 1 =>             -- 17 bit audio
434
                     audio(23 downto 7) <= sample_data(16 downto 0);
435
                     audio(6 downto 0)  <= (others => '0');
436
                  when 2 =>             -- 18 bit audio
437
                     audio(23 downto 6) <= sample_data(17 downto 0);
438
                     audio(5 downto 0)  <= (others => '0');
439
                  when 3 =>             -- 19 bit audio
440
                     audio(23 downto 5) <= sample_data(18 downto 0);
441
                     audio(4 downto 0)  <= (others => '0');
442
                  when 4 =>             -- 20 bit audio
443
                     audio(23 downto 4) <= sample_data(19 downto 0);
444
                     audio(3 downto 0)  <= (others => '0');
445
                  when 5 =>             -- 21 bit audio
446
                     audio(23 downto 3) <= sample_data(20 downto 0);
447
                     audio(2 downto 0)  <= (others => '0');
448
                  when 6 =>             -- 22 bit audio
449
                     audio(23 downto 2) <= sample_data(21 downto 0);
450
                     audio(1 downto 0)  <= (others => '0');
451
                  when 7 =>             -- 23 bit audio
452
                     audio(23 downto 1) <= sample_data(22 downto 0);
453
                     audio(0)           <= '0';
454
                  when 8 =>             -- 24 bit audio
455
                     audio(23 downto 0) <= sample_data(23 downto 0);
456
                  when others =>        -- unsupported modes
457
                     audio(23 downto 0) <= (others => '0');
458
               end case;
459
            end if;
460
         end if;
461
      end process ALAT;
462
   end generate DA32;
463
 
464
   DA16 : if DATA_WIDTH = 16 generate
465
      ALAT : process (wb_clk_i)
466
      begin
467
         if rising_edge(wb_clk_i) then
468
            if send_audio = '0' then
469
               audio(23 downto 0) <= (others => '0');
470
            else
471
               audio(23 downto 8) <= sample_data(15 downto 0);
472
               audio(7 downto 0)  <= (others => '0');
473
            end if;
474
         end if;
475
      end process ALAT;
476
   end generate DA16;
477
 
478 56 gedra
-- Parity vector. These bits are counted to generate even parity
479 72 gedra
   par_vector(23 downto 0) <= audio(23 downto 0);
480
   par_vector(24)          <= valid;
481
   par_vector(25)          <= active_user_data(frame_cnt);
482
   par_vector(26)          <= active_ch_status(frame_cnt);
483
 
484 56 gedra
-- Channel status and user datat to be used if buffers are disabled.
485
-- User data is then all zero, while channel status bits are taken from
486
-- register TxChStat.
487 72 gedra
   def_user_data(191 downto 0) <= (others => '0');
488
   def_ch_status(0)            <= '0';           -- consumer mode
489
   def_ch_status(1)            <= chstat_audio;  -- audio bit
490
   def_ch_status(2)            <= chstat_copy;   -- copy right
491
   def_ch_status(5 downto 3)   <= "000" when chstat_preem = '0'
492
                                else "001";      -- pre-emphasis
493
   def_ch_status(7 downto 6)   <= "00";
494
   def_ch_status(14 downto 8)  <= (others => '0');
495
   def_ch_status(15)           <= chstat_gstat;  -- generation status
496
   def_ch_status(23 downto 16) <= (others => '0');
497
   def_ch_status(27 downto 24) <= "0000" when chstat_freq = "00" else
498
                                  "0010" when chstat_freq = "01" else
499
                                  "0011" when chstat_freq = "10" else
500
                                  "0001";
501
   def_ch_status(191 downto 28) <= (others => '0');
502 56 gedra
 
503
-- Generate channel status vector based on configuration register setting.
504 72 gedra
   active_ch_status <= ch_stat_a when conf_chsten = "01" else
505
                       ch_stat_a when conf_chsten = "10" and framest = CHANNEL_A else
506
                       ch_stat_b when conf_chsten = "10" and framest = CHANNEL_B else
507
                       def_ch_status;
508
 
509 56 gedra
-- Generate user data vector based on configuration register setting.
510 72 gedra
   active_user_data <= user_data_a when conf_udaten = "01" else
511
                       user_data_a when conf_udaten = "10" and framest = CHANNEL_A else
512
                       user_data_b when conf_udaten = "10" and framest = CHANNEL_B else
513
                       def_user_data;
514
 
515 56 gedra
end rtl;

powered by: WebSVN 2.1.0

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