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

Subversion Repositories spdif_interface

[/] [spdif_interface/] [trunk/] [rtl/] [vhdl/] [rx_phase_det.vhd] - Blame information for rev 39

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

Line No. Rev Author Line
1 11 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
---- Oversampling phase detector. Decodes bi-phase mark encoded   ----
10
---- signal. Clock must be at least 8 times higher than bit rate. ----
11
---- The SPDIF bitrate must be minimum 100kHz.                    ----
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 39 gedra
-- Revision 1.2  2004/06/13 18:08:50  gedra
50
-- Renamed generic and cleaned some lint's
51
--
52 20 gedra
-- Revision 1.1  2004/06/06 15:43:02  gedra
53
-- Early version of the bi-phase mark decoder.
54 11 gedra
--
55 20 gedra
--
56 11 gedra
 
57 20 gedra
library ieee;
58
use ieee.std_logic_1164.all;
59 11 gedra
 
60
entity rx_phase_det is
61 20 gedra
  generic (WISHBONE_FREQ: natural := 33);   -- WishBone frequency in MHz
62 11 gedra
  port (
63 20 gedra
    wb_clk_i: in std_logic;             -- wishbone clock
64
    rxen: in std_logic;                 -- phase detector enable
65
    spdif: in std_logic;                -- SPDIF input signal
66
    lock: out std_logic;                -- true if locked to spdif input
67
    rx_data: out std_logic;             -- recevied data
68
    rx_data_en: out std_logic;          -- received data enable
69
    rx_block_start: out std_logic;      -- start-of-block pulse
70
    rx_frame_start: out std_logic;      -- start-of-frame pulse
71
    rx_channel_a: out std_logic;        -- 1 if channel A frame is recevied
72
    rx_error: out std_logic;            -- signal error was detected
73
    ud_a_en: out std_logic;             -- user data ch. A enable
74
    ud_b_en: out std_logic;             -- user data ch. B enable
75
    cs_a_en: out std_logic;             -- channel status ch. A enable
76
    cs_b_en: out std_logic);            -- channel status ch. B enable);            
77 11 gedra
end rx_phase_det;
78
 
79
architecture rtl of rx_phase_det is
80
 
81 39 gedra
  constant TRANSITIONS : integer := 70;
82 11 gedra
  constant FRAMES_FOR_LOCK : integer := 3;
83 20 gedra
  signal maxpulse, maxp, mp_cnt: integer range 0 to 16 * WISHBONE_FREQ;
84
  signal last_cnt, max_thres : integer range 0 to 16 * WISHBONE_FREQ;
85
  signal minpulse, minp, min_thres: integer range 0 to 8 * WISHBONE_FREQ;
86 11 gedra
  signal zspdif, spdif_in, zspdif_in, trans, ztrans : std_logic;
87
  signal trans_cnt : integer range 0 to TRANSITIONS;
88
  signal valid, p_long, p_short: std_logic;
89
  type pulse_type is (ZERO, SHORT, MED, LONG);
90
  type pulse_array is array (0 to 3) of pulse_type;
91
  signal preamble: pulse_array;
92
  signal new_pulse, short_idx, ilock: std_logic;
93
  type frame_state is (IDLE, HUNT, FRAMESTART, FRAME_RX);
94
  signal framerx : frame_state;
95
  signal frame_cnt : integer range 0 to FRAMES_FOR_LOCK;
96
  signal bit_cnt : integer range 0 to 63;
97
  signal pre_cnt : integer range 0 to 7;
98
  type preamble_types is (NONE, PRE_X, PRE_Y, PRE_Z);
99
  signal new_preamble, last_preamble : preamble_types;
100
  signal irx_channel_a : std_logic;
101
 
102
begin
103
 
104
  -- Pulse width analyzer
105
  PHDET: process (wb_clk_i, rxen)
106
  begin
107
    if rxen = '0' then            -- reset by configuration register bit
108
      maxpulse <= 0;
109
      maxp <= 0;
110
      mp_cnt <= 0;
111
      zspdif <= '0';
112
      zspdif_in <= '0';
113
      spdif_in <= '0';
114
      trans_cnt <= 0;
115
      minpulse <= 0;
116
      minp <= 0;
117
      last_cnt <= 0;
118
      trans <= '0';
119
      valid <= '0';
120
      preamble <= (ZERO, ZERO, ZERO, ZERO);
121
    else
122
      if rising_edge(wb_clk_i) then
123
        -- sync spdif signal to wishbone clock
