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 --------------------------------------------------------------------------------