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

Subversion Repositories aes3rx

[/] [aes3rx/] [trunk/] [rtl/] [vhdl/] [aes3rx.vhd] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 nohous
-------------------------------------------------------------------------------
2
-- AES3 / SPDIF Minimalistic Receiver
3
-- Version 0.9
4
-- Petr Nohavica (c) 2009
5
-- Released under GNU Lesser General Public License
6
-- Original target device: Xilinx Spartan-3AN family
7
-------------------------------------------------------------------------------
8 8 nohous
 
9
library IEEE;
10
use IEEE.STD_LOGIC_1164.ALL;
11
use IEEE.STD_LOGIC_ARITH.ALL;
12
use IEEE.STD_LOGIC_UNSIGNED.ALL;
13
 
14
entity aes3rx is
15
   generic (
16 10 nohous
      -- Registers width, determines minimal baud speed of input AES3 at given master clock frequency
17
      reg_width : integer := 5
18 8 nohous
   );
19
   port (
20 10 nohous
      -- Master clock
21
      clk   : in  std_logic;
22
      -- AES3/SPDIF compatible input signal
23
      aes3  : in  std_logic;
24
      -- Synchronous reset
25
      reset : in  std_logic;
26
      -- Serial data out
27 8 nohous
      sdata : out std_logic := '0'; -- output serial data
28 10 nohous
      -- AES3 clock out
29 8 nohous
      sclk  : out std_logic := '0'; -- output serial data clock
30 10 nohous
      -- Block start (asserted when Z subframe is being transmitted)
31
      bsync : out std_logic := '0';
32
      -- Frame sync (asserted for channel A, negated for B)
33
      lrck  : out std_logic := '0';
34
      -- Receiver has (probably) valid data on its outputs
35
      active: out std_logic := '0'
36 8 nohous
   );
37
end aes3rx;
38
 
39
architecture Behavioral of aes3rx is
40 10 nohous
   -- Locking state machine states enum type
41
   type lock_state_type is (locking, confirming, locked);
42
   -- Constants for preamble detection
43
   constant X_PREAMBLE     : std_logic_vector(7 downto 0) := "01000111";
44
   constant Y_PREAMBLE     : std_logic_vector(7 downto 0) := "00100111";
45
   constant Z_PREAMBLE     : std_logic_vector(7 downto 0) := "00010111";
46
   -- Input shift register for handling metastability issues and delaying input
47
   signal aes3_sync        : std_logic_vector(3 downto 0) := (others => '0');
48
   -- Change signal, active high on input transition
49
   signal change           : std_logic := '0';
50
   -- Recovered AES3 clock, stream of pulses
51
   signal aes3_clk         : std_logic := '0';
52
   -- Shift register for preamble detection and data decoding
53
   signal decoder_shift    : std_logic_vector(7 downto 0) := (others => '0');
54
   -- 1 bit counter used for correct decoder_shift alignment for data decoder
55
   signal align_counter    : std_logic := '0';
56
   -- Counter for AES3 clk regeneration
57
   signal clk_counter      : std_logic_vector(reg_width - 1 downto 0) := (others => '0');
58
   -- Counts aes3_clk pulses per frame (for locking reasons)
59
   signal sync_cnt         : std_logic_vector(5 downto 0) := (others => '0');
60
   -- Period register for clk_counter
61
   signal reg_clk_period   : std_logic_vector(reg_width - 1 downto 0) := (others => '1');
62
   -- Asserted when locking state machine is not in locked state
63 9 nohous
   signal sync_lost        : std_logic := '1';
64 10 nohous
   -- Asserted when preamble has been detected
65 9 nohous
   signal preamble_detected: std_logic := '0';
66 10 nohous
   -- Internal version of bsync signal
67
   signal bsync_int        : std_logic := '0';
68
   -- Internal version of lrck signal
69
   signal lrck_int         : std_logic := '0';
70
   -- Internal version of sdata signal
71
   signal sdata_int        : std_logic := '0';
72
   -- State of locking state machine
73
   signal lock_state       : lock_state_type := locking;
74
   -- Next state of locking state machine
75
   signal lock_state_next  : lock_state_type;
76
   -- Signal indicating some error in received AES3, used primarily by locking state machine
77
   signal lock_error       : std_logic;
78
   -- Asserted when sync_cnt is full (i.e. it has value of 63)
79
   signal sync_cnt_full    : std_logic;
80
   -- Asserted when there was at least one aes3_clk pulse since last input transition
81
   signal aes3_clk_activity: std_logic := '0';
82
   -- Signals indicating detection of X, Y and Z preambles
83
   signal x_detected       : std_logic := '0';
84
   signal y_detected       : std_logic := '0';
85
   signal z_detected       : std_logic := '0';
86 8 nohous
begin
87
 
88 10 nohous
   -- Carries out input double sampling in order to avoid metastable states on FFs and creation 
89
   -- of delayed signals for change detector (1 clk period) and decoder (2 clk periods).
90 8 nohous
   input_shift_reg_proc: process (clk)
91
   begin
92
      if clk'event and clk = '1' then
93
         if reset = '1' then
94
            aes3_sync <= (others => '0');
95
         else
96
            aes3_sync <= aes3 & aes3_sync(3 downto 1); -- synthetizes  shift reg
97
         end if;
98
      end if;
99
   end process;
100
 
101 10 nohous
   -- Detects edge on sampled input in the way of comparsion of delayed input and its current 
102
   -- state on XOR gate.
103 8 nohous
   change_detect_proc: process (clk)
104
   begin
105
      if clk'event and clk = '1' then
106
         if reset = '1' then
107
            change <= '0';
108
         else
109 10 nohous
            change <= aes3_sync(2) xor aes3_sync(1);
110
         end if;
111
      end if;
112
   end process;
113
 
114
   -- Counts number of aes3_clk pulses since last preamble detection, used by locking state machine
115
   sync_cnt_proc: process (clk)
116
   begin
117
      if clk'event and clk ='1' then
118
         if reset = '1' then
119
            sync_cnt <= (others => '0');
120
         elsif aes3_clk = '1' then
121
            if preamble_detected = '1' then
122
               sync_cnt <= (others => '0');
123
            else
124
               sync_cnt <= sync_cnt + 1;
125 8 nohous
            end if;
126
         end if;
127
      end if;
128 9 nohous
   end process;
129 10 nohous
 
130
   -- Comparator driving sync_cnt_full signal
131
   sync_cnt_comp: process(sync_cnt)
132 8 nohous
   begin
133 10 nohous
      if sync_cnt = 63 then
134
         sync_cnt_full <= '1';
135
      else
136
         sync_cnt_full <= '0';
137
      end if;
138
   end process;
139
 
140
   -- Lock error occurs when sync_cnt is full and no preamble has been detected (i.e. when the
141
   -- aes3_clk pulse generation speed is too high) or preamble is detected and sync_cnt is not full
142
   -- (when aes3_clk pulse rate is too low) or when since last input transition there was no 
143
   -- aes3_clk pulse at all (value of reg_clk_period is a way too high)
144
   lock_error <= (sync_cnt_full and not preamble_detected) or
145
                 (not sync_cnt_full and preamble_detected) or
146
                 (change and not aes3_clk_activity);
147
 
148
   -- Counter holding aes3_clk period duration. The receiver tries to receive a valid frame using 
149
   -- counter's (which is initially all ones) output, if it fails, counter is enabled to lower its
150
   -- value by one (counter is also enabled when aes3_clk_activity is low on input transition -
151
   -- which indicates that value of reg_clk_period is way too high and no aes3_clk pulses are being
152
   -- generated) and this new value is tried. This process is repeated until lock is not acquired. 
153
   -- This solution consumes less logic than direct measurement of shortest AES3 symbol and is actually
154
   -- more reliable. Lock time is fast enough (will always be under 2**(reg_width + 1) frames, but very
155
   -- likely much faster thanks to initial rapid speed of counting which is given by no activity on
156
   -- aes3_clk signal).
157
   aes3_clk_period_proc: process(clk)
158
   begin
159 8 nohous
      if clk'event and clk = '1' then
160
         if reset = '1' then
161 9 nohous
            reg_clk_period <= (others => '1');
162 10 nohous
         elsif (lock_state = locked and lock_state_next = locking) then
163
            reg_clk_period <= (others => '1');
164
         elsif (aes3_clk = '1' and sync_cnt_full = '1' and lock_state_next = locking) or
165
               (change = '1' and aes3_clk_activity = '0') then
166
            reg_clk_period <= reg_clk_period - 1;
167
         end if;
168
      end if;
169
   end process;
170
 
171
   -- Locking state machine. While initialized in locking state, waits for preamble_detection - once one
172
   -- has been detected, state machine is transitioned to confirming state. When no locking error 
173
   -- occurs during one next frame, receiver is considered locked and state accordingly changes. Otherwise
174
   -- the state machine falls back to locking state.
175
   lock_state_machine: process (lock_state, preamble_detected, sync_cnt_full,
176
                                lock_error)
177
   begin
178
      case lock_state is
179
         when locking =>
180 9 nohous
            if preamble_detected = '1' then
181 10 nohous
               lock_state_next <= confirming;
182
            else
183
               lock_state_next <= locking;
184 8 nohous
            end if;
185 10 nohous
         when confirming =>
186
            if lock_error = '1' then
187
               lock_state_next <= locking;
188
            elsif sync_cnt_full = '1' and preamble_detected = '1' then
189
               lock_state_next <= locked;
190
            else
191
               lock_state_next <= confirming;
192
            end if;
193
         when locked =>
194
            if lock_error = '1' then
195
               lock_state_next <= locking;
196
            else
197
               lock_state_next <= locked;
198
            end if;
199
      end case;
200
   end process;
201
 
202
   -- When state of locking state machine is other than locked, sync_lost signal is asserted.
203
   sync_lost_proc: process (lock_state)
204
   begin
205
      if lock_state = locked then
206
         sync_lost <= '0';
207
      else
208
         sync_lost <= '1';
209
      end if;
210
   end process;
211
 
212
   -- Synchronization process for locking state machine
213
   lock_state_machinine_sync_proc: process (clk)
214
   begin
215
      if clk'event and clk = '1' then
216
         if reset = '1' then
217
            lock_state <= locking;
218
         elsif aes3_clk = '1' or (change = '1' and aes3_clk_activity = '0') then
219
            lock_state <= lock_state_next;
220 8 nohous
         end if;
221
      end if;
222
   end process;
223 9 nohous
 
224 10 nohous
   -- Counter for aes3_clk generation. On input transition, counter is loaded with approx. half
225
   -- of reg_clk_period, which should create 90 degrees phase shift of regenerated clock in respect
226
   -- to delayed input and thus ensure that input will be sampled in approximate middle of 1UI symbol
227
   -- (or in the middle of one half of 2UI symbol or in the middle of one third of 3UI symbol).
228
   -- Otherwise, when no transition has been detected on input and clk_counter counts to zero, full 
229
   -- reg_clk_period is loaded into the counter to create aes3_clk pulses when 2UI and 3UI symbols are 
230
   -- being received.
231
   aes3_clk_cnt_proc: process (clk)
232 8 nohous
   begin
233
      if clk'event and clk = '1' then
234
         if reset = '1' then
235 9 nohous
            clk_counter <= (others => '0');
236 10 nohous
         elsif change = '1' or clk_counter = 0 then
237
            if change = '1' then
238
               clk_counter <= '0' & reg_clk_period(reg_width - 1 downto 1);
239
            else
240
               clk_counter <= reg_clk_period;
241
            end if;
242 9 nohous
         else
243
            clk_counter <= clk_counter - 1;
244 10 nohous
         end if;
245
      end if;
246
   end process;
247
 
248
   -- Generates aes3_clk pulse when clk_counter counts to zero.
249
   process (clk)
250
   begin
251
      if clk'event and clk = '1' then
252
         if reset = '1' then
253 9 nohous
            aes3_clk <= '0';
254 10 nohous
         else
255
            if clk_counter = 0 then
256
               aes3_clk <= '1';
257
            else
258
               aes3_clk <= '0';
259
            end if;
260
         end if;
261
      end if;
262
   end process;
263
 
264
   -- Monitors activity on aes3_clk
265
   process (clk)
266
   begin
267
      if clk'event and clk = '1' then
268
         if reset = '1' then
