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

Subversion Repositories auto_baud

[/] [auto_baud/] [trunk/] [auto_baud_pack.vhd] - Blame information for rev 7

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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