 # dapkg_gen -- Distributed Arithmetic package generator
 # Copyright (C) 2000 Mustafa Tirhi 
 # This program is free software; you can redistribute it and/or modify 
 # it under the terms of the GNU General Public License as published by	 
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,		  
 # but WITHOUT ANY WARRANTY; without even the implied warranty of		  
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #      

 # This program generates the DApkg.vhd file that is used to define 
 # the DA filter core and gives its parameters and the contents of the 
 # Distributed Arithmetic Look-up-table "DALUT" according to the DA algorithm 

                                                                    

package  main ;


{
  use strict;  
                 
  my $filter;                    
  my $input;   
    
  $filter = generate_constants -> new;		
  
  $filter -> read_input;
  $filter -> gen_file;
     
}
                                                                               
##############################################################################

                                                                                          
package generate_constants ;

{
	
use strict;
        
                                     
#------------------------------------------------------------------------------
#              :
#      Function: new    
#              :
#------------------------------------------------------------------------------
#       Purpose: Creat a new object for generate_constants
#------------------------------------------------------------------------------
#  Side Effects: None
#------------------------------------------------------------------------------
#  Return Value: $self
#------------------------------------------------------------------------------
#    Parameters: None
#------------------------------------------------------------------------------
#       Example: 
#------------------------------------------------------------------------------


sub new 
{	     	       	    
  my ($class)  = shift;     	 
 	    
  my($self) ;

  
                 		      	    	    	    	    	    
  $self -> {'taps'}      = 0 ;
  $self -> {'word_size'} = 0 ;      											   					

  $self -> {'MAXTABS'}     = 256 ;
  $self -> {'MAXWORDSIZE'} = 64  ;
  
  $self -> {'constants'} = {} ;             
  $self -> {'rom'}       = {} ;  
  
  bless $self,$class;
}

#-----------------------------------------------------------------------------
#              :
#      Function: read_input
#              :
#-----------------------------------------------------------------------------
#       Purpose: Reading filter taps and word size
#-----------------------------------------------------------------------------
#  Side Effects: None
#-----------------------------------------------------------------------------
#  Return Value: None
#-----------------------------------------------------------------------------
#    Parameters: None
#-----------------------------------------------------------------------------
#       Example: 
#-----------------------------------------------------------------------------

    
sub read_input
{                                                                                        
  my ($self) = shift;
  my $index; 
  my $temp;
  my $max = 0;


  print "\n***** DApkg.vhd generator *****\n" ;

  print "\nEnter word size ";

  chomp ( $self->{'word_size'} = <STDIN> );
 
    
  if( $self->{'word_size'} <= 0 )
  {
      print "Negative no. are not allowed\n";
      exit;      
  }


  print "\nEnter no. of filter taps ";
  
  chomp ($self->{'taps'} = <STDIN>) ;
  
  if( $self->{'taps'} <= 0 )
  {
    print "Negative no. are not allowed\n" ;      
    exit;      
  }
    
    
  $max = 2 ** $self->{'word_size'};
  
  print "\nEnter filter constants starting from tap[0]";
   
  for( $index =0; $index < $self->{'taps'} ; $index++)
  {
    print "\n[$index]:";
	                   
    chomp ($self->{'constants'}->{$index} =  <STDIN>) ;
    	 
    if( $self->{'constants'}->{$index} >= $max  )
    {
      printf "[Error]: large constant >= [$max]\n" ;
      printf "\nInvalid intry please repeat your last entry\n"; 
      $index-- ;      
	  next;
    }                  
  	
  	$self->{'constants'}->{$index} =~ s/ //g;
  	

	if ( $self->{'constants'}->{$index}	=~ m/\D/ 
	or ( length ( $self->{'constants'}->{$index} )  == 0  )  )
	{
      printf "\nInvalid intry please repeat your last entry\n"; 
      $index-- ;      
	  next;
	}
    
  }    
  print "\nFilter information\n";
  print "\nFilter taps = [$self->{'taps'}]";
  print "\nWord size = [$self->{'word_size'}]";
  print "\nFilter constants\n";

  foreach $index (sort numeric keys % {$self->{'constants'} })
  {
    print "\n[$index]:[$self->{'constants'}->{$index}]" ;    
  }
  print "\n";
  print "\nLUT contents\n";

}     		 		 		 	
 



#-----------------------------------------------------------------------------
#              :
#      Function: gen file
#              :
#-----------------------------------------------------------------------------
#       Purpose: Generating VHDL file DApkg.vhd 
#-----------------------------------------------------------------------------
#  Side Effects: None
#-----------------------------------------------------------------------------
#  Return Value: NOne
#-----------------------------------------------------------------------------
#    Parameters: None
#-----------------------------------------------------------------------------
#       Example: 
#-----------------------------------------------------------------------------

    
sub gen_file                                                                                

{                                                                                        
  my ($self) = shift;
  my $i;

  open ( FILE , ">./DApkg.vhd" )  or 
  die "\n Can't creat DApkg.vhd\n";	
 
  printf  FILE "
-------------------------------------------------------------------------------
-- Title      :Distributed Arithmetic Package
-- Project    : Arithmetic blocks
-------------------------------------------------------------------------------
-- File        : DApkg.VHD
-- Author      : Jamil Khatib  
-- Organization: OpenIPCore Project
-- Created     : 2000/04/17
-- Last update : 2000/04/17
-- Platform    : 
-- Simulators  : Modelsim 5.3XE / Windows98
-- Synthesizers: Leonardo / WindowsNT
-- Target      : 
-- Dependency  : 
-------------------------------------------------------------------------------
-- Description: Distributed Arithmetic Package
-------------------------------------------------------------------------------
-- Copyright (c) 2000 Jamil Khatib
-- 
-- This VHDL design file is an open design; you can redistribute it and/or
-- modify it and/or implement it under the terms of the Openip General Public
-- License as it is going to be published by the OpenIPCore Organization and
-- any coming versions of this license.
-- You can check the draft license at
-- http://www.opencores.org/OIPC/license.shtml

-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   1
-- Version         :   0.1
-- Date            :   17th Apr 2000
-- Modifier        :   Jamil Khatib (khatib\@ieee.org)
-- Desccription    :   Created
--
-------------------------------------------------------------------------------
-- Revisions  :
-- Revision Number :   2
-- Version         :   0.2
-- Date            :   30h Apr 2000
-- Modifier        :   Jamil Khatib (khatib\@ieee.org)
-- Desccription    :   defining the constant CONSTANTS for DALUT contents
--					   which should be genrated automatically in later versions
--
-------------------------------------------------------------------------------

-- This file was generated by DApkg_gen perl tool

library ieee;
use ieee.std_logic_1164.all;

package DApkg is
  constant BUFFER_SIZE : integer := $self->{'taps'};  -- No. of inputs, No of filter taps,
                                        -- No. of constants , Buffer Size
  constant DATA_SIZE   : integer := $self->{'word_size'};  -- Word size

  type TABLE is array ( 0 to (2**BUFFER_SIZE) -1) of std_logic_vector((DATA_SIZE -1 ) downto 0);
                                        -- Memory type";
 printf FILE "\n  constant CONSTANTS : TABLE := (\n\n";



 $self -> generate_LUT; # generating rom constants 
 
 
 printf FILE "\n);\n-------------------------------------------------------------------------------";

  printf FILE "\n-- DA filter top core

  component DA
    generic (
      NOINPUTS  :     integer := BUFFER_SIZE;  -- number of inputs, no. of filter taps
      WORD_SIZE :     integer := DATA_SIZE;  -- word size
      CONTENTS  :     TABLE   := CONSTANTS);
    port (
      data      : in  std_logic_vector(WORD_SIZE -1 downto 0);  -- input data
      Clk       : in  std_logic;        -- system clock
      Rst_n     : in  std_logic;        -- System reset
      Result    : out std_logic_vector(WORD_SIZE -1 downto 0);  -- Result
      ValidOut  : out std_logic;        -- Output valid
      Overflow  : out std_logic);       -- Overflow signal
  end component;
-------------------------------------------------------------------------------
-- DALUT Distributed Arithmetic Lookup table

  component DALUT
    generic (
      ADDR_SIZE   : integer;                   --:= BUFFER_SIZE;
      -- LUT address size or number of input terms
      OUTPUT_SIZE : integer;  --:= DATA_SIZE;  -- Output size
      CONTENTS    : TABLE                      -- CONSTANTS
      -- These values should be generated automaticlly from the original
      -- constants of the filter

      );

    port (
      Address : in  std_logic_vector(ADDR_SIZE -1 downto 0);  -- DALUT Address
      Result  : out std_logic_vector(OUTPUT_SIZE -1 downto 0));  -- Result

  end component;

  ------------------------------------------------------------------------------

end DApkg;
package body DApkg is

end DApkg;";  

}     		 		 		 	

#-----------------------------------------------------------------------------
#              :
#      Function: numeric 
#              :
#-----------------------------------------------------------------------------
#       Purpose: comparing to numbers ( used for sorting )
#-----------------------------------------------------------------------------
#  Side Effects: None
#-----------------------------------------------------------------------------
#  Return Value: 1 if true , -1 if false 
#-----------------------------------------------------------------------------
#    Parameters: $a , $b 
#-----------------------------------------------------------------------------
#       Example: 
#-----------------------------------------------------------------------------

sub numeric 
{
    
    if ( $b <= $a) 
    {
        return (1);
    }
    return (-1);		
}


#-----------------------------------------------------------------------------
#              :
#      Function: to_binary_string
#              :
#-----------------------------------------------------------------------------
#       Purpose: converting integer to binary string 
#-----------------------------------------------------------------------------
#  Side Effects: None
#-----------------------------------------------------------------------------
#  Return Value: $bin_string
#-----------------------------------------------------------------------------
#    Parameters: $input  , $bin_string 
#-----------------------------------------------------------------------------
#       Example: 
#-----------------------------------------------------------------------------

sub to_binary_string
{
  my ($self) = shift;
  my ($input , $bin_string ) = @_;
  
  my $i    = 0;
  my $temp = 0;

   
  $i = $self ->{'word_size'} ;
    
  for ( $i = $self ->{'word_size'} ; $i > 0 ; $i-- )
  {
	        
	$temp = $input & 0x1 ;	
    BIN:
    {
      if ($temp eq 0x1 )   { $temp = '1';last BIN; }
      if ($temp eq 0x0 )   { $temp = '0';last BIN; }
    }
						
    $bin_string =  $temp . $bin_string  ;
  	$input = int($input/2);

  }                                       
  $bin_string = '"' . $bin_string . '"';
  
  return ($bin_string);
    
}
       

#-----------------------------------------------------------------------------
#              :
#      Function: generate_LUT 
#              :
#-----------------------------------------------------------------------------
#       Purpose: generating look up table baised on the filter taps
#-----------------------------------------------------------------------------
#  Side Effects: None
#-----------------------------------------------------------------------------
#  Return Value: 1 if true , -1 if false 
#-----------------------------------------------------------------------------
#    Parameters: $a , $b 
#-----------------------------------------------------------------------------
#       Example: 
#-----------------------------------------------------------------------------

sub generate_LUT
{
  my ($self) = shift;
  my $flag;
  my $i = 0 ;
  my $j = 0 ;
  my $max_addr = 2 ** $self->{'taps'};
  my $index = 0;
  my $bin;
    
  for ( $i = 0; $i < $max_addr; $i++) # i = rom address

  {
    $index = $i;
	$self->{'rom'}->{$i} = 0;

	
	    
	for ($j = 0; $j < $self->{'taps'} ; $j++)
	{
	  $flag = 0x1 & $index;           # Mask the first bit

	  $self->{'rom'}->{$i} =     $self->{'rom'}->{$i}  
	                         + ( $self->{'constants'}->{$j} *  $flag );
	        
	  $index = int ($index/2) ;       # get next bit in the address
	        
	}

	printf ("\nROM[%d] = [%d]  ", $i , $self->{'rom'}->{$i} ) ;
	printf $self -> to_binary_string ( $self->{'rom'}->{$i} , $bin ) ;    
	printf "b";

	printf FILE "  ";
	printf FILE  $self -> to_binary_string ( $self->{'rom'}->{$i} , $bin ) ;    
	
	if ($i != ($max_addr-1 ))
	{
		printf FILE ",\n";
	}

   
  }

  printf FILE "\n";
  printf "\n";

}

##############################################################################

}	# end of package generate_constants

