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 56

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

powered by: WebSVN 2.1.0

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