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

Subversion Repositories sd_mmc_emulator

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jclaytons
--------------------------------------------------------------------------
2
-- Package
3
--
4
--
5
 
6
library IEEE;
7
use IEEE.STD_LOGIC_1164.ALL;
8
use IEEE.NUMERIC_STD.ALL;
9
use IEEE.MATH_REAL.ALL;
10
 
11
package signal_conditioning_pack is
12
 
13
  component edge_detector
14
    generic(
15
      DETECT_RISING  : natural;
16
      DETECT_FALLING : natural
17
    );
18
    port (
19
      -- System Clock and Clock Enable
20
      sys_rst_n   : in  std_logic;
21
      sys_clk     : in  std_logic;
22
      sys_clk_en  : in  std_logic;
23
 
24
      -- Input Signal
25
      sig_i       : in  std_logic;
26
 
27
      -- Output pulse
28
      pulse_o     : out std_logic
29
 
30
    );
31
  end component;
32
 
33
  component leaky_integrator
34
    generic(
35
      LEAK_FACTOR_BITS : natural;
36
      LEAK_FACTOR      : natural;
37
      INTEGRATOR_BITS  : natural   -- Bits in the integrating accumulator
38
    );
39
    port (
40
      -- System Clock and Clock Enable
41
      sys_rst_n   : in  std_logic;
42
      sys_clk     : in  std_logic;
43
      sys_clk_en  : in  std_logic;
44
 
45
      -- Settings
46
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
47
 
48
      -- Integration Result
49
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0)
50
 
51
    );
52
  end component;
53
 
54
  component leaky_integrator_with_digital_output
55
    generic(
56
      FACTOR_BITS     : natural;  -- Make this less than INTEGRATOR_BITS
57
      HYSTERESIS_BITS : natural;  -- Make this less than INTEGRATOR_BITS
58
      INTEGRATOR_BITS : natural   -- Bits in the integrating accumulator
59
    );
60
    port (
61
      -- System Clock and Clock Enable
62
      sys_rst_n   : in  std_logic;
63
      sys_clk     : in  std_logic;
64
      sys_clk_en  : in  std_logic;
65
 
66
      -- Settings
67
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
68
      leak_factor : in  signed(FACTOR_BITS-1 downto 0);
69
      hysteresis  : in  unsigned(HYSTERESIS_BITS-1 downto 0);
70
 
71
      -- Integration Result
72
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0);
73
 
74
      -- Conditioned Digital Output Signal
75
      output      : out std_logic
76
    );
77
  end component;
78
 
79
  component multi_stage_leaky_integrator
80
    generic(
81
      STAGES           : natural;
82
      LEAK_FACTOR_BITS : natural;  -- Inversely related to LP corner frequency. (Min=1)
83
      HYSTERESIS_BITS  : natural;  -- Make this less than INTEGRATOR_BITS
84
      INTEGRATOR_BITS  : natural   -- Bits in each integrating accumulator
85
    );
86
    port (
87
      -- System Clock and Clock Enable
88
      sys_rst_n   : in  std_logic;
89
      sys_clk     : in  std_logic;
90
      sys_clk_en  : in  std_logic;
91
 
92
      -- Settings
93
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
94
      hysteresis  : in  unsigned(HYSTERESIS_BITS-1 downto 0);
95
 
96
      -- Final Stage Integration Result
97
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0);
98
 
99
      -- Conditioned Digital Output Signal
100
      output      : out std_logic
101
    );
102
  end component;
103
 
104
  component integrating_pulse_stretcher
105
    generic(
106
      MIN_CLKS        : natural; -- pulses below this many clocks are ignored
107
      RETRIGGERABLE   : natural; -- 1=restart on new pulses.  0=decay to zero before restarting
108
      STRETCH_FACTOR  : natural; -- 0=don't stretch, 1=double, 2=triple
109
      INITIAL_OFFSET  : natural; -- Value initially loaded into integrator
110
      INTEGRATOR_BITS : natural  -- Bits in the integrating accumulator
111
    );
