📄 fracn09.pl
字号:
$i_array[$stage + 1] = 0;# work out how many ff are used.$ff_count_recursive_controller = 0;for (my $s = 1; $s <= $stage + 1; $s++) { $ff_count_recursive_controller++; # for stageN_output retime $ff_count_recursive_controller++; # for stageN_carry retime $ff_count_recursive_controller += (ceil(log($n_array[$s] + 1) / log(2))); # counter}$ff_count_recursive_controller--; # no carry from last stage!############### Design the phase accumulator ###################################print "designing phase accumulator\n" if ($verbose);use vars qw($num_bits $c $ratio_pa $fout_achieved_pa $error_achieved_pa); # more global variables$num_bits = 0;while (1){ $num_bits++; $c = floor(0.5 + ((2 ** $num_bits) / $desired_ratio)); next if ($c == 0); $ratio_pa = (2 ** $num_bits) / $c; last if (($ratio_pa <= $max_ratio) and ($ratio_pa >= $min_ratio)); # ok #last if ($c > (2 ** 30)); # avoid overflowing integers in VHDL last if (($num_bits > 56) and $convergence_check); # exceeding Perl floating point accuracy!}$fout_achieved_pa = $fin / $ratio_pa; # Hz$error_achieved_pa = $fout_achieved_pa - $fout; # Hzif (abs($error_achieved_pa / $fout) > $tolerance) { warning("Warning: Phase accumulator design did not meet frequency tolerance target.");}############### Check for Fout > 1/2 Fin ######################################## If the output frequency is > 1/2 the input frequency, the 50% duty# cycle output doesn't make sense, so we need to detect this special case.# We also disable for >= 1/2, to get around code generation problem in# phase accumulator jitter improver.use vars qw($gen_50_percent_output); # more global variables#$gen_50_percent_output = ($fin/$fout >= 2);#$gen_50_percent_output = (($c <= (2 ** ($num_bits - 1))) and ($n > 1));$gen_50_percent_output = (($c < (2 ** ($num_bits - 1))) and ($n > 1)); # ver 07if (not $gen_50_percent_output) { warning("Warning: Fin/Fout ratio < 2.", " The 50% duty cycle output \"output_50\" has not been implemented.");}#$gen_50_percent_output = 1; # use this to test test bench.############### generate some VHDL and Verilog ################################## open vhdl fileprint "opening $vhdl_name\n" if ($verbose);rename $vhdl_name, "$vhdl_name.bak";open (VHDL, ">$vhdl_name") or die "Can't open VHDL file $vhdl_name: $!";# open verilog fileprint "opening $verilog_name\n" if ($verbose);rename $verilog_name, "$verilog_name.bak";open (VERILOG, ">$verilog_name") or die "Can't open Verilog file $verilog_name: $!";# subs for optionally expanding tabs to spaces before writing to files# (the "expand" sub uses the value of the global variable "tabstop")sub vhdl { foreach my $line (@_) { print VHDL ($tabstop > 0) ? expand($line) : $line; }}sub verilog { foreach my $line (@_) { print VERILOG ($tabstop > 0) ? expand($line) : $line; }}# write a comment to both filessub comment{ foreach my $line (@_) { if ( $line =~ m/^(\t+)(.*)$/s ) { # indented comment, maintain leading tabs vhdl $1 . "--" . $2; verilog $1 . "//" . $2; } else { # comment at left margin vhdl "--" . $line; verilog "//" . $line; } }}# write a solid "separator" line to both filessub comment_line{ vhdl "-" x 80 . "\n"; verilog "/" x 80 . "\n";}# returns "unsigned" or "std_logic_vector" depending on whether we# are using IEEE.numeric_std or Synopsys std_logic_unsigned library.sub unsigned { return ($std_logic_unsigned ? "std_logic_vector" : "unsigned");}# Work out whether a word is plural (returns "" or "s", depending on whether# the numeric argument is equal to 1)sub plural { return ($_[0] == 1 ? "" : "s");}# function that returns the number of bits needed to hold integer range 0 to argsub log2{ use integer; my $result = 0; my $count = $_[0]; while ($count > 0) { $result = $result + 1; $count = $count / 2; } no integer; return $result;}print "writing to $vhdl_name and $verilog_name\n" if ($verbose);# write file headercomment_line;vhdl "-- File : $vhdl_name (machine generated)\n";vhdl "-- Contains : entity $entity_name (architecture $architecture_name)\n";verilog "// File : $verilog_name (machine generated)\n";verilog "// Contains : module $entity_name\n";comment " Author : $0 (version $version)\n";comment " Command Line : $0 @argv_orginal\n";comment " Date : " . (scalar localtime) . "\n";comment " Complain to : fractional_divider\@hotmail.com\n";comment "\n";vhdl "-- This machine generated VHDL file contains a fixed ratio frequency divider.\n";verilog "// This machine generated Verilog file contains a fixed ratio frequency divider.\n";comment " Different styles of dividers can be selected by generics or parameters.\n";comment "\n";comment " use_phase_accumulator = TRUE selects a \"classic\" phase accumulator\n";comment " frequency divider\n";comment "\n";comment " use_phase_accumulator = FALSE selects a frequency divider made up of\n";comment " a dual modulus prescaler and a controller\n";comment " In this case, the generics \"minimum_jitter\"\n";comment " and \"use_recursive_controller\"\n";comment " control size / jitter tradeoffs in\n";comment " the controller.\n";comment "\n";comment " The phase accumulator style divider has a regular structure (in the sense\n";comment " that it doesn't change much if the ratio is changed - which is good for\n";comment " floorplanning) and it is quite easy to understand.\n";comment " The output frequency is a rational multiple of the input frequency in\n";comment " the form:\n";comment "\n";comment " c\n";comment " --------------- * Fin\n";comment " (2 ** num_bits)\n";comment "\n";comment " where c and num_bits are integers.\n";comment " The hardware consists of a constant adder, so it will be simple to\n";comment " make it work at high speed.\n";comment " The output jitter will generally be equal to or just less than one\n";comment " cycle of the input clock.\n";comment " Here is a block diagram:\n";comment " \n";comment " 'clock'-----------------------+\n";comment " |\n";comment " +-------+ +----------+\n";comment " Constant--->| | | |\n";comment " 'c' | Adder |--->| Register |-+-->'phase'\n";comment " +->| | | | |\n";comment " | +-------+ +----------+ |\n";comment " | |\n";comment " +----------------------------+\n";comment "\n";comment " The MSB of the 'phase' signal has approximately a 50% duty cycle, and\n";comment " is retimed (in another ff not shown) and used as the 'output_50' output.\n";comment " The carry output of the adder will be high once every output cycle,\n";comment " and is registered (in another ff not shown) and used as the\n";comment " 'output_pulse' output.\n";comment "\n";comment "\n";comment " The dual modulus prescaler divider is somewhat harder to understand, but\n";comment " it may result in less hardware, and it may enable the exact ratio to\n";comment " be produced.\n";comment " In this case, the output frequency is a rational multiple of the input\n";comment " frequency in the form:\n";comment "\n";comment " (a + b)\n";comment " ----------------------- * Fin\n";comment " (a * n) + (b * (n + 1))\n";comment "\n";comment " where a, b, and n are integers.\n";comment " The dual modulus prescaler divides the input clock by n or (n+1).\n";comment " The controller causes the prescaler to divide by n for a cycles of the\n";comment " output, and divide by (n+1) for b cycles of the output.\n";comment " Depending on how these a and b cycles are mixed up, the output\n";comment " jitter will vary.\n";comment " There are a number of ways to make the controller.\n";comment " If the generic use_recursive_controller is TRUE, the controller consists\n";comment " of a state machine that produces the best interleaving of the a and b cycles,\n";comment " which gives about the same jitter as the phase accumulator.\n";comment " If use_recursive_controller is FALSE, the controller consists of a counter\n";comment " and a lookup table to interleave the a and b cycles.\n";comment " There are more tradeoffs: if the generic minimum_jitter is FALSE, the lookup\n";comment " table bunches all the a cycles together, and all the b cycles together.\n";comment " This results in simple hardware, but may produce lots of jitter.\n";comment " If the generic minimum_jitter is TRUE, the lookup table produces the best\n";comment " interleaving of the a and b cycles, but it may result in an excessively\n";comment " large case statement.\n";comment " (It will usually be possible to come up with a much better\n";comment " controller design by hand, but the details vary so much with\n";comment " the choice of frequencies that it is hard to generalise this\n";comment " into a simple script.)\n";if (not $low_jitter_controller) { comment " Note: the minimum_jitter controller has not been implemented in this file,\n"; comment " so don't set the generic minimum_jitter to TRUE.\n";}comment " Here is a block diagram:\n";comment "\n";comment " +--------------+\n";comment " | Dual modulus | 'prescaler_out'\n";comment " 'clock'---->| Prescaler |------+--------->\n";comment " | /n or /(n+1) | |\n";comment " +--------------+ |\n";comment " ^ |\n";comment " | +------------+\n";comment " | | |\n";comment " +-------| Controller |\n";comment " 'modulus_control' | |\n";comment " +------------+\n";comment "\n";comment "\n";comment " For a given set of input to output frequency ratio and tolerance,\n";comment " the only way to work out which type of divider is better is\n";comment " to try them! Generally, the phase accumulator is better for\n";comment " loose tolerances (> 10ppm), and the dual modulus prescaler is\n";comment " better if the ratio must be exact, but this depends on the ratio.\n";comment "\n";comment " Frequency Parameters:\n";comment " Input Frequency: $fin Hz.\n";comment " Desired Output Frequency: $fout Hz.\n";comment " Requested Relative Frequency Error Bounds (+/-) : $tolerance (" . ($tolerance * 1e6) . " ppm)\n";comment "\n";comment " Frequency Results (use_phase_accumulator = FALSE) :\n";comment " Achieved Output Frequency: $fout_achieved Hz.\n";comment " Achieved Relative Frequency Error: " . ($error_achieved / $fout) . " (" . (($error_achieved / $fout) * 1e6) . " ppm)\n";comment " Achieved Frequency Error: $error_achieved Hz.\n";comment "\n";comment " Frequency Results (use_phase_accumulator = TRUE) :\n";comment " Achieved Output Frequency: $fout_achieved_pa Hz.\n";comment " Achieved Relative Frequency Error: " . ($error_achieved_pa / $fout) . " (" . (($error_achieved_pa / $fout) * 1e6) . " ppm)\n";comment " Achieved Frequency Error: $error_achieved_pa Hz.\n";comment "\n";comment " Output Jitter Parameters (use_phase_accumulator = FALSE) :\n";comment " The fundamental frequency is " . ($fin / ($a * $n + $b * ($n + 1))) . " Hz.\n";comment " The amplitude is $bad_jitter seconds p-p (minimum_jitter = FALSE).\n";comment " The amplitude is $good_jitter seconds p-p (minimum_jitter = TRUE).\n";comment "\n";comment " Output Jitter Parameters (use_phase_accumulator = TRUE) :\n";comment " The fundamental frequency is " . ($fin / (2 ** $num_bits)) . " Hz.\n";comment " The amplitude is " . (1 / $fin) . " seconds p-p (approx).\n";comment "\n";comment " Design Parameters (use_phase_accumulator = FALSE) :\n";comment " Approx " . ((ceil(log($n + 1) / log(2)) + 2) + (ceil(log($a + $b) / log(2)) + 1)) . " flip flops (" . (ceil(log($n + 1) / log(2))) . " in prescaler, " . (ceil(log($a + $b) / log(2)) + 1) . " in controller and 2 retimes).\n";comment " The recursive controller uses approx $ff_count_recursive_controller flip flop" . (plural $ff_count_recursive_controller) . ".\n";comment " The Dual-Modulus Prescaler uses ratios /$n,/" . ($n + 1) . "\n";comment " The Output consists of $a cycle" . (plural $a) . " of $n input clock" . (plural $n) . ",\n";comment " and $b cycle" . (plural $b) . " of " . ($n + 1) . " input clocks.\n";comment " There " . (($a + $b) == 1 ? "is" : "are") . " " . ($a + $b) . " output clock" . (plural ($a + $b)) . " for every " . ($a * $n + $b * ($n + 1)) . " input clock" . (plural ($a * $n + $b * ($n + 1))) . ".\n";comment "\n";comment " Design Parameters (use_phase_accumulator = TRUE) :\n";comment " Approx " . ($num_bits + 2) . " flip flops ($num_bits in accumulator and 2 retimes)\n";comment " There " . ($c == 1 ? "is" : "are") . " " . ($c) . " output clock" . (plural $c) . " for every " . (2**$num_bits) . " input clocks.\n";comment "\n";# write summary of all dividers generated
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -