⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fracn09.pl

📁 Clock generation perl to vhdl oijoij
💻 PL
📖 第 1 页 / 共 5 页
字号:
# default parameters$tolerance = 1.0e-7;        # default allowable relative tolerance on fout (+/-)$entity_name = "fracn";     # default name of entity in generated VHDL$architecture_name = "rtl"; # default name of architecture in generated VHDL$low_jitter_controller = 1; # on by default$convergence_check = 1;     # on by default$tabstop = 4;               # size of indent in generated code$verbose = -t STDOUT;       # on by default iff connected to tty$std_logic_arith = 0;       # off by default (default to lib IEEE.numeric_std)$std_logic_unsigned = 0;    # off by default (default to lib IEEE.numeric_std)# process command line argumentsuse vars qw(@argv_orginal);@argv_orginal = @ARGV; # save for later...do {    use Getopt::Std;        # for command line parsing...    my %opts;    getopt('aefhHit', \%opts);    foreach (keys %opts) {        #print "$_\t" . (defined $opts{$_} ? $opts{$_} : "undefined") . "\n";        SWITCH : {            if (/^a$/) { $architecture_name = $opts{$_}; last SWITCH; }            if (/^e$/) { $entity_name       = $opts{$_}; last SWITCH; }            if (/^f$/) { $base_name         = $opts{$_}; last SWITCH; }            if (/^t$/) { $tolerance         = $opts{$_}; last SWITCH; }            if (/^i$/) { $tabstop           = $opts{$_}; last SWITCH; }            if (/^s$/) { $std_logic_arith = 1;           last SWITCH; }            if (/^u$/) { $std_logic_unsigned = 1;        last SWITCH; }            if (/^g$/) { $low_jitter_controller = 0;     last SWITCH; }            if (/^c$/) { $convergence_check = 0;         last SWITCH; }            if (/^v$/) { $verbose = not $verbose;        last SWITCH; }            if (/^x$/) {                                 last SWITCH; } # magic ignored option!            if (/^h$/i) { usage_exit;                    last SWITCH; }   # help            usage_exit("unknown option '$_'\n");        }    }};usage_exit("Wrong number of arguments\n") if ($#ARGV != 1);# more global variablesuse vars qw($fin $fout $desired_ratio $min_ratio $max_ratio);use vars qw($floor_max_ratio $floor_min_ratio $ceil_min_ratio);$fin = $ARGV[0] + 0;    # input clock frequency (Hz)$fout = $ARGV[1] + 0;   # desired output frequency (Hz)# Check for bad inputusage_exit("Bad architecture name option\n")    if ((not defined $architecture_name) or ($architecture_name !~ /^[a-z][a-z0-9_]+$/i));usage_exit("Bad entity name option\n")    if ((not defined $entity_name) or ($entity_name !~ /^[a-z][a-z0-9_]+$/i));# output file names$base_name = $entity_name if (not defined $base_name);$vhdl_name = "$base_name.vhd";$verilog_name = "$base_name.v";usage_exit("Indent size must be a number\n") unless ($tabstop > 0 or $tabstop eq "0");usage_exit("Can't use std_logic_arith and std_logic_unsigned at the same time\n")    if ($std_logic_arith and $std_logic_unsigned);# check for input that would cause numeric problems.usage_exit("frequencies must be > 0Hz\n") if ($fin <= 0 or $fout <= 0);usage_exit("Fin/Fout ratio too small\n") if ($fin/$fout < 1);#usage_exit("Fin/Fout ratio too small\n") if ($fin/$fout < 2); # can't do /1 prescaler?!usage_exit("Fin/Fout ratio too big\n") if (($fin/$fout > 1e12) and $convergence_check);usage_exit("tolerance must be > 0\n") if ($tolerance <= 0);usage_exit("tolerance too tight (try something like 0.0000001, or use the -c switch)\n") if (($tolerance < 1e-15) and $convergence_check);usage_exit("tolerance too loose (try something like 0.0001)\n") if (($tolerance >= 1) and $convergence_check);$desired_ratio = ($fin / $fout);$min_ratio = ($fin / ($fout * (1 + $tolerance)));$max_ratio = ($fin / ($fout * (1 - $tolerance)));#print "trying ratios between $min_ratio and $max_ratio\n";# get the integer upper and lower bounds$floor_max_ratio = floor($max_ratio);$floor_min_ratio = floor($min_ratio);$floor_min_ratio = 1 if ($floor_min_ratio == 0);    # fix for ratios close to 1$ceil_min_ratio  = ceil($min_ratio);die "numeric problems" if ($floor_max_ratio <= 0 or $floor_min_ratio <= 0);if (not $low_jitter_controller) {    warning("Warning: the controller enabled by the \"minimum_jitter\" generic has",            "  not been implemented due to the -g command line switch.");}if ($std_logic_unsigned) {    warning("Warning: std_logic_unsigned library has been used",            "  due to the -u command line switch.");}if ($std_logic_arith) {    warning("Warning: std_logic_arith library has been used",            "  due to the -s command line switch.");}############### Design the prescaler (choose a value for n) ####################print "designing prescaler\n" if ($verbose);use vars qw($n);    # more global variables$n = $floor_min_ratio;# check to see if a straight integer divider will doif ($floor_max_ratio >= $ceil_min_ratio) {    warning("Warning: a fractional-N divider is not needed.");    if ($floor_max_ratio > $ceil_min_ratio) {        warning("  Integer dividers $ceil_min_ratio to $floor_max_ratio are ok.");        $n = $floor_max_ratio;    }    else {        warning("  Integer divider $floor_max_ratio is ok.");        $n = $floor_max_ratio;    }}#print "/$n,/" . ($n + 1) . " prescaler\n";############## Design the controller (choose values for a and b) ###############print "designing controller\n" if ($verbose);use vars qw($a $b $ratio $fout_achieved $error_achieved);    # more global variables$a = 1;     # number of /n cycles$b = 0;     # number of /(n+1) cyclesdo {    my $iterations_remaining = $convergence_check ? 1e7 : 1e12;    # try different values of a and b until the ratio falls between min_ratio and    # max_ratio    while (1)    {        die "No convergence - try adjusting tolerance or use -c switch\n" .            "Current values are a=$a b=$b"            unless (--$iterations_remaining);        $ratio = ($a * $n + $b * ($n + 1))/($a + $b);        if ($ratio < $min_ratio) {            # too small            $b++;            next;        }        if ($ratio > $max_ratio) {            # too big            $a++;            next;        }        # just right, Goldilocks        last;    }};$fout_achieved = $fin/$ratio;               # Hz$error_achieved = $fout_achieved - $fout;   # Hzif (abs($error_achieved / $fout) > $tolerance) {    warning("Warning: Dual Modulus Prescaler design did not meet frequency tolerance target.");}############ Work out the jitter performance ###################################use vars qw($bad_jitter $good_jitter $controller_table); # more global variables# calculate jitter performance, for "high jitter" controller architecture$bad_jitter  = $a * ($ratio - $n) / $fin;#$bad_jitter = $b * ($n + 1 - $ratio) / $fin; # should be the sameprint "calculating controller table\n" if ($verbose);do {    # work out distribution of /n,/n+1 for better jitter performance    # (used in "low jitter" architecture)    my $used_a = 0;    my $used_b = 0;    my $desired_trajectory = $a / ($a + $b);    # The array controller_table contains the distribution of /n, /n+1    # (changed from an array to a string in version 0.05 to save space.)    $controller_table = "";    # work out first entry (be careful, sometimes $b may be 0)    if ( $a > $b ) {        (substr $controller_table, 0, 1) = '1';        $used_a++;    }    else {        (substr $controller_table, 0, 1) = '0';        $used_b++;    }    # work out rest of table for "maximum interleaving" (which gives minimum jitter)    for (my $index = 1; $index < $a + $b; $index++)    {        if ( $used_a / $index > $desired_trajectory ) {            (substr $controller_table, $index, 1) = '0';            $used_b++;        }        else {            (substr $controller_table, $index, 1) = '1';            $used_a++;        }    }    die "Numeric problem in jitter reducer" unless ($used_a == $a and $used_b == $b);};print "estimating jitter\n" if ($verbose);do {    my $total_outputs = 0;    my $total_input_clocks = 0;    my $max_pos_error = 0;    my $max_neg_error = 0;    # now measure the jitter    for (my $index = 0; $index < $a + $b; $index++)    {        $total_input_clocks += (substr $controller_table, $index, 1) ? $n : $n + 1;        $total_outputs++;        my $phase_error = $total_input_clocks - ($ratio * $total_outputs);        $max_pos_error = $phase_error if ( $max_pos_error < $phase_error );        $max_neg_error = $phase_error if ( $max_neg_error > $phase_error );    }    $good_jitter  = ($max_pos_error - $max_neg_error) / $fin;};############### Design the recursive controller ################################print "designing recursive controller\n" if ($verbose);# The modulus control signal for the prescaler can be generated by another# fractional-N divider, which in turn can have its modulus control signal# generated by yet another fractional-N divider, and so on.# We stop when we don't need another fractional-N divider, and can just use# a fixed divider.# The particular arrangement we use also produces the minimum possible jitter.use vars qw($stage @n_array @m_array @a_array @b_array @i_array); # more global variablesuse vars qw($ff_count_recursive_controller); # more global variables$stage = 0;# Stage is (roughly) the number of recursive stages needed:#  Stage  0 is the prescaler we've already designed#  Stages 1 .. $stage are the recursive dual modulus dividers#  Stage  $stage + 1 is the fixed divider at the end$n_array[$stage] = $n;  # this stage divides by n or n+1$m_array[$stage] = 'X'; # Controls duty cycle of modulus control output from this stage.$a_array[$stage] = $a;  # This stage requires its modulus control input to be low for this number of cycles$b_array[$stage] = $b;  # This stage requires its modulus control input to be high for this number of cycles$i_array[$stage] = 'X'; # Invert the output of this stage#print "n$stage=$n\tm$stage=\ta$stage=$a\tb$stage=$b\ti$stage=\n";while ($b_array[$stage] > 1.0001 and $a_array[$stage] > 1.0001) {    my $n1 = $n_array[$stage];    my $a1 = $a_array[$stage];    my $b1 = $b_array[$stage];    my $n2; my $m2; my $a2; my $b2; my $i2;    my $determinant;    die "negative count" if ($n1 < 0 or $a1 < 0 or $b1 < 0);    $i2 = ($a1 < $b1) ? 1 : 0;    if ( $i2 ) {        $n2 = floor(($a1 + $b1) / ($a1));        $m2 = ceil($b1 / $a1);        # we have a1, b1, and we know how to determine a1, b1 from a2, b2,        # so invert the 2x2 matrix to work out a2, b2 from a1, b1.        $determinant = ($n2 - $m2 + 1);        die "singular matrix" if ($determinant == 0);        $a2 = ($m2 * $a1 - ($n2 + 1 - $m2) * $b1) / $determinant;        $b2 = ((1 - $m2) * $a1 + ($n2 + 1 - $m2) * $b1) / $determinant;    }    else {        $n2 = floor(($a1 + $b1) / ($b1));        $m2 = ceil($a1 / $b1);        $determinant = ($m2 - $n2 - 1);        die "singular matrix" if ($determinant == 0);        $a2 = (($n2 + 1 - $m2) * $a1 - $m2 * $b1) / $determinant;        $b2 = (($m2 - $n2 - 1) * $a1 + ($m2 - 1) * $b1) / $determinant;    }    $stage++;    $n_array[$stage] = $n2;    $m_array[$stage] = $m2;    $a_array[$stage] = $a2;    $b_array[$stage] = $b2;    $i_array[$stage] = $i2;    #print "n$stage=$n2\tm$stage=$m2\ta$stage=$a2\tb$stage=$b2\ti$stage=$i2\n";    die "too many stages in recursive controller" if ($stage > 15 and $convergence_check);}# fill in the parameters for the last (non-fractional) stage$n_array[$stage + 1] = $a_array[$stage] + $b_array[$stage] - 1;$m_array[$stage + 1] = $a_array[$stage];$a_array[$stage + 1] = 'X';$b_array[$stage + 1] = 'X';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -