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

Subversion Repositories p9813_rgb_led_string_driver

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

powered by: WebSVN 2.1.0

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