# CLAverilog Perl Module provides CLAverilog subroutine that takes even number of bits as input and
# generates Verilog code for a Carry Look-Ahead Adder of length equal to input bits.
# Last Updated: 05/14/2005

package CLAverilog;
use 5.006;
require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(CLAverilog);

use strict;
#use warnings;

sub CLAverilog {

	my ($cla_length)=@_;
	my ($i, @bclg2_L, @bclg4_L, $bclg_count, $rng_start, @Cin_L, $pg_count, $level, $final_level);

	# If specified CLA length is not a positive even integer, warn the user and exit with a return value of '1'
	if (($cla_length<=0) || $cla_length%2) {
		warn ("Cannot generate $cla_length-bit Carry Look-Ahead Adder!\a\n",
		"Carry Look-Ahead Adder length should be a positive even integer\n"
		);
		return 1;
	} else {

		# Find number of BCLG2, BCLG4 and BCLG levels required
		$level=1;
		($bclg2_L[$level], $bclg4_L[$level])=Find_bclg($cla_length);
		while (($bclg2_L[$level]+$bclg4_L[$level])>1) {
			$level++;
			($bclg2_L[$level], $bclg4_L[$level])=Find_bclg($bclg2_L[$level-1]+$bclg4_L[$level-1]);
		}
		$final_level=$level;

		# Module definition
		printf ("//%s bit Carry Look-Ahead Adder\n", $cla_length);
		printf ("module cla%s (Cout, Sum, A, B, Cin);\n\n", $cla_length);

		# Define input ports
		printf ("\tinput [%s:0] A;\n", $cla_length-1);
		printf ("\tinput [%s:0] B;\n", $cla_length-1);
		print ("\tinput Cin;\n\n");

		# Define output ports
		printf ("\toutput [%s:0] Sum;\n", $cla_length-1);
		print ("\toutput Cout;\n\n");

		# Define nets
		printf ("\twire [%s:0] ctemp;\n",$cla_length-1);
		printf ("\twire [%s:0] g_L0;\n", $cla_length-1);
		printf ("\twire [%s:0] p_L0;\n", $cla_length-1);
		for ($level=1; $level<=$final_level; $level++) {
			printf ("\twire [%s:0] g_L%s;\n", $bclg4_L[$level]+$bclg2_L[$level]-1, $level);
			printf ("\twire [%s:0] p_L%s;\n", $bclg4_L[$level]+$bclg2_L[$level]-1, $level);
		}
		print ("\twire t1;\n");

		print ("\n//CLA Level 0:\n");  # --------------- CLA Level 0 -------------------------
		print ("\tassign ctemp[0] = Cin;\n");
		for ($i=0;$i<$cla_length;$i++) {
			printf ("\trfa r%02s(g_L0[%s], p_L0[%s], Sum[%s], A[%s], B[%s], ctemp[%s]);\n", $i+1, $i, $i, $i, $i, $i, $i);
		}

		print ("\n//CLA Level 1:\n");  # --------------- CLA Level 1 -------------------------
		$bclg_count=0;
		$rng_start=0;
		$pg_count=0;
		for ($i=0; $i<$bclg4_L[1]; $i++, $bclg_count++, $pg_count++, $rng_start+=4) {
			$Cin_L[2][$pg_count]=$rng_start;
			printf ("\tbclg4 b%02s(ctemp[%s:%s], g_L1[%s], p_L1[%s], g_L0[%s:%s], p_L0[%s:%s], ctemp[%s]);\n", $bclg_count+1, $rng_start+3, $rng_start+1, $pg_count, $pg_count, $rng_start+3, $rng_start, $rng_start+3, $rng_start, $rng_start);
		}
		for ($i=0; $i<$bclg2_L[1]; $i++, $bclg_count++, $pg_count++, $rng_start+=2) {
			$Cin_L[2][$pg_count]=$rng_start;
			printf ("\tbclg2 b%02s(ctemp[%s], g_L1[%s], p_L1[%s], g_L0[%s:%s], p_L0[%s:%s], ctemp[%s]);\n", $bclg_count+1, $rng_start+1, $pg_count, $pg_count, $rng_start+1, $rng_start, $rng_start+1, $rng_start, $rng_start);
		}

		# ---------------------------------------------- CLA Level 2, 3, ... -----------------
		for ($level=2; $level<=$final_level; $level++) {
			print "\n//CLA Level $level:\n";
			$rng_start=0;
			$pg_count=0;
			for ($i=0; $i<$bclg4_L[$level]; $i++, $bclg_count++, $pg_count++,$rng_start+=4) {
				$Cin_L[$level+1][$pg_count]=$Cin_L[$level][$rng_start];
				printf ("\tbclg4 b%02s({ctemp[%s], ctemp[%s], ctemp[%s]}, g_L%s[%s], p_L%s[%s], g_L%s[%s:%s], p_L%s[%s:%s], ctemp[%s]);\n", $bclg_count+1, $Cin_L[$level][$rng_start+3], $Cin_L[$level][$rng_start+2], $Cin_L[$level][$rng_start+1], $level, $pg_count, $level, $pg_count, $level-1, $rng_start+3, $rng_start, $level-1, $rng_start+3, $rng_start, $Cin_L[$level][$rng_start]);
			}
			for ($i=0; $i<$bclg2_L[$level]; $i++, $bclg_count++, $pg_count++,$rng_start+=2) {
				$Cin_L[$level+1][$pg_count]=$Cin_L[$level][$rng_start];
				printf ("\tbclg2 b%02s(ctemp[%s], g_L%s[%s], p_L%s[%s], g_L%s[%s:%s], p_L%s[%s:%s], ctemp[%s]);\n", $bclg_count+1, $Cin_L[$level][$rng_start+1], $level, $pg_count, $level, $pg_count, $level-1, $rng_start+1, $rng_start, $level-1, $rng_start+1, $rng_start, $Cin_L[$level][$rng_start]);
			}
		}

		print ("\n//Carry out:\n");
		printf ("\tand a1(t1 , p_L%s[0], Cin);\n", $final_level);
		printf ("\tor o1(Cout , g_L%s[0], t1);\n", $final_level);
	
		printf ("\nendmodule //cla%s\n",$cla_length);
		# CLA generation was successful, so exit with a return value of '0'
		return 0;
	}
}

