APS-X84 VHDL/FPGA SYNTHESIS TUTORIAL

VHDL INCLUDE STUFF
Libraries and Packages

A PACKAGE is VHDL's method of implementing libraries. Items can be declared in a package like CONSTANTS and FUNCTIONS. We have gone over CONSTANTS in a previous page, and will discuss FUNCTIONS in detail later. LIBRARIES are declared in VHDL using the LIBRARY KEYWORD:
library IEEE; 
use IEEE.std_logic_1164.all; 

library METAMOR; 
use METAMOR.attributes.all; 

library SYNOPSYS; 
use SYNOPSYS.std_logic_arith.all; 
use SYNOPSYS.std_logic_unsigned.all; 

library PN_PAK; 
use PN_PAK.PN_PAK.all; 

IEEE.std_logic_1164 - This is the basic IEEE VHDL library which declares different a type of logic which we will use continually. The std_logic type is basically a bit (1 or 0) with some additional features like high impedance (Z) and don't cares (X). Operations and conversion routines are also defined in this library.

The USE and the  .all extenuation  tells the compiler to use all the elements/routine/functions contained in the IEEE.std_logic  library. This file is usually in text format and can be printed out and viewed. It is  VHDL code. In the FOUNDATION series
the file is located in :

active\vhdl\vhdl_lib\ieee.vhd

The same can be said for metamor.vhd and synopsys.vhd. It might be a good idea to stop and just take a look at these files.

Also in that directory is a new PACKAGE which we wrote ourselves called PN_PAK. The text of this package is shown below:
-------------------------------------------------------------------------- 
-- PACKAGE PN_pak 
-- 
-- Date:        16 Nov 96 
-- Version:     1.0  Associated Professional Systems 
-- 
-- Description: PN sample routines. 
-- 
-- APS 1996 
-- 
-------------------------------------------------------------------------- 

library ieee ; 
use ieee.std_logic_1164.all ; 

PACKAGE PN_PAK IS 
 
 FUNCTION slvect2int(vect : std_logic_vector) RETURN INTEGER; 
 
 FUNCTION int2slvect(int_value : INTEGER; size: INTEGER) RETURN std_logic_vector; 
 
     FUNCTION Adj_Regs_slv( 
        registers: std_logic_vector; 
    lrs_taps: std_logic_vector; 
    lrs_fill: std_logic_vector; 
    sync: std_logic 
         ) RETURN std_logic_vector; 
END PN_PAK; 

PACKAGE BODY PN_PAK IS 
------------------------------------------------------------------------ 
------------------------------------------------------------------------- 
-- 
-- Covert standard logic vector to integer 
-- 