112
    port (
113
      -- System Clock and Clock Enable
114
      sys_rst_n   : in  std_logic;
115
      sys_clk     : in  std_logic;
116
      sys_clk_en  : in  std_logic;
117
 
118
      -- Input
119
      pulse_i     : in  std_logic;
120
 
121
      -- Output
122
      pulse_o     : out std_logic
123
 
124
    );
125
  end component;
126
 
127
end signal_conditioning_pack;
128
 
129
-------------------------------------------------------------------------------
130
-- Edge Detector
131
-------------------------------------------------------------------------------
132
--
133
-- Author: John Clayton
134
-- Date  : Nov.  1, 2013 Started Coding, drawing from various other sources.
135
--                       Created description.  Simulated it and saw that it
136
--                       works.
137
--                 
138
--
139
-- Description
140
-------------------------------------------------------------------------------
141
-- This module is a super simple edge detector, which produces is high-going
142
-- pulse whenever there is an edge on the input.  The type of edge is
143
-- selectable via generic.
144
--
145
-- The sys_clk_en affects the operation by extending the length of the pulse
146
-- output beyond one single sys_clk cycle, as expected.
147
--
148
-- Detecting both rising and falling edges is allowed.  Detecting neither is
149
-- also allowed, but not recommended.
150
--
151
-- The sys_rst_n input is an asynchronous reset.
152
 
153
library IEEE;
154
use IEEE.STD_LOGIC_1164.ALL;
155
use IEEE.NUMERIC_STD.ALL;
156
use IEEE.MATH_REAL.ALL;
157
 
158
library work;
159
use work.convert_pack.all;
160
 
161
  entity edge_detector is
162
    generic(
163
      DETECT_RISING  : natural := 1;
164
      DETECT_FALLING : natural := 0
165
    );
166
    port (
167
      -- System Clock and Clock Enable
168
      sys_rst_n   : in  std_logic;
169
      sys_clk     : in  std_logic;
170
      sys_clk_en  : in  std_logic;
171
 
172
      -- Input Signal
173
      sig_i       : in  std_logic;
174
 
175
      -- Output pulse
176
      pulse_o     : out std_logic
177
 
178
    );
179
  end edge_detector;
180
 
181
architecture beh of edge_detector is
182
 
183
  -- Constants
184
 
185
  -- Functions & associated types
186
 
187
  -- Signal Declarations
188
  signal sig_r1  : std_logic;
189
  signal pulse_r : std_logic;
190
  signal pulse_f : std_logic;
191
  signal pulse_b : std_logic;
192
 
193
begin
194
 
195
process (sys_clk, sys_rst_n)
196
begin
197
  if (sys_rst_n='0') then
198
    sig_r1 <= '0';
199
  elsif (sys_clk'event and sys_clk='1') then -- rising edge
200
    if (sys_clk_en='1') then
201
      sig_r1 <= sig_i;
202
    end if;
203
  end if;
204
end process;
205
 
206
-- The detection
207
pulse_r <= '1' when sig_i='1' and sig_r1='0' else '0';
208
pulse_f <= '1' when sig_i='0' and sig_r1='1' else '0';
209
pulse_b <= sig_i xor sig_r1;
210
 
211
-- The output
212
pulse_o <= pulse_b when DETECT_RISING/=0 and DETECT_FALLING/=0 else
213
           pulse_r when DETECT_RISING/=0 else
214
           pulse_f when DETECT_FALLING/=0 else
215
           '0'; -- Haha!  Don't go there!
216
 
217
end beh;
218
 
219
-------------------------------------------------------------------------------
220
-- Leaky Integrator
221
-------------------------------------------------------------------------------
222
--
223
-- Author: John Clayton
224
-- Date  : Oct. 11, 2013 Started Coding, drawing from various other sources.
225
--                       Created description.  Simulated it and saw that it
226
--                       works.
227
--                 
228
--
229
-- Description
230
-------------------------------------------------------------------------------
231
-- This module is a pretty simple digital "leaky integrator" designed to low
232
-- pass noisy signals by integrating them.
233
--
234
--   The first order differential equation is of the form:
235
--
236
--     dx/dt = -leak_factor*x + input
237
--
238
-- The input is discretized in both time and amplitude.  A one bit digital
239
-- input can be mapped to the "input" signal by using a positive value for
240
-- '1' and a negative value for '0'  Alternately, a signed DSP type signal
241
-- can be used directly.
242
--
243
-- The "leak_factor" is a feedback term, so that "DC gain" is inversely
244
-- proportional to the leak_factor.
245
--
246
-- Due to the presence of the feedback term, the integration's DC value, or
247
-- constant term, gets "leaked" to zero over time.  This is nice because
248
-- the threshold centers around zero.
249
--
250
-- Hysteresis can be added so that the digital output transitions an amount
251
-- above or below zero, depending on the current value of the output.
252
--
253
-- Clear as mud?  Well, it's similar to a low-pass filter, and the hysteresis
254
-- also helps remove noise on the input signal.
255
--
256
-- The sys_rst_n input is an asynchronous reset.
257
 
258
library IEEE;
259
use IEEE.STD_LOGIC_1164.ALL;
260
use IEEE.NUMERIC_STD.ALL;
261
use IEEE.MATH_REAL.ALL;
262
 
263
library work;
264
use work.convert_pack.all;
265
 
266
  entity leaky_integrator is
267
    generic(
268
      LEAK_FACTOR_BITS : natural := 10;
269
      LEAK_FACTOR      : natural := 10;
270
      INTEGRATOR_BITS  : natural := 16   -- Bits in the integrating accumulator
271
    );
272
    port (
273
      -- System Clock and Clock Enable
274
      sys_rst_n   : in  std_logic;
275
      sys_clk     : in  std_logic;
276
      sys_clk_en  : in  std_logic;
277
 
278
      -- Settings
279
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
280
 
281
      -- Integration Result
282
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0)
283
 
284
    );
285
  end leaky_integrator;
286
 
287
architecture beh of leaky_integrator is
288
 
289
  -- Constants
290
 
291
  -- Functions & associated types
292
 
293
  -- Signal Declarations
294
  signal sum     : signed(INTEGRATOR_BITS-1 downto 0);
295
  signal delta   : signed(INTEGRATOR_BITS-1 downto 0);
296
  signal m_term  : signed(INTEGRATOR_BITS+LEAK_FACTOR_BITS downto 0);
297
 
298
begin
299
 
300
-- The feedback term
301
m_term <= sum*to_signed(LEAK_FACTOR,LEAK_FACTOR_BITS+1);
302
 
