http://fractional-divider.tripod.com/ 1 --------------------------------------------------------------------------------
2 --
File : fracn20.vhd
3 -- Contains :
entity fracn20 (
architecture rtl)
4 --
Author : Allan Herriman
5 -- Date : Tue Dec
24 2002
6 -- Version :
2.0.
0
7 -- Complain
to : fractional_divider@hotmail.com
8 -- License : (
read below)
9 --
10 -- This
file contains synthesisable VHDL
for a fixed ratio frequency divider.
11 --
12 -- The
output frequency
is a rational multiple
of the
input
13 -- frequency
in the form:
14 --
15 -- (a +
b)
16 -- ----------------------- *
Fin
17 -- (a * n) + (b * (n +
1))
18 --
19 -- where a, b,
and n are integers.
20 -- The dual modulus prescaler divides the
input clock by n
or (n+
1).
21 -- The controller causes the prescaler
to divide by n
for a cycles
of the
22 --
output,
and divide by (n+
1)
for b cycles
of the
output.
23 -- The controller consists
of a state machine that produces the best
24 -- interleaving
of the a
and b cycles,
25 -- which gives the minimum possible amount
of jitter.
26 -- The peak
to peak
output jitter will be <= one period
of the
input clock.
27 --
28 -- Here
is a
block diagram:
29 --
30 -- +--------------+
31 -- | Dual modulus |
'prescaler_out'
32 --
'clock'---->| Prescaler |------+--------->
33 -- | /n
or /(n+
1) | |
34 -- +--------------+ |
35 -- ^ |
36 -- | +------------+
37 -- | | |
38 -- +-------| Controller |
39 --
'modulus_control' | |
40 -- +------------+
41 --
42 --
43 --
The generics:
44 -- input_frequency - set this
to the
input clock frequency
in Hz
45 -- output_frequency - set this
to the desired
output frequency
in Hz
46 -- tolerance - set this
to the allowable relative tolerance
47 --
on the
output frequency. The default value
48 --
of 1.0e-7 should be adequate
for most purposes.
49 -- VHDL guarantees only about
15 digits
of precision,
50 -- so tolerances < 1e-
15 don
't make much sense.
51 -- Don
't make tolerance exactly zero, as
52 --
floating point precision problems may cause an
53 -- infinite
loop.
54 --
55 -- Note: the output_50
output has a (nominally)
50%
duty cycle.
56 -- This
output will only be valid
if output_frequency <
0.5 *
input_frequency
57 --
58 --
Revisions:
59 --
2.0.
0 Dec
24 2002 Initial revision.
60 -- (Starting at
2.0.
0,
to distinguish it from earlier VHDL-
generating
61 --
Perl scripts.)
62 --
63 --
License:
64 -- This source code (
and accompanying test bench
and scripts) are released
65 -- under the terms
of the BSD license.
66 -- http:
//www.opensource.org/licenses/bsd-license.html
67 --
68 -- Copyright (c)
2003, Allan Herriman
69 --
All rights reserved.
70 --
71 -- Redistribution
and use in source
and binary forms,
with or without
72 --
modification, are permitted provided that the following conditions
73 --
are met:
74 --
75 -- Redistributions
of source code must retain the above copyright
76 -- notice, this list
of conditions
and the following disclaimer.
77 -- Redistributions
in binary form must reproduce the above copyright
78 -- notice, this list
of conditions
and the following disclaimer
in
79 -- the documentation
and/
or other materials provided
with the
80 --
distribution.
81 -- The name
of Allan Herriman may
not be used
to endorse
or promote
82 --
products derived from this software without specific prior
83 --
written permission.
84 --
85 -- THIS SOFTWARE
IS PROVIDED BY THE COPYRIGHT HOLDERS
AND CONTRIBUTORS
86 --
"AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
87 -- LIMITED
TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY
AND FITNESS
FOR
88 -- A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT
89 -- OWNER
OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL,
90 -- SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
91 -- LIMITED
TO, PROCUREMENT
OF SUBSTITUTE GOODS
OR SERVICES; LOSS
OF USE,
92 -- DATA,
OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
93 -- THEORY
OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY,
OR TORT
94 -- (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING
IN ANY WAY
OUT OF THE
USE
95 --
OF THIS SOFTWARE, EVEN
IF ADVISED
OF THE POSSIBILITY
OF SUCH DAMAGE.
96 --
97 --
98 --
99 --
BUGS:
100 -- This code
is a straightforward translation
of the perl script fracn09.pl
101 --
to VHDL. Please see fracn09.pl
for a list
of bugs.
102 -- http:
//fractional_divider.tripod.com/fracn09.zip
103 --
104 --
Simulation Status:
105 -- It should work fine
in any VHDL
'93 or '00 LRM compliant simulator.
106 -- Seems
to work fine
in recent versions
of Modelsim
and Simili.
107 -- It wouldn
't compile in Scirocco Version 2006.6-6.
108 --
109 -- Synthesis Status (Jan
'03):
110 -- It should work find
in any reasonable VHDL
'93 or '00 synthesiser,
111 -- as only basic RTL code has been used. (Some tools may
object to
112 -- the
assert statements though. If this
is the
case, those statements
113 -- may be removed without changing the
function of the code.)
114 --
115 -- Seems
to work fine
in:
116 -- - LeonardoSpectrum 2002e build
16 (other versions may be ok, but
117 -- haven
't been tested)
118 -- - Synplify Pro
7.3.
0 and later
119 --
120 -- Doesn
't work in:
121 -- - Synplify Pro prior
to version
7.3.
0
122 -- -
Any synthesis tool from Synopsys.
123 -- - Any
of the low cost, FPGA vendor supplied tools (e.g. XST, MAXPLUS2).
124 --
125 --
Common tool problems:
126 -- - Can
't handle VHDL '93 syntax.
127 -- - Can
't handle generics of type real.
128 -- - They think that
function f_prescaler_params contains an
129 -- infinite
loop.
130 -- -
Fails an internal assertion.
131 -- - Incorrect calculation
of "longest static prefix" of signal stageout
132 --
causing multiple drivers.
133 -- - Doesn
't correctly interpret the LRM rules regarding initial values
134 --
on ports
135 --
136 -- If your particular toolset doesn
't work with this code,
137 --
please consider instead using fracn09.pl available at
138 -- http:
//fractional_divider.tripod.com/
139 --------------------------------------------------------------------------------
140
141 library ieee;
142 use ieee.std_logic_1164.
all;
143
144 entity fracn20
is
145 generic (
146 input_frequency :
real; -- :=
1.0e6; -- frequency
of clock (Hz)
147 output_frequency :
real; -- :=
32768.0; -- desired frequency
of output (Hz)
148 tolerance :
real :=
1.0e-7;
149 improve_duty_cycle :
boolean :=
FALSE; --
TRUE uses a falling edge ff
to make the output_50 duty cycle closer
to 50%
150 suppress_report :
boolean :=
TRUE
151 );
152 port (
153 async_reset :
in std_logic :=
'0'; --
active high reset
154 clock :
in std_logic; --
input clock
155 clock_enable :
in std_logic :=
'1'; --
active high clock enable
156 output_50 :
out std_logic; --
output - approx
50%
duty cycle
157 output_pulse :
out std_logic --
output - high
for single clock per cycle
158 );
159 end entity fracn20;
160
161 architecture rtl
of fracn20
is
162
163 constant desired_ratio :
real := (input_frequency /
output_frequency);
164 constant min_ratio :
real := (input_frequency / (output_frequency * (
1.0 +
tolerance)));
165 constant max_ratio :
real := (input_frequency / (output_frequency * (
1.0 -
tolerance)));
166
167 pure function max (x, y :
integer)
return integer is
168 begin
169 if x > y
then
170 return x;
171 else
172 return y;
173 end if;
174 end max;
175
176 pure function floor_to_natural (x :
real)
return natural
is
177 variable result : natural;
178 begin
179 result :=
integer(x);
180 if real(result) > x
then
181 result := result -
1;
182 end if;
183 return result;
184 end floor_to_natural;
185
186 pure function ceil_to_natural (x :
real)
return natural
is
187 variable result : natural;
188 begin
189 result :=
integer(x);
190 if real(result) < x
then
191 result := result +
1;
192 end if;
193 return result;
194 end ceil_to_natural;
195
196 -- get the
integer upper
and lower bounds
197 constant floor_max_ratio :
positive :=
floor_to_natural(max_ratio);
198 constant floor_min_ratio :
positive := max(floor_to_natural(min_ratio),
1);
199 constant ceil_min_ratio :
positive :=
ceil_to_natural(min_ratio);
200
201
202 -- work
out the frequency division needed
in the dual modulus prescaler
203 pure function choose_n
return integer is
204 variable n :
positive;
205 begin
206 n :=
floor_min_ratio;
207
208 -- check
to see
if a straight
integer divider will do
209 if floor_max_ratio >= ceil_min_ratio
then
210 --
warning(
"Warning: a fractional-N divider is not needed.");
211 if floor_max_ratio > ceil_min_ratio
then
212 --
warning(
" Integer dividers $ceil_min_ratio to $floor_max_ratio are ok.");
213 n :=
floor_max_ratio;
214 else
215 --
warning(
" Integer divider $floor_max_ratio is ok.");
216 n :=
floor_max_ratio;
217 end if;
218 end if;
219 return n;
220 end choose_n;
221
222 -- prescaler divides by n, n+
1
223 constant n :
positive :=
choose_n;
224
225
226 type t_prescaler_params
is record
227 a : natural;
228 b : natural;
229 fout_achieved :
real;
230 error_achieved :
real;
231 end record t_prescaler_params;
232
233
234 -- Find smallest non-negative integers a
and b such that
235 --
236 -- Fout (a +
b)
237 -- ---- = -----------------------
238 -- Fin (a * n) + (b * (n +
1))
239 --
240 --
(within the prescribed tolerance).
241 --
242 -- Note: I also tried a continued PFE based
on Euclid
's GCD algorithm.
243 -- It used fewer iterations, but didn
't always find the smallest
244 -- a
and b, so was rejected.
245 pure function f_prescaler_params
return t_prescaler_params
is
246 variable a : natural;
247 variable b : natural;
248 variable result : t_prescaler_params;
249 variable ratio :
real;
250 variable dummy_count : natural :=
2_000_000_000;
251 attribute syn_looplimit :
integer; -- Needed
for Synplify
7.3 to work
252 attribute syn_looplimit
of bigloop :
label is 10_000_000;
253 begin
254 a :=
1; -- number
of /
n cycles
255 b :=
0; -- number
of /(n+
1) cycles
256
257 bigloop :
while dummy_count >
0 loop -- test prevents spurious
"infinite loop" errors from LeonardoSpectrum
258
259 ratio :=
real(a * n + b * (n +
1))/
real(a +
b);
260
261 if ratio < min_ratio
then
262 --
too small
263 b := b +
1;
264 next;
265 end if;
266 if ratio > max_ratio
then
267 --
too big
268 a := a +
1;
269 next;
270 end if;
271 -- just
right
272 exit;
273 dummy_count := dummy_count -
1; --
never executed
274 end loop;
275
276 result.a :=
a;
277 result.b :=
b;
278 result.fout_achieved := input_frequency/ratio; --
Hz
279 result.error_achieved := result.fout_achieved - output_frequency; --
Hz
280
281 return result;
282 end f_prescaler_params;
283
284 constant prescaler_params : t_prescaler_params :=
f_prescaler_params;
285
286 constant relative_error :
real := prescaler_params.error_achieved /
output_frequency;
287
288
289 --
prescaler signals
290 signal modulus_control :
std_logic;
291 signal prescaler_count :
integer range 0 to n;
292 signal prescaler_out :
std_logic;
293 signal prescaler_out_50 :
std_logic;
294 signal duty_correction :
std_logic;
295
296
297 -- controller signals
and constants
298 constant max_stages :
positive :=
20;
299
300 type t_integer_array
is array (natural
range <>)
of integer;
301
302 type t_stage
is record
303 n : natural; -- this stage divides by n (
or n+
1)
304 m : natural; -- Controls duty cycle
of modulus control
output from this stage.
305 a : natural; -- This stage requires its modulus control
input to be low
for this number
of cycles
306 b : natural; -- This stage requires its modulus control
input to be high
for this number
of cycles
307 i :
std_logic; -- Invert the
output of this stage
308 end record t_stage;
309
310 type t_stage_array
is array (natural
range <>)
of t_stage;
311
312 pure function f_controller_params
return t_stage_array
is
313 variable stage : natural :=
0;
314 variable stage_array : t_stage_array(max_stages
downto 0);
315 variable n1 : natural;
316 variable a1 : natural;
317 variable b1 : natural;
318 variable n2 : natural;
319 variable m2 : natural;
320 variable a2 : natural;
321 variable b2 : natural;
322 variable i2 :
std_logic;
323 variable determinant :
integer;
324 begin
325 stage_array(stage).n :=
n;
326 stage_array(stage).a :=
prescaler_params.a;
327 stage_array(stage).b :=
prescaler_params.b;
328
329 while (stage_array(stage).b >
1 and stage_array(stage).a >
1)
loop
330 n1 :=
stage_array(stage).n;
331 a1 :=
stage_array(stage).a;
332 b1 :=
stage_array(stage).b;
333 assert n1 >=
0 and a1 >=
0 and b1 >=
0;
334 if a1 < b1
then
335 i2 :=
'1';
336 n2 := (a1 + b1) /
a1;
337 m2 := (a1 + b1 -
1) /
a1;
338 determinant := n2 - m2 +
1;
339 assert determinant /=
0;
340 a2 := (m2 * a1 - (n2 +
1 - m2) * b1) /
determinant;
341 b2 := ((
1 - m2) * a1 + (n2 +
1 - m2) * b1) /
determinant;
342 else
343 i2 :=
'0';
344 n2 := (a1 + b1) /
b1;
345 m2 := (a1 + b1 -
1)/
b1;
346 determinant := (m2 - n2 -
1);
347 assert determinant /=
0;
348 a2 := ((n2 +
1 - m2) * a1 - m2 * b1) /
determinant;
349 b2 := ((m2 - n2 -
1) * a1 + (m2 -
1) * b1) /
determinant;
350 end if;
351 stage := stage +
1;
352 stage_array(stage).n :=
n2;
353 stage_array(stage).m :=
m2;
354 stage_array(stage).a :=
a2;
355 stage_array(stage).b :=
b2;
356 stage_array(stage).i :=
i2;
357 end loop;
358
359 -- fill
in the parameters
for the last (non-
fractional) stage
360 stage := stage +
1;
361 stage_array(stage).n := stage_array(stage -
1).a + stage_array(stage -
1).b -
1;
362 stage_array(stage).m := stage_array(stage -
1).a;
363 stage_array(stage).i :=
'0';
364
365 return stage_array(stage
downto 0);
366
367 end f_controller_params;
368
369
370 constant stage_array : t_stage_array :=
f_controller_params;
371
372 constant stages : natural := stage_array
'high;
373
374 signal count : t_integer_array(stages
downto 1);
375 signal carry :
std_logic_vector(stages
downto 0);
376 signal stageout :
std_logic_vector(stages +
1 downto 1) := (
others =>
'W'); -- initial value works around bug
in Modelsim versions prior
to 5.7b
377
378 --
function to work
out the modulus needed
for each counter stage
379 -- (otherwise each stage will be a
32 bit counter, which
380 -- still gives the correct results, but
is wasteful
of logic)
381 pure function makemod(x : natural)
return integer is
382 variable log :
integer :=
0;
383 variable my_count :
integer :=
x;
384 begin
385 while my_count >
0 loop
386 log := log +
1;
387 my_count := my_count /
2;
388 end loop;
389 return 2 **
log;
390 end function makemod;
391
392 begin --
architecture rtl
393
394 -- print some
of the constants,
for debugging
395 assert suppress_report
396 report
397 "n = " &
integer'image(n) &
398 " a = " &
integer'image(prescaler_params.a) &
399 " b = " &
integer'image(prescaler_params.b) &
400 " fout_achieved = " &
real'image(prescaler_params.fout_achieved) &
401 " error_achieved = " &
real'image(prescaler_params.error_achieved) & " (Hz) " &
402 real'image(relative_error) & " (rel)" &
403 " stages = " &
integer'image(stages)
404 severity note;
405
406
407 -- check some
of the constants
408 assert input_frequency >
0.0 severity failure;
409 assert output_frequency >
0.0 severity failure;
410 assert input_frequency >= output_frequency
severity failure;
411 assert tolerance <
1.0 and tolerance >=
0.0 severity failure;
412
413 assert abs(relative_error) <= tolerance
report "out of tolerance" severity error;
414
415
416 --------------------------------------------------------------------------------
417 -- Prescaler. Divides by either n
or n +
1
418 -- depending
on whether the
signal "modulus_control" is '0' or '1'.
419 -- Note: the
"terminal count" is fixed,
and the load value
is
420 -- varied,
to give smaller, faster logic (?
)
421 --------------------------------------------------------------------------------
422 prescaler :
process (async_reset, clock)
423 begin
424 if async_reset =
'1' then
425 prescaler_count <=
0;
426 prescaler_out_50 <=
'0';
427 elsif
rising_edge(clock)
then
428 if clock_enable =
'1' then
429 --
manage counter
430 if prescaler_count < n
then
431 prescaler_count <= prescaler_count +
1;
432 else
433 if modulus_control =
'0' then
434 prescaler_count <=
1;
435 else
436 prescaler_count <=
0;
437 end if;
438 end if;
439 --
decode counter
440 if prescaler_count <= n/
2 then
441 prescaler_out_50 <=
'0';
442 else
443 prescaler_out_50 <=
'1';
444 end if;
445 end if;
446 end if;
447 end process prescaler;
448
449 decode_prescaler_out :
if n >
1 generate
450 decoder :
process (async_reset, clock)
451 begin
452 if async_reset =
'1' then
453 prescaler_out <=
'0';
454 elsif
rising_edge(clock)
then
455 if clock_enable =
'1' then
456 if prescaler_count < n
then
457 prescaler_out <=
'0';
458 else
459 prescaler_out <=
'1';
460 end if;
461 end if;
462 end if;
463 end process decoder;
464 end generate decode_prescaler_out;
465
466 no_decode_prescaler_out :
if n <=
1 generate
467 prescaler_out <=
'0' when prescaler_count =
0 else '1';
468 end generate no_decode_prescaler_out;
469
470 output_pulse <=
prescaler_out;
471
472
473 --------------------------------------------------------------------------------
474 --
Duty cycle improvement using falling edge flip flop.
475 --------------------------------------------------------------------------------
476 duty_cycle_improver :
if improve_duty_cycle
generate
477 improver :
process (async_reset, clock)
478 begin
479 if async_reset =
'1' then
480 duty_correction <=
'0';
481 elsif
falling_edge(clock)
then
482 if clock_enable =
'1' then
483 duty_correction <= prescaler_out_50
and modulus_control;
484 end if;
485 end if;
486 end process improver;
487
488 output_50 <= duty_correction
or prescaler_out_50;
489
490 end generate duty_cycle_improver;
491
492 no_duty_cycle_improver :
if not improve_duty_cycle
generate
493 output_50 <=
prescaler_out_50;
494 end generate no_duty_cycle_improver;
495
496 -- trash output_50
when it will
not be useful
497 trash_output_50 :
if input_frequency <=
2.0 * output_frequency
generate
498 output_50 <=
'X';
499 end generate trash_output_50;
500
501
502 --------------------------------------------------------------------------------
503 --
recursive controller
504 -- The modulus control
signal for the prescaler can be generated by another
505 -- fractional-N divider, which
in turn can have its modulus control
signal
506 -- generated by yet another fractional-N divider,
and so
on.
507 -- We stop
when we don
't need another fractional-N divider, and can just use
508 --
a fixed divider.
509 -- The particular arrangement we
use also produces the smallest possible jitter.
510 -- The stagecount
and stageout signals have been initialised
to non-
zero
511 -- values
to improve the jitter measurements during simulation. This
is not
512 -- needed
for synthesis,
and these values should be set
to zero
if this
513 --
improves synthesis results.
514 --
515 -- count will increment between
0 and stage_array(stage).n
or
516 --
1 and stage_array(stage).n, depending
on output of the
next stage.
517 --------------------------------------------------------------------------------
518 controllers :
for stage
in 1 to stages
generate
519 constant countmask : natural :=
makemod(stage_array(stage).n);
520 begin
521 controller :
process (async_reset, clock)
522 begin
523 if async_reset =
'1' then
524 count(stage) <=
stage_array(stage).n;
525 carry(stage) <=
'0';
526 stageout(stage) <=
stage_array(stage).i;
527 elsif
rising_edge(clock)
then
528 if clock_enable =
'1' then
529 if carry(stage -
1) =
'1' then
530 if count(stage) < stage_array(stage).n
then
531 count(stage) <= (count(stage) +
1)
mod countmask;
532 carry(stage) <=
'0';
533 else
534 if stageout(stage +
1) =
'0' then
535 count(stage) <=
1;
536 else
537 count(stage) <=
0;
538 end if;
539 carry(stage) <=
'1';
540 end if;
541 if count(stage) < stage_array(stage).m
then
542 stageout(stage) <=
stage_array(stage).i;
543 else
544 stageout(stage) <=
not stage_array(stage).i;
545 end if;
546 else
547 carry(stage) <=
'0';
548 end if;
549 end if;
550 end if;
551 end process controller;
552 end generate controllers;
553
554 modulus_control <= stageout(
1);
555
556 carry(
0) <=
prescaler_out;
557
558 stageout(stages +
1) <=
'1'; -- last stage
is a fixed modulus divider
559
560 end architecture rtl; --
of entity fracn20
561 --------------------------------------------------------------------------------
562 -- <EOF>
fracn20.vhd
563 --------------------------------------------------------------------------------
转载于:https://www.cnblogs.com/shangdawei/archive/2012/05/10/2494851.html