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

powered by: WebSVN 2.1.0

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