303
-- The difference term
304
delta  <= input - s_resize_l(m_term,delta'length);
305
 
306
-- The leaky integrator
307
process (sys_clk, sys_rst_n)
308
begin
309
  if (sys_rst_n='0') then
310
    sum <= to_signed(0,integrator'length);
311
  elsif (sys_clk'event and sys_clk='1') then -- rising edge
312
    if (sys_clk_en='1') then
313
      sum <= sum + delta;
314
    end if;
315
  end if;
316
end process;
317
 
318
-- The outputs
319
integrator <= sum;
320
 
321
end beh;
322
 
323
-------------------------------------------------------------------------------
324
-- Leaky Integrator with conditioned Digital Output
325
-------------------------------------------------------------------------------
326
--
327
-- Author: John Clayton
328
-- Date  : Oct. 11, 2013 Started Coding, drawing from various other sources.
329
--                       Created description.  Simulated it and saw that it
330
--                       works.
331
--                 
332
--
333
-- Description
334
-------------------------------------------------------------------------------
335
-- This module is a pretty simple digital "leaky integrator" designed to clean
336
-- up noisy repetitive signals by integrating them, and applying thresholds
337
-- to the integrated result.
338
--
339
--   The first order differential equation is of the form:
340
--
341
--     dx/dt = -leak_factor*x + input
342
--
343
-- The input is discretized in both time and amplitude.  A one bit digital
344
-- input can be mapped to the "input" signal by using a positive value for
345
-- '1' and a negative value for '0'
346
--
347
-- The "leak_factor" is a feedback term, so that "DC gain" is inversely
348
-- proportional to the leak_factor.
349
--
350
-- Due to the presence of the feedback term, the integration's DC value, or
351
-- constant term, gets "leaked" to zero over time.  This is nice because
352
-- the threshold centers around zero.
353
--
354
-- Hysteresis can be added so that the digital output transitions an amount
355
-- above or below zero, depending on the current value of the output.
356
--
357
-- Clear as mud?  Well, it's similar to a low-pass filter, and the hysteresis
358
-- also helps remove noise on the input signal.
359
--
360
-- The sys_rst_n input is an asynchronous reset.
361
 
362
library IEEE;
363
use IEEE.STD_LOGIC_1164.ALL;
364
use IEEE.NUMERIC_STD.ALL;
365
use IEEE.MATH_REAL.ALL;
366
 
367
library work;
368
use work.convert_pack.all;
369
 
370
  entity leaky_integrator_with_digital_output is
371
    generic(
372
      FACTOR_BITS     : natural := 10;  -- Make this less than INTEGRATOR_BITS
373
      HYSTERESIS_BITS : natural := 10;  -- Make this less than INTEGRATOR_BITS
374
      INTEGRATOR_BITS : natural := 16   -- Bits in the integrating accumulator
375
    );
376
    port (
377
      -- System Clock and Clock Enable
378
      sys_rst_n   : in  std_logic;
379
      sys_clk     : in  std_logic;
380
      sys_clk_en  : in  std_logic;
381
 
382
      -- Settings
383
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
384
      leak_factor : in  signed(FACTOR_BITS-1 downto 0);
385
      hysteresis  : in  unsigned(HYSTERESIS_BITS-1 downto 0);
386
 
387
      -- Integration Result
388
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0);
389
 
390
      -- Conditioned Digital Output Signal
391
      output      : out std_logic
392
    );
393
  end leaky_integrator_with_digital_output;
394
 
395
architecture beh of leaky_integrator_with_digital_output is
396
 
397
  -- Constants
398
 
399
  -- Functions & associated types
400
 
401
  -- Signal Declarations
402
  signal sum     : signed(INTEGRATOR_BITS-1 downto 0);
403
  signal delta   : signed(INTEGRATOR_BITS-1 downto 0);
404
  signal m_term  : signed(INTEGRATOR_BITS+FACTOR_BITS-1 downto 0);
405
  signal out_l   : std_logic;
406
  signal hp_term : signed(INTEGRATOR_BITS-1 downto 0);
407
  signal hn_term : signed(INTEGRATOR_BITS-1 downto 0);
408
 
409
begin
410
 
411
-- The feedback term
412
m_term <= sum*leak_factor;
413
 
414
-- The difference term
415
delta  <= input - s_resize_l(m_term,delta'length);
416
 
417
-- The leaky integrator
418
process (sys_clk, sys_rst_n)
419
begin
420
  if (sys_rst_n='0') then
421
    sum <= to_signed(0,integrator'length);
422
    out_l <= '0';
423
  elsif (sys_clk'event and sys_clk='1') then -- rising edge
424
    if (sys_clk_en='1') then
425
      sum <= sum + delta;
426
      if (out_l='0') then
427
        if (sum>hp_term) then
428
          out_l <= '1';
429
        end if;
430
      else
431
        if (sum<hn_term) then
432
          out_l <= '0';
433
        end if;
434
      end if;
435
    end if;
436
  end if;
437
end process;
438
 
439
-- The hysteresis terms
440
hp_term <= signed(u_resize(hysteresis,INTEGRATOR_BITS));
441
hn_term <= not(hp_term)+1;
442
 
443
-- The outputs
444
integrator <= sum;
445
output <= out_l;
446
 
447
end beh;
448
 
449
-------------------------------------------------------------------------------
450
-- Multi Stage Leaky Integrator with Digital Output
451
-------------------------------------------------------------------------------
452
--
453
-- Author: John Clayton
454
-- Date  : Oct. 11, 2013 Started Coding, drawing from various other sources.
455
--                       Created description.
456
--                 
457
--
458
-- Description
459
-------------------------------------------------------------------------------
460
-- This module implements N-stages of leaky integrators.  Each stage has the
461
-- same leak factor, which is a value fixed by generics.  Use powers of two
462
-- to avoid inferring multipliers.  The smallest value of 1 is actually a
463
-- pretty nice choice.  The LEAK_FACTOR_BITS generic determines how small
464
-- the leak factor is by setting the number of bits.  The integer is converted
465
-- as follows:
466
--
467
--   multiplicand = to_signed(LEAK_FACTOR,LEAK_FACTOR_BITS);
468
--
469
--   It seems that the smallest signed number is 2 bits wide - one for a sign
470
--   bit, and the other for magnitude.  So, LEAK_FACTOR_BITS must be >=2.
471
--   Between stages, an arithmetic shift right operation is inserted, which is
472
--   intended to automatically scale the signal to fit the next integrator.
473
--
474
-- The hysteresis value is only applied at the final stage output, to derive
475
-- the conditioned digital output signal.
476
--
477
-- The "leak_factor" is a feedback term, so that "DC gain" is inversely
478
-- proportional to the leak_factor.
479
--
480
-- Due to the presence of the feedback term, the integration's DC value, or
481
-- constant term, gets "leaked" to zero over time.  This is nice because
482
-- the threshold centers around zero.
483
--
484
-- Hysteresis can be added so that the digital output transitions an amount
485
-- above or below zero, depending on the current value of the output.
486
--
487
-- Clear as mud?  Well, it's similar to a low-pass filter, and the hysteresis
488
-- also helps remove noise on the input signal.
489
--
490
-- The more stages are used, the more low-pass filtering occurs.
491
--
492
-- The sys_rst_n input is an asynchronous reset.
493
 
494
library IEEE;
495
use IEEE.STD_LOGIC_1164.ALL;
496
use IEEE.NUMERIC_STD.ALL;
497
use IEEE.MATH_REAL.ALL;
498
 
499
library work;
500
use work.convert_pack.all;
501
use work.signal_conditioning_pack.all;
502
 
503
  entity multi_stage_leaky_integrator is
504
    generic(
505
      STAGES           : natural := 2;
506
      LEAK_FACTOR_BITS : natural := 5;  -- Inversely related to LP corner frequency. (Min=1)
507
      HYSTERESIS_BITS  : natural := 8;  -- Make this less than INTEGRATOR_BITS
508
      INTEGRATOR_BITS  : natural := 16  -- Bits in each integrating accumulator
509
    );
510
    port (
511
      -- System Clock and Clock Enable
512
      sys_rst_n   : in  std_logic;
513
      sys_clk     : in  std_logic;
514
      sys_clk_en  : in  std_logic;
515
 
516
      -- Settings
517
      input       : in  signed(INTEGRATOR_BITS-1 downto 0);
518
      hysteresis  : in  unsigned(HYSTERESIS_BITS-1 downto 0);
519
 
520
      -- Final Stage Integration Result
521
      integrator  : out signed(INTEGRATOR_BITS-1 downto 0);
522
 
523
      -- Conditioned Digital Output Signal
524
      output      : out std_logic
525
    );
526
  end multi_stage_leaky_integrator;
527
 
528
architecture beh of multi_stage_leaky_integrator is
529
 
530
  -- Constants
531
    -- This value has been found to preserve amplitude between stages,
532
    -- without appreciable growth or shrinkage of sum levels.
533
  constant STAGE_ASR   : natural := LEAK_FACTOR_BITS+1;
534
  constant LEAK_FACTOR : natural := 1;
535
 
536
  -- Functions & associated types
537
 
538
  -- Signal Declarations
539
  type sum_type is array (natural range STAGES-1 downto 0) of signed(INTEGRATOR_BITS-1 downto 0);
540
  signal sum_in  : sum_type;
541
  signal sum_out : sum_type;
542
  signal out_l   : std_logic;
543
  signal hp_term : signed(INTEGRATOR_BITS-1 downto 0);
544
  signal hn_term : signed(INTEGRATOR_BITS-1 downto 0);
545
 
546
begin
547
 
548
 
549
----------------------------------------------
550
leaky_gen : for nvar in 0 to STAGES-1 generate
551
begin
552
  lint : leaky_integrator
553
    generic map(
554
      LEAK_FACTOR_BITS => LEAK_FACTOR_BITS,
555
      LEAK_FACTOR      => LEAK_FACTOR,
556
      INTEGRATOR_BITS  => INTEGRATOR_BITS
557
    )
558
    port map(
559
      -- System Clock and Clock Enable
560
      sys_rst_n   => sys_rst_n,
561
      sys_clk     => sys_clk,
562
      sys_clk_en  => sys_clk_en,
563
 
564
      -- Settings
565
      input       => sum_in(nvar),
566
 
567
      -- Integration Result
568
      integrator  => sum_out(nvar)
569
 
570
    );
571
end generate;
572
 
573
sum_in(0) <= input;
574
sum_gen : for nvar in 1 to STAGES-1 generate
575
begin
576
  sum_in(nvar) <= asr_function(sum_out(nvar-1),STAGE_ASR);
577
end generate;
578
 
579
-- The hysteresis and digital output
580
process (sys_clk, sys_rst_n)
581
begin
582
  if (sys_rst_n='0') then
583
    out_l <= '0';
584
  elsif (sys_clk'event and sys_clk='1') then -- rising edge
585
    if (sys_clk_en='1') then
586
      if (out_l='0') then
587
        if (sum_out(STAGES-1)>hp_term) then
588
          out_l <= '1';
589
        end if;
590
      else
591
        if (sum_out(STAGES-1)<hn_term) then
592
          out_l <= '0';
593
        end if;
594
      end if;
595
    end if;
596
  end if;
597
end process;
598
 
599
-- The hysteresis terms
600
hp_term <= signed(u_resize(hysteresis,INTEGRATOR_BITS));
601
hn_term <= not(hp_term)+1;
602
 
603
-- The outputs
604
integrator <= sum_out(STAGES-1);
605
output <= out_l;
606
 
607
end beh;
608
 
609
-------------------------------------------------------------------------------
610
-- Integrating Pulse Stretcher
611
-------------------------------------------------------------------------------
612
--
613
-- Author: John Clayton
614
-- Date  : Oct. 24, 2013 Started Coding, drawing from various other sources.
615
--                       Created description.  Simulated it and saw that it
616
--                       works.
617
--                 
618
--
619
-- Description
620
-------------------------------------------------------------------------------
621
-- This module is a pretty simple digital pulse stretcher.  A high input pulse
622
-- present for more than MIN_CLKS clock cycles causes the INITIAL_OFFSET value
623
-- to be loaded into an accumulator.  The accumulator is then incremented by 
624
-- STRETCH_FACTOR each clock cycle that the input pulse remains high, and is
625
-- decremented by one for each clock cycle that the input pulse is low.
626
--
627
-- The output is driven high whenever the accumulator is positive.
628
--
629
-- The output pulse width is given by:
630
--
631
--   Tpulse_o = STRETCH_FACTOR*(Tpulse_i-MIN_CLKS) + INITIAL_OFFSET
632
--
633
-- The INITIAL_OFFSET can be used to overcome the effects of minimum input
634
-- pulse filtering.  Also, if a negative value is used for it, then the
635
-- output pulse is delayed by additional clock cycles beyond the MIN_CLKS
636
-- of delay already present.  Another use for the INITIAL_OFFSET value is
637
-- to "bridge together" a train of pulses which might have some jitter.
638
-- The INITIAL_OFFSET value allows for some slop of jitter to be covered
639
-- by the extra decay time, so that no "gaps" appear in the output pulse.
640
--
641
-- During the decay time, when the output is high, the arrival of a new pulse
642
-- will cause further charging of the accumulator.  There is no minimum pulse
643
-- width for this to occur.  The MIN_CLKS only applies to starting the unit
644
-- from a quiescent state.
645
--
646
-- The integrator is a signed quantity, so set INTEGRATOR_BITS accordingly,
647
-- because the integrator can only hold positive quantities up to
648
-- 2^(INTEGRATOR_BITS-1)-1.
649
--
650
-- The sys_rst_n input is an asynchronous reset.
651
 
652
library IEEE;
653
use IEEE.STD_LOGIC_1164.ALL;
654
use IEEE.NUMERIC_STD.ALL;
655
use IEEE.MATH_REAL.ALL;
656
 
657
library work;
658
use work.convert_pack.all;
659
 
660
  entity integrating_pulse_stretcher is
661
    generic(
662
      MIN_CLKS        : natural :=  5; -- pulses below this many clocks are ignored
663
      RETRIGGERABLE   : natural :=  1; -- 1=restart on new pulses.  0=decay to zero before restarting
664
      STRETCH_FACTOR  : natural :=  2; -- 0=no output, 1=same size, 2=double
665
      INITIAL_OFFSET  : natural := 25; -- Value initially loaded into integrator
666
      INTEGRATOR_BITS : natural := 16  -- Bits in the integrating accumulator
667
    );
668
    port (
669
      -- System Clock and Clock Enable
670
      sys_rst_n   : in  std_logic;
671
      sys_clk     : in  std_logic;
672
      sys_clk_en  : in  std_logic;
673
 
674
      -- Input
675
      pulse_i     : in  std_logic;
676
 
677
      -- Output
678
      pulse_o     : out std_logic
679
 
680
    );
681
  end integrating_pulse_stretcher;
682
 
683
architecture beh of integrating_pulse_stretcher is
684
 
685
  -- Constants
686
  constant RUNT_BITS : natural := timer_width(MIN_CLKS);
687
 
688
  -- Functions & associated types
689
 
690
  -- Signal Declarations
691
  signal runt_count : unsigned(RUNT_BITS-1 downto 0);
692
  signal sum        : signed(INTEGRATOR_BITS-1 downto 0);
693
  signal pulse_i_r1 : std_logic;
694
  signal pulse_l    : std_logic;
695
 
696
begin
697
 
698
-- The integrator
699
process (sys_clk, sys_rst_n)
700
begin
701
  if (sys_rst_n='0') then
702
    runt_count <= to_unsigned(0,runt_count'length);
703
    sum        <= to_signed(0,sum'length);
704
    pulse_i_r1 <= '0';
705
  elsif (sys_clk'event and sys_clk='1') then -- rising edge
706
    if (sys_clk_en='1') then
707
      -- Detect rising edge of input pulse
708
      pulse_i_r1 <= pulse_i;
709
      -- When the pulse_i input is consecutively high, decrement the runt
710
      -- counter until it is zero.
711
      if (runt_count>0) then
712
        if (pulse_i='1') then
713
          runt_count <= runt_count-1;
714
        else
715
          runt_count <= to_unsigned(MIN_CLKS,runt_count'length);
716
        end if;
717
      end if;
718
      -- Trigger on rising edge of pulse_i
719
      if (pulse_i='1' and pulse_i_r1='0') then
720
        if (pulse_l='0' or (RETRIGGERABLE=1 and pulse_l='1')) then
721
          runt_count <= to_unsigned(MIN_CLKS,runt_count'length);
722
        end if;
723
      end if;
724
      -- Load initial offset into accumulator on final runt countdown
725
      if (runt_count=1) then
726
        sum <= to_signed(INITIAL_OFFSET,sum'length);
727
      end if;
728
      -- Either accumulate or decay, depending on input state
729
      if (pulse_i='1' and runt_count=0) then
730
        sum <= sum+STRETCH_FACTOR;
731
      elsif (pulse_i='0' and pulse_l='1') then
732
        sum <= sum-1;
733
      end if;
734
    end if;
735
  end if;
736
end process;
737
 
738
-- The output
739
pulse_l <= '1' when (sum>0) else '0';
740
pulse_o <= pulse_l;
741
 
742
end beh;
743
 

powered by: WebSVN 2.1.0

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