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

Subversion Repositories spdif_interface

[/] [spdif_interface/] [tags/] [spdif_rel_1/] [rtl/] [vhdl/] [rx_phase_det.vhd] - Blame information for rev 73

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

powered by: WebSVN 2.1.0

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