FUNCTION slvect2int(vect : std_logic_vector) RETURN INTEGER IS 

 VARIABLE size :   INTEGER RANGE vect'length-1 DOWNTO 0; 
 VARIABLE result : INTEGER RANGE (2**vect'length)-1 DOWNTO 0; 
 BEGIN 
  result := 0; 
  FOR i IN 0 TO size LOOP 

   IF (vect(i) = '1') THEN 
    result := result + 2**i; 
   END IF; 

  END LOOP; 
  RETURN result; 
 END slvect2int; 

------------------------------------------------------------------------- 
------------------------------------------------------------------------- 
-- 
-- Convert integer to standard logic vector 
-- 

FUNCTION int2slvect(int_value : INTEGER; size:  INTEGER) RETURN std_logic_vector IS 

 
 VARIABLE result : std_logic_vector(size-1 DOWNTO 0); 
 BEGIN 
  FOR i IN 0 TO size-1 LOOP 

   IF ((int_value/(2**i)) REM 2) = 0 THEN 
    result(i) := '0'; 
   ELSE 
    result(i) := '1'; 
   END IF; 
  END LOOP; 
  RETURN result; 
 END int2slvect; 

------------------------------------------------------------------------- 
------------------------------------------------------------------------- 
------------------------------------------------------------------------- 
------------------------------------------------------------------------- 
-- Adj_Regs_bv - 
--         Determine feedback bit from register contents and tap settings 
--         and adjust the registers (LRS GENERATOR). When using this routine 
--         always have at least one extra register than is needed in your chain 
--         this will allow you to store the output bit in the msbit which allows 
--         us to use chains shorter than the assigned vector length. ie. if our 
--         largest possible lrs id an R16 (16 registers) than allocate 17 registers 
--         std_logicvectro(16 dt 0) for all the associated register chains. This 
--         routine returns the adjusted register chain. 
-- 
-- Author:   R. Schwarz 
-- Company:  APS 
-- Date:  July 1996 
-- 
-- 
FUNCTION Adj_Regs_slv 
  ( 
  registers:  std_logic_vector; -- current register state 
  lrs_taps:  std_logic_vector; -- current lrs tap settings 
  lrs_fill:  std_logic_vector; -- current lrs fill settings 
  sync:   std_logic         -- sync pulse signal to reload fill 
  ) RETURN std_logic_vector IS 

   -- feedback bit variable 
   VARIABLE fb_bit : std_logic; 
   -- temporary register set to calculate the feedback tap 
   VARIABLE temp_regs :std_logic_vector(registers'length-1 DOWNTO 0); 
   -- registers after shifting and processing 
   VARIABLE result : Std_logic_vector(registers'length-1 DOWNTO 0); 
   -- number where the last tap bit is contained for an r11(402h) the number is 11 
   VARIABLE LastBit : integer RANGE registers'length-1 DOWNTO 0; 
 
   BEGIN 

   -- mask off all ones at tap positions 
   temp_regs := registers AND lrs_taps; 
   -- initialize feedback bit to 0 
   fb_bit := '0'; 

   -- loop through all temp registers to calculate feedback bit 
   -- if odd number of ones then fbbit = '1' else '0' 
   FOR i IN 0 TO registers'length-1 LOOP 
    IF (temp_regs(i) = '1') THEN 
     fb_bit := fb_bit XOR '1'; 
    END IF; 
   END LOOP; 

   --assign all but msbit since it has output bit 
   --this works since if msb of taps is shorter than num of registers 
   --used the anding with taps at beginning will mask off this bit for 
   --feedback bit determination 
   FOR i IN 1 TO registers'length-2 LOOP 
    if sync = '1' then 
         result(i):= lrs_fill(i); 
        else 
     result(i) := registers(i-1); 
    end if; 
    -- assign ms tap number 
    IF lrs_taps(i-1) ='1' THEN 
     LastBit := i-1; 
    END IF; 
   END LOOP; 
   -- assign resultant lsb 
   if sync = '1' then 
    -- if reloading fill 
    result(0) := lrs_fill(0); 
   else 
           -- else feed back the newly formed feed back bit 
    result(0) := fb_bit; 
   end if; 
   -- assign resultant msb (output) 
   result(registers'length-1) := registers(LastBit); -- try using Lastbit instead of LastBit-1 
 
   RETURN result; 
   END Adj_Regs_slv; 
 
END PN_PAK; 

As can be seen in the PN_PAK.vhd PACKAGE
PACKAGE PN_PAK IS declares the PACKAGE 
which contains some declarations of functions like:
FUNCTION slvect2int(vect : std_logic_vector) RETURN INTEGER;
The function itself  is also shown below  which we will examine:
-- 
-- Covert standard logic vector to integer 
-- 

FUNCTION slvect2int(vect : std_logic_vector) RETURN INTEGER IS 

 VARIABLE size :   INTEGER RANGE vect'length-1 DOWNTO 0; 
 VARIABLE result : INTEGER RANGE (2**vect'length)-1 DOWNTO 0; 
 BEGIN 
  result := 0; 
  FOR i IN 0 TO size LOOP 

   IF (vect(i) = '1') THEN 
    result := result + 2**i; 
   END IF; 

  END LOOP; 
  RETURN result; 
 END slvect2int;

This FUNCTION is used to convert STD_LOGIC_VECTORs to INTEGERS. It has alot of elements in it which we will discuss. A FUNCTION is a subprogram which is usually used for computing a single value. As can be seen in our FUNCTION we send in a std_logic_vector and RETURN an INTEGER. VARIABLES size and result are declare in side the FUNCTION. Notice that size is declared as a vect'length size INTEGER. vect is the name of the STD_LOGIC_VECTOR which is passed into the FUNCTION. length is an attribute of the STD_LOGIC_VECTOR object. There are many other attributes of STD_LOGIC_VECTORs and other VHDL data types which are available for use. We will not discuss these in this text but it is a feature worth exploring in a more detailed VHDL text. For our purposes we need to understand that this FUNCTION which is a part of the PN_PAK package can be USEd in VHDL codes as shown in the example below:
library IEEE; 
use IEEE.std_logic_1164.all; 

library METAMOR; 
use METAMOR.attributes.all; 

library SYNOPSYS; 
use SYNOPSYS.std_logic_arith.all; 
use SYNOPSYS.std_logic_unsigned.all; 

library PN_PAK; 
use PN_PAK.PN_PAK.all; 

ENTITY X84DEMO IS 

   PORT 
  ( 
   The555In:       IN        std_logic; 
   DivSigOut:      BUFFER    std_logic; 
   DivCntIn:       IN std_logic_vector(7 downto 0) 
  ); 

 

  attribute pinnum of DivCntIn  : signal is  "P10,P9,P8,P7,P6,P5,P4,P3"; 
  attribute pinnum of DivSigOut  : signal is  "P35"; 
  attribute pinnum of The555In  : signal is  "P24"; 
 
 
END X84DEMO; 
---------------------------------------------------------------- 
---------------------------------------------------------------- 
ARCHITECTURE behave OF X84DEMO IS 

SIGNAL Count: INTEGER RANGE 0 TO 255; 
SIGNAL MultCnt: INTEGER RANGE 0 TO 255; 

-- Divide input by Multiplier times the DivCntIn value 
CONSTANT Multiplier : INTEGER RANGE 0 to 255 := 10; 

BEGIN 

DIVIDER: PROCESS 
BEGIN 
     WAIT UNTIL The555In'EVENT AND The555In = '1'; -- wait til rising edge 

 
      IF MultCnt >= Multiplier THEN 
        Count <= Count +1; -- increment counter 
        MultCnt <= 0;      -- reinitialize Multiplier Counter 
      ELSE 
       MultCnt <= MultCnt + 1; -- Output divided pulse; 
      END IF; 

      IF Count >= slvect2int(DivCntIn,8) THEN 
       DivSigOut <= NOT DivSigOut; -- toggle LED on X84 
        Count <= 0; -- reinitialize counter 
      END IF; 
 
END PROCESS; 

END behave; 

Notice how we are able to use the INTEGER data type to increment and compare data values to a STD_LOGIC_VECTOR which is a byte input to the FPGA chip on the X84 board in this example. Next we will implement the divider VHDL code shown above.