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.