# Find_bclg: This subroutine finds the number of BCLG2 and BCLG4 required in a BCLG level,
# depending on the number of (p, g) input pairs.
sub Find_bclg {
	my ($Inputs)=@_;
	my ($bclg2, $bclg4)=(0, 0);

	if ($Inputs>=8) {
		$bclg2=(4-($Inputs/2)%4)%4; # Derived from the table below
		$bclg4=($Inputs-$bclg2*2)/4; # Derived from the table below
	} else {
		$bclg2=(($Inputs/2)%2); # Derived from the table below
		$bclg4=($Inputs-$bclg2*2)/4; # Derived from the table below
	}
	return ($bclg2,$bclg4);
}

###################################################################################################################
# Following table shows BCLG2 and BCLG4 progression for CLA length upto 64 bits
# The expressions for BCLG2 and BCLG4 are derived from this table
###################################################################################################################
#   No. of Bits 02 04 06 08 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 ...
#                |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
# Level1  BCLG2  1  0  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0  3  2  1  0 ...
#         BCLG4  0  1  1  2  1  2  3  4  3  4  5  6  5  6  7  8  7  8  9 10  9 10 11 12 11 12 13 14 13 14 15 16 ...
#                |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
# Level2  BCLG2  0  0  1  1  0  0  0  0  1  1  1  1  0  0  0  0  3  3  3  3  2  2  2  2  1  1  1  1  0  0  0  0 ...
#         BCLG4  0  0  0  0  0  1  1  1  1  1  1  1  2  2  2  2  1  1  1  1  2  2  2  2  3  3  3  3  4  4  4  4 ...
#                |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
# Level3  BCLG2  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 ...
#         BCLG4  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1 ...
###################################################################################################################

1;