269
            aes3_clk_activity <= '0';
270
         else
271 9 nohous
            if change = '1' then
272 10 nohous
               aes3_clk_activity <= '0';
273 9 nohous
            elsif clk_counter = 0 then
274 10 nohous
               aes3_clk_activity <= '1';
275 8 nohous
            end if;
276
         end if;
277
      end if;
278
   end process;
279 9 nohous
 
280 10 nohous
   -- Eight bit shift register for preamble detection and decoder functionality.
281 8 nohous
   decoder_shift_reg_proc: process (clk)
282
   begin
283
      if clk'event and clk = '1' then
284
         if reset = '1' then
285
            decoder_shift <= (others => '0');
286
         elsif aes3_clk = '1' then
287
            decoder_shift <= aes3_sync(0) & decoder_shift(7  downto 1);
288
         end if;
289
      end if;
290 9 nohous
   end process;
291 10 nohous
 
292
   -- Preamble detectors (implemented using comparators)
293
   x_preamble_detector: process(decoder_shift)
294
   begin
295
      if decoder_shift = X_PREAMBLE or decoder_shift = not X_PREAMBLE then
296
         x_detected <= '1';
297
      else
298
         x_detected <= '0';
299
      end if;
300
   end process;
301 9 nohous
 
302 10 nohous
   y_preamble_detector: process(decoder_shift)
303 8 nohous
   begin
304 10 nohous
      if decoder_shift = Y_PREAMBLE or decoder_shift = not Y_PREAMBLE then
305
         y_detected <= '1';
306
      else
307
         y_detected <= '0';
308
      end if;
309
   end process;
310
 
311
   z_preamble_detector: process(decoder_shift)
312
   begin
313
      if decoder_shift = Z_PREAMBLE or decoder_shift = not Z_PREAMBLE then
314
         z_detected <= '1';
315
      else
316
         z_detected <= '0';
317
      end if;
318
   end process;
319
 
320
   preamble_detected <= x_detected or y_detected or z_detected;
321
 
322
   -- One bit counter used for correct bit alignment on bit decoder. Align_counter is reset on 
323
   -- preamble detection and thus allows decoder to be correctly aligned with sampled symbol beginning.
324
   align_cnt_proc: process(clk)
325
   begin
326 9 nohous
      if clk'event and clk = '1' then
327
         if reset = '1' then
328
            align_counter <= '0';
329 10 nohous
         elsif aes3_clk = '1' then
330
            if preamble_detected = '1' then
331
               align_counter <= '0';
332
            else
333 8 nohous
               align_counter <= not align_counter;
334
            end if;
335
         end if;
336
      end if;
337
   end process;
338
 
339 10 nohous
   -- Drives lrck and bsync signals
340
   frame_block_sync_proc: process (clk)
341
   begin
342
      if clk'event and clk = '1' then
343
         if aes3_clk = '1' and preamble_detected = '1' then
344
            lrck_int <= x_detected or z_detected;
345
            bsync_int <= z_detected;
346
         end if;
347
      end if;
348 11 nohous
   end process;
349
 
350 10 nohous
   -- Two consecutive sampled symbols, when equal, are considered as logical 0. Two consecutive sampled 
351
   -- symbols, when differs, are considered as logical 1. This logical value is then shifted into 
352
   -- data_shift_reg.
353
   data_shift_reg_proc: process (clk)
354
   begin
355
      if clk'event and clk = '1' then
356
         if aes3_clk = '1' and align_counter = '1' then
357
            sdata_int <= decoder_shift(1) xor decoder_shift(0);
358
         end if;
359
      end if;
360
   end process;
361
 
362
   -- Synchronization and activity signals outputs
363 9 nohous
   activity_eval_proc: process (clk)
364
   begin
365
      if clk'event and clk = '1' then
366
         active <= not sync_lost;
367 10 nohous
         lrck <= lrck_int and not sync_lost;
368
         bsync <= bsync_int and not sync_lost;
369 9 nohous
         sclk <= align_counter and not sync_lost;
370
         sdata <= sdata_int and not sync_lost;
371
      end if;
372
   end process;
373 8 nohous
end Behavioral;
374
 

powered by: WebSVN 2.1.0

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