124
        zspdif <= spdif;
125
        spdif_in <= zspdif;
126
        -- find the longest pulse, which is the bi-phase violation
127
        -- also find the shortest pulse
128
        zspdif_in <= spdif_in;
129
        if zspdif_in /= spdif_in then
130
          mp_cnt <= 0;
131
          trans <= '1';
132
          last_cnt <= mp_cnt;
133
          if mp_cnt > maxp then
134
            maxp <= mp_cnt;
135
          end if;
136
          if mp_cnt < minp then
137
            minp <= mp_cnt;
138
          end if;
139
        else
140
          trans <= '0';
141 20 gedra
          if mp_cnt < 16 * WISHBONE_FREQ then
142 11 gedra
            mp_cnt <= mp_cnt + 1;
143
          end if;
144
        end if;
145
        -- transition counting
146
        if trans = '1' then
147
          if trans_cnt < TRANSITIONS then
148
            trans_cnt <= trans_cnt + 1;
149
          else
150
            -- the max/min pulse length is updated after given # of transitions
151
            trans_cnt <= 0;
152
            maxpulse <= maxp;
153
            maxp <= 0;
154
            minpulse <= minp;
155 20 gedra
            minp <= 8 * WISHBONE_FREQ;
156 11 gedra
            min_thres <= maxp / 2;
157
            if maxp < 11 then
158
              max_thres <= maxp - 1;
159
            else
160
              max_thres <= maxp - 3;
161
            end if;
162
          end if;
163
        end if;
164
        -- detection of valid SPDIF signal
165
        if maxpulse > 6 then
166
          valid <= '1';
167
        else
168
          valid <= '0';
169
        end if;
170
        -- bit decoding
171
        if trans = '1' then
172
          if (last_cnt < min_thres) and (last_cnt > 0) then
173
            p_short <= '1';
174
            preamble(0) <= SHORT;
175
          else
176
            p_short <= '0';
177
          end if;
178
          if last_cnt >= max_thres then
179
            p_long <= '1';
180
            preamble(0) <= LONG;
181
          else
182
            p_long <= '0';
183
          end if;
184
          if last_cnt = 0 then
185
            preamble(0) <= ZERO;
186
          end if;
187
          if (last_cnt < max_thres) and (last_cnt >= min_thres) then
188
            preamble(0) <= MED;
189
          end if;
190
          preamble(3) <= preamble(2);
191
          preamble(2) <= preamble(1);
192
          preamble(1) <= preamble(0);
193
        end if;
194
        -- preamble detection
195
        if preamble(3) = LONG and preamble(2) = LONG and preamble(1) = SHORT
196
          and preamble(0) = SHORT then
197
          new_preamble <= PRE_X;
198
        elsif preamble(3) = LONG and preamble(2) = MED and preamble(1) = SHORT
199
          and preamble(0) = MED then
200
          new_preamble <= PRE_Y;
201
        elsif preamble(3) = LONG and preamble(2) = SHORT and preamble(1) = SHORT
202
          and preamble(0) = LONG then
203
          new_preamble <= PRE_Z;
204
        else
205
          new_preamble <= NONE;
206
        end if;
207
        -- delayed transition pulse for the state machine
208
        ztrans <= trans;
209
        new_pulse <= ztrans;
210
      end if;
211
    end if;
212
  end process;
213
 
214
  lock <= ilock;
215
  rx_channel_a <= irx_channel_a;
216
 
217
  -- State machine that hunt for and lock onto sub-frames
218
  FRX: process (wb_clk_i, rxen)
219
  begin  -- process FRX
220
    if rxen = '0' then
221
      framerx <= IDLE;
222
      ilock <= '0';
223
      rx_data <= '0';
224
      rx_data_en <= '0';
225
      rx_block_start <= '0';
226
      rx_frame_start <= '0';
227
      irx_channel_a <= '0';
228
      ud_a_en <= '0';
229
      ud_b_en <= '0';
230
      cs_a_en <= '0';
231
      cs_b_en <= '0';
232
      rx_error <= '0';
233
    elsif rising_edge(wb_clk_i) then
234
      case framerx is
235
        when  IDLE =>                   -- wait for recevier to be enabled
236
          if valid = '1' then
237
            framerx <= HUNT;
238
          end if;
239
        when HUNT =>                    -- wait for preamble detection
240
          frame_cnt <= 0;
241
          ilock <= '0';
242
          rx_error <= '0';
243
          if new_pulse = '1' then
244
            if new_preamble /= NONE then
