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

Subversion Repositories sd_mmc_emulator

[/] [sd_mmc_emulator/] [trunk/] [rtl/] [auto_baud_pack.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jclaytons
--------------------------------------------------------------------------
2
-- Package of auto_baud components
3
--
4
-- Contains the following components:
5
--
6
--   auto_baud_with_tracking
7
--
8
 
9
library IEEE;
10
use IEEE.STD_LOGIC_1164.ALL;
11
use IEEE.NUMERIC_STD.ALL;
12
 
13
package auto_baud_pack is
14
 
15
  component auto_baud_with_tracking
16
    generic (
17
      CLOCK_FACTOR    : natural; -- Output is this factor times the baud rate
18
      FPGA_CLKRATE    : real;    -- FPGA system clock rate
19
      MIN_BAUDRATE    : real;    -- Minimum expected incoming Baud rate
20
      DELTA_THRESHOLD : integer  -- Max. number of sys_clks difference allowed between
21
                                 -- "half_measurement" and "measurement"
22
    );
23
    port (
24
 
25
      sys_rst_n    : in  std_logic;
26
      sys_clk      : in  std_logic;
27
      sys_clk_en   : in  std_logic;
28
 
29
      -- rate and parity
30
      rx_parity_i  : in  unsigned(1 downto 0); -- 0=none, 1=even, 2=odd
31
 
32
      -- serial input
33
      rx_stream_i  : in  std_logic;
34
 
35
      -- Output
36
      baud_lock_o  : out std_logic;
37
      baud_clk_o   : out std_logic
38
    );
39
  end component;
40
 
41
end auto_baud_pack;
42
 
43
package body auto_baud_pack is
44
end auto_baud_pack;
45
 
46
-------------------------------------------------------------------------------
47
-- Auto Baud with tracking core
48
-------------------------------------------------------------------------------
49
--
50
-- Author: John Clayton
51
-- Date  : Aug. 20, 2002 Began project
52
-- Update: Sep.  5, 2002 copied this file from "autobaud.v"
53
--                       Added tracking functions, and debugged them.
54
-- Update: Sep. 13, 2002 Added test data.  Module complete, it works well.
55
-- Update: Nov. 20, 2009 Began translation into VHDL
56
-- Update: Mar. 22, 2012 After much successful use of this core in VHDL,
57
--                       decided to add sys_clk_en input.
58
-- Update: July  2, 2012 I was astounded to find a "false positive" reading
59
--                       from this module during a simulation, and added the
60
--                       "edge count" counter to help eliminate such cases,
61
--                       in which two zero bits can get interpreted as a
62
--                       single start bit, and somehow, amazingly, the rest
63
--                       of the bits following this also match the expected
64
--                       values.  In these cases, the edge count will not
65
--                       match, and the measurement will be discarded.
66
-- Update: Dec. 13, 2012 Changed SYS_CLK_RATE and MIN_BAUD_RATE from integer
67
--                       to real values.
68
-- Update: Jul. 29, 2015 Added second synchronization flip flop to mitigate
69
--                       metastability issues with rx_stream_i.
70
--
71
-- Description
72
-------------------------------------------------------------------------------
73
-- This is a state-machine driven core that measures transition intervals
74
-- in a particular character arriving via rs232 transmission (i.e. PC serial 
75
-- port.)  Measurements of time intervals between transitions in the received
76
-- character are then used to generate a baud rate clock for use in serial
77
-- communications back and forth with the device that originally transmitted
78
-- the measured character.  The clock which is generated is in reality a
79
-- clock enable pulse, one single clock wide, occurring at a rate suitable
80
-- for use in serial communications.  (This means that it will be generated
81
-- at 4x or 8x or 16x the actual measured baud rate of the received character.
82
-- The multiplication factor is called "CLOCK_FACTOR" and is a settable
83
-- parameter within this module.  The parameter "CLOCK_FACTOR" need not
84
-- be a power of two, but it should be a number between 2 and 16 inclusive.)
85
--
86
-- The particular character which is targeted for measurement and verification
87
-- in this module is: carriage return (CR) = 0x0d = 13.
88
-- This particular character was chosen because it is frequently used at the
89
-- end of a command line, as entered at a keyboard by a human user interacting
90
-- with a command interpreter.  It is anticipated that the user would press
91
-- the "enter" key once upon initializing communications with the electronic
92
-- device, and the resulting carriage return character would be used for 
93
-- determining BAUD rate, thus allowing the device to respond at the correct
94
-- rate, and to carry on further communications.  The electronic device using
95
-- this "auto_baud" module adjusts its baud rate to match the baud rate of
96
-- the received data.  This works for all baud rates, within certain limits,
97
-- and for all system clock rates, within certain limits.
98
--
99
-- Received serially, and with no parity bit, the carriage return appears as
100
-- the following waveform:
101
-- ________    __    ____          _______________
102
--         |__|d0|__|d2d3|________|stop
103
--        start   d1      d4d5d6d7
104
--
105
-- The waveform is shown with an identical "high" time and "low" time for
106
-- each bit.  However, actual measurements taken using a logic analyzer
107
-- on characters received from a PC show that the times are not equal.
108
-- The "high" times turned out shorter, and the "low" times longer...
109
-- Therefore, this module attempts to average out this discrepancy by
110
-- measuring one low time and one high time.
111
--
112
-- Since the transition measurements must unavoidably contain small amounts
113
-- of error, the measurements are made during the beginning 2 bits of
114
-- the received character, (that is, start bit and data bit zero).
115
-- Then the measurement is immediately transformed into a baud rate clock,
116
-- used to verify correct reception of the remaining 8 bits of the character.
117
-- If the entire character is not received correctly using the generated
118
-- baud rate, then the measurement is scrapped, and the unit goes into an
119
-- idle scanning mode waiting for another character to test.
120
--
121
-- This effectively filters out characters that the unit is not interested in
122
-- receiving (anything that is not a carriage return.)  There is a slight
123
-- possibility that a group of other characters could appear by random
124
-- chance in a configuration that resembles a carriage return closely enough
125
-- that the unit might accept the measurement and produce a baud clock too
126
-- low.  But the probability of this happening is remote enough that the
127
-- unit is considered highly "robust" in normal use, especially when used
128
-- for command entry by humans.  It would take a very clever user indeed, to
129
-- enter the correct series of characters with the correct intercharacter
130
-- timing needed to possibly "fool" the unit!
131
--
132
-- (Also, the baud rate produced falls within certain limits imposed by
133
--  the hardware of the unit, which prevents the auto_baud unit from mistaking
134
--  a series of short glitches on the serial data line for a really
135
--  fast CR character.)
136
--
137
-- This method of operation implies that each carriage return character
138
-- received will produce a correctly generated baud rate clock.  Therefore,
139
-- each and every carriage return actually causes a new baud rate clock to
140
-- be produced.  However, updates occur smoothly, and there should be no
141
-- apparent effect as an old BAUD clock is stopped and a new one started.
142
-- The transition is done smoothly.
143
--
144
-- For users who desire a single measurement at the beginning of a session
145
-- to produce a steady baud clock during the entire session, there is a
146
-- slightly smaller module called "auto_baud.v" which performs a single
147
-- measurement, but which requires a reset pulse in order to begin measuring
148
-- for a new BAUD rate.
149
--
150
-- NOTES:
151
-- - This module uses a counter to divide down the sys_clk signal to produce the
152
--   baud_clk_o signal.  Since the frequency of baud_clk_o is nominally
153
--   CLOCK_FACTOR * rx_baud_rate, where "rx_baud_rate" is the baud rate
154
--   of the received character, then the higher you make CLOCK_FACTOR, the
155
--   higher the generated baud_clk_o signal frequency, and hence the lower the
156
--   resolution of the divider.  Therefore, using a lower value for the
157
--   CLOCK_FACTOR will allow you to use a lower sys_clk with this module.
158
-- - The lower the minimum baud rate setting, the larger the counters will be.
159
--   This is so that the counters can accomodate the large count values needed
160
--   to divide the system clock into the low Baud rate output.
161
--
162
-- - If the percentage error for your highest desired baud rate is greater
163
--   than a few percent, you might want to use a higher Fsys_clk or else a 
164
--   lower CLOCK_FACTOR.
165
--
166
-- Note: Simply changing the template bits does not reconfigure the
167
--       module to look for a different character (because a new measurement
168
--       window might have to be defined for a different character...)
169
--       The template bits are the exact bits used during verify, against
170
--       which the incoming character is checked.
171
--       The LSB of the character is not used for verification, since it is
172
--       actually used in the measurement.
173
--
174
 
175
 
176
library IEEE;
177
use IEEE.STD_LOGIC_1164.ALL;
178
use IEEE.NUMERIC_STD.ALL;
179
use IEEE.MATH_REAL.ALL;
180
 
181
library work;
182
use work.convert_pack.all;
183
 
184
entity auto_baud_with_tracking is
185
    generic (
186
      CLOCK_FACTOR    : natural := 16;        -- Output is this factor times the baud rate
187
      FPGA_CLKRATE    : real := 25000000.0;   -- FPGA system clock rate
188
      MIN_BAUDRATE    : real := 57600.0;      -- Minimum expected incoming Baud rate
189
      DELTA_THRESHOLD : integer := 6          -- Max. number of sys_clks difference allowed between
190
                                              -- "half_measurement" and "measurement"
191
    );
192
    port (
193
 
194
      sys_rst_n    : in  std_logic;
195
      sys_clk      : in  std_logic;
196
      sys_clk_en   : in  std_logic;
197
 
198
      -- rate and parity
199
      rx_parity_i  : in  unsigned(1 downto 0); -- 0=none, 1=even, 2=odd
200
 
201
      -- serial input
202
      rx_stream_i  : in  std_logic;
203
 
204
      -- Output
205
      baud_lock_o  : out std_logic;
206
      baud_clk_o   : out std_logic
207
    );
208
end auto_baud_with_tracking;
209
 
210
architecture beh of auto_baud_with_tracking is
211
 
212
-- Constants
213
constant TEMPLATE_BITS    : unsigned(7 downto 0) := "00001101";  -- Carriage return
214
constant MAIN_COUNT_WIDTH : integer := timer_width(FPGA_CLKRATE/MIN_BAUDRATE); -- Bit Width of timer.
215
 
216
-- Internal signal declarations
217
  -- State Machine
218
type FSM_STATE_TYPE is (IDLE, MEASURE_START_BIT, MEASURE_DATA_BIT, VERIFY);
219
signal fsm_state        : FSM_STATE_TYPE;
220
 
221
signal baud_lock        : std_logic; -- When high, indicates output can operate.
222
signal char_mismatch    : std_logic; -- Indicates character did not verify
223
signal baud_count       : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- BAUD counter register
224
signal baud_div         : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- measurement for running
225
signal measurement      : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- measurement for verify
226
signal half_check       : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- Half of measurement
227
signal half_measurement : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- measurement at end of start bit
228
signal delta            : unsigned(MAIN_COUNT_WIDTH-1 downto 0); -- Difference value
229
signal target_bits      : unsigned(8 downto 0); -- Character bits to compare
230
signal target_bit_count : unsigned(3 downto 0); -- Contains count of bits remaining to check
231
signal parity           : std_logic; -- The "template bit" for checking the received parity bit.
232
signal edge_count       : unsigned(3 downto 0);
233
signal edge             : std_logic;
234
signal rx_stream_r1     : std_logic;
235
signal rx_stream_r2     : std_logic;
236
 
237
----------------------------------------------------------------------------
238
-- Functions
239
----------------------------------------------------------------------------
240
  function gen_even_parity(in_a : unsigned) return std_logic is
241
  variable i : natural;
242
  variable o : std_logic;
243
 
244
  begin
245
 
246
  o := '0'; -- Default value
247
  for i in 0 to in_a'length-1 loop
248
    o := o xor in_a(i);
249
  end loop;
250
 
251
  return(o);
252
 
253
  end;
254
 
255
-----------------------------------------------------------------------------
256
begin
257
 
258
parity <= '1' when (rx_parity_i="00") else
259
          gen_even_parity(TEMPLATE_BITS) when (rx_parity_i="01") else
260
          not gen_even_parity(TEMPLATE_BITS) when (rx_parity_i="10") else
261
          '1';
262
-- Form a difference between the measurement and twice the "half-measurement"
263
-- Take the absolute value.
264
half_check <= '0' & measurement(MAIN_COUNT_WIDTH-1 downto 1);
265
delta <= (half_check-half_measurement) when (half_check>half_measurement) else
266
         (half_measurement-half_check);
267
 
268
-- This is state machine.  It checks the status of the rx_stream_i line
269
-- and coordinates the measurement of the time interval of the first two
270
-- bits of the received character, which is the "measurement interval."
271
-- Following the measurement interval, the state machine enters a new
272
-- phase of bit verification.  If the measured time interval is accurate
273
-- enough to measure the remaining 8 or 9 bits of the character correctly, then
274
-- the measurement is accepted, and the baud rate clock is driven onto
275
-- the baud_clk_o output pin.  Incidentally, the process of verification
276
-- effectively filters out characters which are not the desired target
277
-- character for measurement.  In this case, the target character is the
278
-- carriage return.
279
 
280
fsm_proc: process(sys_clk, sys_rst_n, parity)
281
begin
282
  if (sys_rst_n='0') then
283
    fsm_state        <= IDLE;   -- asynchronous reset
284
    baud_clk_o       <= '0';
285
    baud_lock        <= '0';
286
    char_mismatch    <= '0';
287
    baud_count       <= (others=>'0');
288
    half_measurement <= (others=>'0'); -- The measurement at the end of the start bit
289
    measurement      <= (others=>'0'); -- The candidate divider value.
290
    baud_div         <= (others=>'0'); -- The "running" copy of measurement
291
    target_bits      <= '1' & parity & TEMPLATE_BITS(7 downto 1);
292
    target_bit_count <= (others=>'0');
293
    edge_count       <= (others=>'0');
294
    rx_stream_r1     <= '1';
295
    rx_stream_r2     <= '1';
296
  elsif (sys_clk'event and sys_clk='1') then
297
    if (sys_clk_en='1') then
298
 
299
      -- Store previous stream sample, for edge detection
300
      rx_stream_r1 <= rx_stream_i;
301
      rx_stream_r2 <= rx_stream_r1;
302
 
303
      -- Handle the baud clock output generation, if we have achieved "baud_lock"
304
      if (baud_lock='1') then
305
        if (baud_count + 2*CLOCK_FACTOR > baud_div) then
306
          baud_count <= to_unsigned(CLOCK_FACTOR,baud_count'length);
307
            -- baud_count <= baud_count + to_unsigned(CLOCK_FACTOR,baud_count'length) - baud_div; 
308
            -- (Compromised above for simplicity)
309
            -- (It could have been baud_count+CLOCK_FACTOR-baud_div)
310
          baud_clk_o <= '1';
311
        else
312
          baud_count   <= baud_count + 2*CLOCK_FACTOR;
313
          baud_clk_o   <= '0';
314
        end if;
315
      end if;
316
 
317
      case (fsm_state) is
318
 
319
        when IDLE =>
320
          char_mismatch    <= '0';
321
          measurement      <= (others=>'0');
322
          half_measurement <= (others=>'0');
323
          target_bits      <= '1' & parity & TEMPLATE_BITS(7 downto 1);
324
          if (rx_parity_i=0) then
325
            target_bit_count <= to_unsigned(8,target_bit_count'length);
326
          else
327
            target_bit_count <= to_unsigned(9,target_bit_count'length); -- ODD/EVEN parity means extra bit.
328
          end if;
329
          if (rx_stream_r1 = '0') then
330
            fsm_state <= MEASURE_START_BIT;
331
          end if;
332
 
333
        when MEASURE_START_BIT =>
334
          if (rx_stream_r1 = '1') then
335
            half_measurement <= measurement;
336
            fsm_state        <= MEASURE_DATA_BIT;
337
          else
338
            measurement <= measurement+1;
339
          end if;
340
 
341
        when MEASURE_DATA_BIT =>
342
          -- The duration of the data bit must not be significantly different
343
          -- than the duration of the start bit...
344
          measurement <= measurement+1;
345
          edge_count  <= (others=>'0');
346
          if (rx_stream_r1='0') then  -- Look for the end of the least significant data bit.
347
            if (delta>DELTA_THRESHOLD) then
348
              fsm_state <= IDLE;
349
            else
350
              fsm_state <= VERIFY;
351
            end if;
352
          end if;
353
 
354
        when VERIFY =>  -- Wait for verify operations to finish
355
          if (edge='1') then
356
            edge_count <= edge_count+1;
357
          end if;
358
          if (target_bit_count=0) then -- At the stop bit, check the status
359
            if (char_mismatch='0' and edge_count=3) then
360
              baud_div  <= measurement; -- Store final verified measurement for running
361
              baud_lock <= '1';
362
            end if;
363
            if (rx_stream_r1='1') then -- Only return when there is a chance of making a valid new measurement...
364
              fsm_state <= IDLE; -- Whether successful, or not, return to IDLE ("autotracking" feature.)
365
            end if;
366
          else
367
            if (half_measurement>=measurement) then -- Initial setting leads to near mid-bit sampling.
368
              half_measurement <= (others=>'0');
369
              target_bits <= '0' & target_bits(target_bits'length-1 downto 1);
370
              target_bit_count <= target_bit_count-1;
371
              if (target_bits(0)/=rx_stream_r1) then
372
                char_mismatch <= '1';
373
              end if;
374
            else
375
              half_measurement <= half_measurement+2;
376
            end if;
377
          end if;
378
 
379
        --when others => 
380
        --  fsm_state <= IDLE;
381
      end case;
382
 
383
    end if; -- sys_clk_en
384
  end if; -- sys_clk
385
end process;
386
 
387
edge <= rx_stream_r2 xor rx_stream_r1;
388
 
389
baud_lock_o <= baud_lock;
390
 
391
 
392
end beh;
393
 

powered by: WebSVN 2.1.0

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