245
              framerx <= FRAMESTART;
246
            end if;
247
          end if;
248
        when FRAMESTART =>              -- reset sub-frame bit counter
249
          bit_cnt <= 0;
250
          pre_cnt <= 0;
251
          if frame_cnt < FRAMES_FOR_LOCK then
252
            frame_cnt <= frame_cnt + 1;
253
          else
254
            ilock <= '1';
255
          end if;
256
          last_preamble <= new_preamble;
257
          short_idx <= '0';
258
          rx_frame_start <= '1';
259
          rx_block_start <= '0';
260
          framerx <= FRAME_RX;
261
        when FRAME_RX =>                -- receive complete sub-frame
262
          if new_pulse = '1' then
263
            if bit_cnt < 28 then
264
              case preamble(0) is
265
                when ZERO =>
266
                  short_idx <= '0';
267
                when SHORT =>
268
                  if short_idx = '0' then
269
                    short_idx <= '1';
270
                  else
271
                    -- two short pulses is a logical '1'
272
                    bit_cnt <= bit_cnt + 1;
273
                    short_idx <= '0';
274
                    rx_data <= '1';
275
                    rx_data_en <= ilock;
276
                    -- user data enable for the capture register
277
                    if bit_cnt = 25 and ilock = '1' then
278
                      ud_a_en <= irx_channel_a;
279
                      ud_b_en <= not irx_channel_a;
280
                    end if;
281
                    -- channel status enable for the capture register
282
                    if bit_cnt = 26 and ilock = '1' then
283
                      cs_a_en <= irx_channel_a;
284
                      cs_b_en <= not irx_channel_a;
285
                    end if;
286
                  end if;
287
                when MED =>
288
                  -- medium pulse is logical '0'
289
                  bit_cnt <= bit_cnt + 1;
290
                  rx_data <= '0';
291
                  rx_data_en <= ilock;
292
                  short_idx <= '0';
293
                  -- user data enable for the capture register
294
                  if bit_cnt = 25 and ilock = '1' then
295
                    ud_a_en <= irx_channel_a;
296
                    ud_b_en <= not irx_channel_a;
297
                  end if;
298
                  -- channel status enable for the capture register
299
                  if bit_cnt = 26 and ilock = '1' then
300
                    cs_a_en <= irx_channel_a;
301
                    cs_b_en <= not irx_channel_a;
302
                  end if;
303
                when LONG =>
304
                  short_idx <= '0';
305
                when others =>
306
                  framerx <= HUNT;
307
              end case;
308
            else
309
              -- there should be 4 pulses in preamble
310
              if pre_cnt < 7 then
311
                pre_cnt <= pre_cnt + 1;
312
              else
313
                rx_error <= '1';
314
                framerx <= HUNT;
315
              end if;
316
              -- check for correct preamble here
317
              if pre_cnt = 3 then
318
                case last_preamble is
319
                  when PRE_X =>
320
                    if new_preamble = PRE_Y then
321
                      framerx <= FRAMESTART;
322
                      irx_channel_a <= '0';
323
                    else
324
                      rx_error <= '1';
325
                      framerx <= HUNT;
326
                    end if;
327
                  when PRE_Y =>
328
                    if new_preamble = PRE_X or new_preamble = PRE_Z then
329
                      irx_channel_a <= '1';
330
                      -- start of new block?
331
                      if new_preamble = PRE_Z then
332
                        rx_block_start <= '1';
333
                      end if;
334
                      framerx <= FRAMESTART;
335
                    else
336
                      rx_error <= '1';
337
                      framerx <= HUNT;
338
                    end if;
339
                  when PRE_Z =>
340
                    if new_preamble = PRE_Y then
341
                      irx_channel_a <= '0';
342
                      framerx <= FRAMESTART;
343
                    else
344
                      rx_error <= '1';
345
                      framerx <= HUNT;
346
                    end if;
347
                  when others =>
348
                    rx_error <= '1';
349
                    framerx <= HUNT;
350
                end case;
351
              end if;
352
            end if;
353
          else
354
            rx_data_en <= '0';
355
            rx_block_start <= '0';
356
            rx_frame_start <= '0';
357
            ud_a_en <= '0';
358
            ud_b_en <= '0';
359
            cs_a_en <= '0';
360
            cs_b_en <= '0';
361
          end if;
362
        when others =>
363
          framerx <= IDLE;
364
      end case;
365
    end if;
366
  end process FRX;
367
 
368
end rtl;

powered by: WebSVN 2.1.0

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