Skip to content
Snippets Groups Projects
mem_model.vhd 99.9 KiB
Newer Older
library ieee;
use ieee.std_logic_1164.all;
library std;
use std.textio.all;

PACKAGE mem_model is

    -- 2d array to store data for each row
    type row_matrix  is array (NATURAL RANGE <>, NATURAL RANGE <>) of UX01;
    type rowptr_type is access row_matrix;
    -- record for for storing refresh and memory ptr for each row
    type row_data_type is
        record
            last_refresh : time;                -- last time row was refreshed
            rowptr       : rowptr_type;         -- ptr to 2d matrix with data
            all_xs       : BOOLEAN;             -- true if row is filled with Xs
        end record;
    -- array of refresh times and memory ptrs for the rows
    type row_data is array (NATURAL RANGE <>) of row_data_type;
    type row_data_ptr_type is access row_data;
    type strptr is access string;
    type default_ptr_type is access std_logic_vector;
    type mem_type is (DRAM, SRAM, ROM);   -- memory types
    
    -- record defining memory and holding general information

    type mem_id_rtype is

        record
            memory_type    : mem_type;            -- memory type
            refresh_period : time;                -- refresh period
            last_init      : time;                -- last time a refresh was performed
            counter        : NATURAL;             -- refresh counter
            name           : strptr;              -- pointer to memory name
            rows           : POSITIVE;            -- # of rows
            columns        : POSITIVE;            -- # of columns
            width          : POSITIVE;            -- # word length
            length         : POSITIVE;            -- # of memory locations
            row_data_ptr   : row_data_ptr_type;   -- ptr to memory ptrs.
            default_val    : default_ptr_type;    -- ptr to default memory word value
        end record;

    type mem_id_type is access mem_id_rtype;

    
--********************************************************************************
    --    Function Name   :  SRAM_Initialize
    --
    --    Purpose         :  To create the data structure used to store a
    --                       static RAM and to initialize it
    --
    --    Parameters      :  name    - string used to represent the memory
    --                       length  - the number of "words" in the memory
    --                       width   - the length of a "word" of memory
    --                       default_word   - value to which each word of memory
    --                                        should be initialized
    --
    --    RETURNED VALUE  :  mem_id_type - ptr to memory record
    --
    --    NOTE            :  initially the data structure is empty with no
    --                       space being allocated for the memory
    --
    --    Use             :  sram_l1 := SRAM_Initialize ("lsb_of_RAM",1048576,1,"0");
--********************************************************************************
        
	impure    Function SRAM_Initialize ( Constant name            : IN string;
                               Constant length          : IN POSITIVE;
                               Constant width           : IN POSITIVE;
                               Constant default_word    : IN std_logic_vector
                             ) return mem_id_type;

	impure    Function SRAM_Initialize_u ( Constant name            : IN string;
                               Constant length          : IN POSITIVE;
                               Constant width           : IN POSITIVE;
                               Constant default_word    : IN std_ulogic_vector
                             ) return mem_id_type;

--********************************************************************************
    --    Procedure Name  :  Mem_Read
    --
    --    Purpose         :  To read a "word" from memory
    --
    --    Parameters      :  mem_id    -  ptr to memory data structure
    --                       address   -  address to read from
    --                       data      -  contents of memory location
    --                       
    --
    --    NOTE            :  a read refreshes row of a DRAM
    --
    --    Use             :  Mem_Read (ROM1, "100100111", data_bus);
--********************************************************************************

    Procedure Mem_Read (  Variable mem_id    : INOUT mem_id_type;
                          Constant address   : IN std_ulogic_vector;
                          Variable data      : OUT std_ulogic_vector
                       );

--********************************************************************************
    --    Procedure Name  :  Mem_Write
    --
    --    Purpose         :  To write a "word" to memory
    --
    --    Parameters      :  mem_id    -  ptr to memory data structure
    --                       address   -  address to read from
    --                       data      -  "word" to be written to memory
    --
    --    NOTE            :  a write refreshes row of a DRAM
    --
    --    Use             :  Mem_Write (ROM1, "100100111", "10X1");
--********************************************************************************
        
    Procedure Mem_Write (  Variable mem_id    : INOUT mem_id_type;
                           Constant address   : IN std_ulogic_vector;
                           Constant data      : IN std_ulogic_vector
                        );

END mem_model;






PACKAGE BODY mem_model is

    Type D1_b_ulogic_type is array(bit) of std_ulogic;
    type hex_ray is array(1 to 16) of character;
    type IDENTIFIER is (HEX_NUM1, COMMENT1, WIDTH1, DEFAULT1, COLON1, DOTDOT1, BLANK1, SYN_ERROR1);
    type digit_to_hex_type is array(0 to 15) of character;

    -- mentor doesn't like the subtype UX01  -  "resolved sybyte cannot be used as a discrete range"
    type UX01_1DRAY is array(std_ulogic range 'U' to '1') of bit;

    -------------------------------------------------------------------------------------------
    --  THE FOLLOWING CONSTANTS MAY BE CHANGED BY THE USER TO CUSTOMIZE STD_MEMPAK
    -------------------------------------------------------------------------------------------

    -- defines the number of bits used to represent an integer on the machine used to run the vhdl simulator
    CONSTANT IntegerBitLength : INTEGER := 32;

    -- defines the maximum length of strings in this package

    CONSTANT MAX_STR_LEN : NATURAL := 256;

    -- constants used to map X's and U's  in an address to valid values
    
    CONSTANT ADDRESS_X_MAP : BIT := '1';
    CONSTANT ADDRESS_U_MAP : BIT := '1';
    CONSTANT ADDRESS_MAP : UX01_1DRAY :=
                           (ADDRESS_U_MAP, ADDRESS_X_MAP, '0', '1');

    -- constants used to map X's and U's in memory locations to a bit value 
    -- when a bit or a bit_vector is returned by the memory read operation
    
    CONSTANT DATA_X_MAP : BIT := '1';
    CONSTANT DATA_U_MAP : BIT := '1';
    CONSTANT DATA_MAP : UX01_1DRAY :=
                        (DATA_U_MAP, DATA_X_MAP, '0', '1');

    -- constants setting collumn size of SRAM's and ROM's so that entire
    -- memory does not have to be allocated if it is not used.
    
    CONSTANT SRAM_COL_SIZE : NATURAL := 1024;
    CONSTANT ROM_COL_SIZE : NATURAL := 1024;

    -- constant used to enable/disable certain warning assertions
    CONSTANT MEM_WARNINGS_ON : BOOLEAN := TRUE;

    -- constant used to determine how many words per line to output when doing a memory dump
    CONSTANT WORDS_PER_LINE : POSITIVE := 16;


    ----------------------------------------------------------------------------------------------------------
    -- CONSTANTS THAT SHOULD NOT BE MODIFIED
    -- These are used by the package to perform various conversions, comparisions, etc.
    ----------------------------------------------------------------------------------------------------------

    CONSTANT DIGIT_TO_HEX : digit_to_hex_type := ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
    CONSTANT hex : hex_ray := ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
    CONSTANT bit_to_std_ulogic : D1_b_ulogic_type := ('0', '1');
    CONSTANT SPACESTR : STRING(1 to 20) := "                    ";
    CONSTANT SPACE : CHARACTER :=  ' ';
    CONSTANT TAB   : CHARACTER := HT;

    


function StrLen1 ( Constant l_str : IN string ) return NATURAL is

Variable alias_l_str : string(1 to l_str'length) := l_str;
Variable i : integer := 1;

begin
    while ( (i <= l_str'length) and (alias_l_str(i) /= NUL) ) loop
        i := i + 1;
    end loop;
    i := i - 1;
    return i;
end;    

function to_str (Constant dd : IN std_logic) return Character is

begin
    case dd is
        when '1' => return '1';
        when '0' => return '0';
        when 'U' => return 'U';
        when 'X' => return 'X';
        when 'L' => return 'L';
        when 'H' => return 'H';
        when '-' => return '-';
        when 'Z' => return 'Z';
        when 'W' => return 'W';
    end case;
end;

function to_str (Constant dd : IN bit) return character is

begin
  if dd = '0' then
      return '0';
  else
      return '1';
  end if;
end;
    
function i_to_str (Constant int : IN integer) return string is

Constant length : integer := 33;
Variable i, len, pos : integer;
Variable str : string (1 to length);
Variable tint : integer := int;
Variable temp : Character;
Variable negative : BOOLEAN := FALSE;

begin
   for i in 1 to  length loop
     str(i) := ' ';
   end loop;
   if (tint < 0 ) then
      tint := -tint;
      negative := TRUE;
   end if;
   i := length;
   while (  (i >= 1 ) and (tint /= 0)) loop
       str(i) := CHARACTER'Val(48 + (tint mod 10));
       tint := tint/10;
       i := i - 1;
   end loop;
   if (NEGATIVE) then
      str(i) := '-';
      i := i - 1;
   end if;
   len := length - i;
   pos := i + 1;
   for i in 1 to len loop
     str(i) := str(pos);
     pos := pos + 1;
   end loop;
   if (len = 0) then
       len := 1;
       str(1) := '0';
   end if;
   return  (str(1 to len));
   
end;

function v_to_str  (Constant vect : IN bit_vector) return string is

Variable str : string( 1 to vect'length);
Variable alias_vect : bit_vector(1 to vect'length) := vect;
Variable i : integer;

begin
    for i in 1 to vect'length loop
        case alias_vect(i) is
          when '1' => str(i) := '1';
          when '0' => str(i) := '0';
        end case;
    end loop;
    return(str);
end;


function v_to_str  (Constant vect : IN std_logic_vector) return string is

Variable str : string( 1 to vect'length);
Variable alias_vect : std_logic_vector(1 to vect'length) := vect;
Variable i : integer;

begin
    for i in 1 to vect'length loop
        case alias_vect(i) is
          when '1' => str(i) := '1';
          when '0' => str(i) := '0';
          when 'U' => str(i) := 'U';
          when 'X' => str(i) := 'X';
          when 'L' => str(i) := 'L';
          when 'H' => str(i) := 'H';
          when '-' => str(i) := '-';
          when 'Z' => str(i) := 'Z';
          when 'W' => str(i) := 'W';
        end case;
    end loop;
    return(str);
end;

-- used to return a printable string for the memory name
function pstr ( Constant name : in string ) return string is

   variable j : integer;

begin
   j := 1;
   while ( (j < name'length) and (name(j) /= nul) ) loop
      j := j + 1;
   end loop;
   if (name(j) = nul) then
      j := j - 1;
   end if;
   return name(1 to j);
end;



    ---------------------------------------------------------------------------
    --    Function Name   :  minimum
    --
    --    PURPOSE         :  to determine the smaller of two integers
    --                       
    --    Parameters      :  int1 - first integer
    --                    :  int2 - second integer
    --
    --    Returned Value  :  integer - the smaller of int1 and int2
    --
    ---------------------------------------------------------------------------

    Function minimum ( Constant int1 : IN integer;
                       Constant int2 : IN integer
                     ) return integer is

    begin
         if (int1 < int2) then
            return int1;
        else
            return int2;
        end if;
    end;

--+-----------------------------------------------------------------------------
--|     Procedure Name : StrCpy1
--| 1.2.3
--|     Overloading    : None
--|
--|     Purpose        : Copy r_string to l_string.
--|
--|     Parameters     :
--|                      l_str    - output,  STRING, target string
--|                      r_str    - input, STRING, source string
--|
--|     Result         : 
--|
--|     NOTE           : If the length of target string is greater than
--|                      the source string, then target string is padded
--|                      with space characters on the right side and when
--|                      the length of target string is shorter than the 
--|                      length of source string only left most characters
--|                      of the source string will be be copied to the target.
--|                      
--| 
--|     USE            :
--|                      Variable s1: string(1 TO 8);
--|
--|                       StrCpy1(s1, "123456789A");
--|                       s1 will hold "12345678"      
--|-----------------------------------------------------------------------------
    PROCEDURE StrCpy1   ( VARIABLE l_str : OUT STRING;
                          CONSTANT r_str : IN  STRING) IS
       VARIABLE  l_len     : integer := l_str'LENGTH;
       VARIABLE  r_len     : integer := r_str'LENGTH;
       VARIABLE  r         : STRING ( 1 to r_len) := r_str;
       VARIABLE result     : STRING (1 to l_len);
       VARIABLE indx       : integer := 1;
    BEGIN
       assert (l_len > 0)
          report "StrCpy:  target string is of zero length "
          severity ERROR;
              
       while ( (indx <= r_len) and (indx <= l_len) and (r(indx) /= NUL) ) loop
          result(indx) := r(indx);
          indx := indx + 1;
       end loop;
       if (indx <= l_len) then
          result(indx) := NUL;
       end if;
       l_str := result;
       return;
    END StrCpy1;

    

--+---------------------------------------------------------------------------
--|     Procedure Name : fgetline1
--| 
--|     Overloading    : None
--|
--|     Purpose        : To read a line from the input TEXT file and 
--|                      save into a string. 
--|
--|     Parameters     :
--|                         l_str    -- output, STRING,
--|                         stream   -- input, TEXT, input file 
--|
--|     result         : string.
--|
--|     Note:          : The TEXT is defined in the package TEXTIO to be 
--|                      a  file of string.
--|     USE:           :
--|                      VARIABLE  line_buf : string(1 TO 256);
--|                      FILE      in_file : TEXT IS IN "file_text_in.dat";
--|                      
--|                        fgetline1(line_buf, in_file);
--|
--|                       Will read a line  from the file
--|                       file_text_in.dat  and place  into  line_buf.
--|
--|-----------------------------------------------------------------------------
   PROCEDURE fgetline1  ( VARIABLE l_str    : OUT STRING;
                         FILE stream   : TEXT;
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
                         VARIABLE line_ptr : INOUT LINE
                       ) IS
        VARIABLE str_copy   : STRING(1 TO MAX_STR_LEN + 1);
        VARIABLE ch         : character;
        VARIABLE indx       : NATURAL := 0;
   BEGIN
      If ( (line_ptr /= NULL) and (line_ptr'LENGTH > 0) ) then
          NULL;
      elsif ( not ENDFILE(stream) ) then
         READLINE(stream, line_ptr);
      else
         assert NOT MEM_WARNINGS_ON
            report " fgetline1 --- end of file text,  no text read "
            severity WARNING;
         l_str(l_str'left) := NUL;
         return;
      end if;
      while ( (line_ptr /= NULL) and (line_ptr'length /= 0) ) loop
         READ(line_ptr,ch);
         indx := indx + 1;
         str_copy(indx) := ch;
      end loop;
      str_copy(indx + 1) := NUL;
      strcpy1(l_str, str_copy);
      return;
   END;

   

--+----------------------------------------------------------------------------- 
--|     Function Name  : Is_White1
--| hidden.
--|     Overloading    : None 
--|  
--|     Purpose        : Test whether a character is a blank, a tab or 
--|                      a newline character.
--|
--|     Parameters     : 
--|                      c     - input   Character.
--| 
--|     Result         :Booelan -- True if the argument c is a blank or a tab(HT), 
--|                     or a line feed (LF), or carriage return (CR). false otherwise.   
--| 
--| 
--|     See Also       : Is_Space
--|----------------------------------------------------------------------------- 
     FUNCTION  Is_White1  ( CONSTANT c    : IN CHARACTER
                         ) RETURN BOOLEAN IS
         VARIABLE result : BOOLEAN;
     BEGIN
        IF ( (c = ' ') OR (c = HT)  OR (c = CR) OR (c=LF) ) THEN
             result := TRUE;
        ELSE
             result := FALSE;
        END IF;
        RETURN result;

     END; 
    
--+-----------------------------------------------------------------------------
--|     Function Name  : Find_NonBlank1
--| hidden 
--|     Overloading    : None
--|
--|     Purpose        : Find first non_blank character in a string.
--|
--|     Parameters     :
--|                      str_in    - input ,  
--|
--|     Result         : Natural, index of non_blank character. If string
--|                      has all the white character then str_in'LENGTH is
--|                      returned;
--|
--|     NOTE           :
--|
--|     Use            :
--|                      VARIABLE s_flag : String(1 TO 10) := "      TRUE"; 
--|                      VARIABLE idx: Natural 
--|
--|                       idx := Find_NonBlank1 (s_flag);
--|
--|-----------------------------------------------------------------------------
   FUNCTION Find_NonBlank1  ( CONSTANT str_in   : IN STRING
                           ) RETURN NATURAL IS
      VARIABLE str_copy :  STRING (1 TO str_in'LENGTH) := str_in;
      VARIABLE index    :  Natural := 1;
      VARIABLE ch       :  character;
       
    BEGIN
          loop
            EXIT WHEN (index > str_in'LENGTH);
            if Is_White1(str_copy(index)) then
                index := index + 1;
            else
                EXIT;
            end if;
          end loop;
          return index;
--      
-- old code
-- 
--        ch := str_copy(index);
--        while ( ( index < str_in'LENGTH) AND (Is_White1(ch) ) ) LOOP
--        	index := index + 1;
--              ch := str_copy(index);
--        end LOOP;
--        return index;
    END;

--+----------------------------------------------------------------------------- 
--|     Function Name  : To_Upper1
--| 1.
--|     Overloading    : None 
--|  
--|     Purpose        :Convert a string to upper case.
--|
--|     Parameters     : 
--|                      val     - input, string to be converted   
--| 
--|     Result         :  string .
--| 
--| 
--|     See Also       : To_Lower, Is_Upper, Is_Lower
--|----------------------------------------------------------------------------- 
    FUNCTION  To_Upper1  ( CONSTANT  val    : IN String
                         ) RETURN STRING IS
        VARIABLE result   : string (1 TO val'LENGTH) := val;
        VARIABLE ch       : character;
    BEGIN
        FOR i IN 1 TO val'LENGTH LOOP
            ch := result(i);
            EXIT WHEN ((ch = NUL) OR (ch = nul));
            IF ( ch >= 'a' and ch <= 'z') THEN
    	          result(i) := CHARACTER'VAL( CHARACTER'POS(ch) 
                                       - CHARACTER'POS('a')
                                       + CHARACTER'POS('A') );
            END IF;
    	END LOOP;
    	RETURN result;
    END To_Upper1;
    
--+-----------------------------------------------------------------------------
--|     Function Name  : From_HexString1
--| 
--|     Overloading    : None
--|
--|     Purpose        : Convert  from a Hex String to a bit_vector.
--|
--|     Parameters     :
--|                      str     - input ,  Hex string to be converted,
--|
--|     Result         : bit_vector
--|
--|     NOTE           : 
--|
--|     Use            :
--|                      VARIABLE b_vect : bit_vector( 15 DOWNTO 4) ; 
--|
--|                       b_vect := From_HexString1 ("   3DD   1010");
--|                       This statement will set b_vect  equal to "001111011101".
--|
--|-----------------------------------------------------------------------------
    FUNCTION From_HexString1   ( CONSTANT str   : IN STRING
                               ) RETURN bit_vector IS

      CONSTANT len         : Integer := 4 * str'LENGTH;
      CONSTANT hex_dig_len : Integer := 4;
      VARIABLE str_copy    : STRING (1 TO str'LENGTH) := To_Upper1(str);
      VARIABLE index       : Natural;
      VARIABLE ch          : character;
      VARIABLE i, idx      : Integer;
      VARIABLE invalid     : boolean := false;
      VARIABLE r           : bit_vector(1 TO len) ;
      VARIABLE result      : bit_vector(len - 1 DOWNTO 0) ;
      CONSTANT BIT_ZERO    : bit_vector(1 to 4) := "0000";
      CONSTANT BIT_ONE     : bit_vector(1 to 4) := "0001";
      CONSTANT BIT_TWO     : bit_vector(1 to 4) := "0010";
      CONSTANT BIT_THREE   : bit_vector(1 to 4) := "0011";
      CONSTANT BIT_FOUR    : bit_vector(1 to 4) := "0100";
      CONSTANT BIT_FIVE    : bit_vector(1 to 4) := "0101";
      CONSTANT BIT_SIX     : bit_vector(1 to 4) := "0110";
      CONSTANT BIT_SEVEN   : bit_vector(1 to 4) := "0111";
      CONSTANT BIT_EIGHT   : bit_vector(1 to 4) := "1000";
      CONSTANT BIT_NINE    : bit_vector(1 to 4) := "1001";
      CONSTANT BIT_TEN     : bit_vector(1 to 4) := "1010";
      CONSTANT BIT_ELEVEN  : bit_vector(1 to 4) := "1011";
      CONSTANT BIT_TWELVE  : bit_vector(1 to 4) := "1100";
      CONSTANT BIT_THIRTEEN: bit_vector(1 to 4) := "1101";
      CONSTANT BIT_FOURTEEN: bit_vector(1 to 4) := "1110";
      CONSTANT BIT_FIFTEEN : bit_vector(1 to 4) := "1111";
       
    BEGIN
      -- Check for null input
        IF (str'LENGTH = 0) THEN
		assert false
		report " From_HexString1  --- input string has zero length ";
                RETURN "";

        ELSIF  (str(str'LEFT) = NUL) THEN
		assert false
		report " From_HexString1  --- input string has nul character"
                        & " at the LEFT position "
                severity ERROR;
                RETURN "";  -- null  bit_vector
	END IF;
        -- find the position of the first non_white character
        index := Find_NonBlank1(str_copy);
        IF (index > str'length) THEN
		assert false
		report " From_HexString1  --- input string is empty  ";
                RETURN ""; 
        ELSIF (str_copy(index)=NUL) THEN
		assert false report " From_HexString1  -- first non_white character is a NUL ";
                RETURN "";
        END IF;

        i := 0;
        FOR idx IN index TO  str'length LOOP
		ch := str_copy(idx);
                EXIT WHEN ((Is_White1(ch)) OR (ch = NUL));                
		CASE ch IS
	          WHEN '0'        => r(i+1 TO i+ hex_dig_len) := BIT_ZERO;
        	  WHEN '1'        => r(i+1 TO i+ hex_dig_len) := BIT_ONE;
        	  WHEN '2'        => r(i+1 TO i+ hex_dig_len) := BIT_TWO;
        	  WHEN '3'        => r(i+1 TO i+ hex_dig_len) := BIT_THREE;
        	  WHEN '4'        => r(i+1 TO i+ hex_dig_len) := BIT_FOUR;
        	  WHEN '5'        => r(i+1 TO i+ hex_dig_len) := BIT_FIVE;
        	  WHEN '6'        => r(i+1 TO i+ hex_dig_len) := BIT_SIX;
        	  WHEN '7'        => r(i+1 TO i+ hex_dig_len) := BIT_SEVEN;
        	  WHEN '8'        => r(i+1 TO i+ hex_dig_len) := BIT_EIGHT;
        	  WHEN '9'        => r(i+1 TO i+ hex_dig_len) := BIT_NINE;
        	  WHEN 'A' | 'a'  => r(i+1 TO i+ hex_dig_len) := BIT_TEN;
        	  WHEN 'B' | 'b'  => r(i+1 TO i+ hex_dig_len) := BIT_ELEVEN;
        	  WHEN 'C' | 'c'  => r(i+1 TO i+ hex_dig_len) := BIT_TWELVE;
        	  WHEN 'D' | 'd'  => r(i+1 TO i+ hex_dig_len) := BIT_THIRTEEN;
        	  WHEN 'E' | 'e'  => r(i+1 TO i+ hex_dig_len) := BIT_FOURTEEN;
        	  WHEN 'F' | 'f'  => r(i+1 TO i+ hex_dig_len) := BIT_FIFTEEN;
       	  	  WHEN NUL        => exit;
        	  WHEN OTHERS  	  => -- a non  binary value was passed
       	  	                     invalid := TRUE;
         	       		     ASSERT FALSE
                                     REPORT "From_HexString1(str(" & i_to_str(idx) & ") => " 
                                     & ch & ") is an invalid character"
	                	     SEVERITY ERROR;
       	       	END CASE;
                i := i + hex_dig_len;
	END LOOP;
     -- check for invalid character in the string
        if ( invalid ) THEN
           r(1 TO i) := (OTHERS => '0');
        end if;
        result(i - 1 DOWNTO 0) := r(1 TO i);
        return result(i - 1 DOWNTO 0);     -- return slice of result

    END;

    -------------------------------------------------------------------------------
    --     Function Name  : RegFill1
    -- 1.7.4
    --     Overloading    : None
    --
    --     Purpose        : Fill an std_logic_vector with a given value
    --
    --     Parameters     :
    --                      SrcReg     - input  std_logic_vector, the  logic vector to be read.
    --                      DstLength  - input  NATURAL, length of the return logic vector.
    --                      FillVal    - input  std_ulogic, default is '0'
    --
    --     Result         : std_logic_vector of length DstLength
    --
    --     NOTE           : The length of the return logic vector  is specified by the
    --                      parameter 'DstLength'. The input logic vector will
    --                      be  filled with the FillVal
    --
    --     Use            :
    --                      VARIABLE vect : std_logic_vector ( 15 DOWNTO 0 );
    --                      vect := RegFill1 ( "00000101", 16, 'U');
    --
    --     See Also       : SignExtend
   -------------------------------------------------------------------------------
    FUNCTION RegFill1   ( CONSTANT SrcReg      : IN std_logic_vector;
                         CONSTANT DstLength   : IN NATURAL;
                         CONSTANT FillVal     : IN std_ulogic   := '0'
                       ) RETURN std_logic_vector IS
      CONSTANT reslen : INTEGER := DstLength;
      VARIABLE result : std_logic_vector (reslen - 1 DOWNTO 0) := (OTHERS => '0');
      VARIABLE reg    : std_logic_vector (SrcReg'LENGTH - 1 DOWNTO 0) := SrcReg;
    BEGIN
     --  null range check
      IF (SrcReg'LENGTH = 0) THEN
         IF (DstLength = 0) THEN
            ASSERT FALSE
            REPORT " RegFill1 --- input  has null range and" &
                " Destination also has null range. "
            SEVERITY ERROR;
            RETURN result ; 
         ELSE
            ASSERT FALSE
            REPORT " RegFill1 --- input  has null range"
            SEVERITY ERROR;
            result := (OTHERS => FillVal);
            RETURN result ; 
         END IF;
 
      ELSIF (DstLength = 0) THEN
          ASSERT false
          REPORT "RegFill1 --- Destination has null range "
          SEVERITY ERROR;
          RETURN result;   
 
      ELSIF (DstLength <= SrcReg'LENGTH) THEN
                        -- no need to sign extend
         ASSERT (DstLength = SrcReg'LENGTH)
         REPORT " RegFill1 ---  Destination length is less than source"
         SEVERITY ERROR;
         RETURN reg;        -- return the input data without any change
 
      ELSE
           result(SrcReg'LENGTH - 1 DOWNTO 0) := reg;
        -- Fill the MSB's of result with the given fill value.
          For i IN reslen - 1 DOWNTO SrcReg'LENGTH  Loop
             result(i) := FillVal;
          END LOOP;
      END IF;
    
      -- convert to X01
         result := To_X01(result);
    -- That's all
       RETURN result;
    END;

    
    
  --+-----------------------------------------------------------------------------
  --|     Function Name  : bv_To_StdLogicVector
  --|
  --|     Overloading    : 
  --|
  --|     Purpose        : Translate a BIt_VECTOR into an std_logic_vector.
  --|
  --|     Parameters     : SrcVect - input  bit_vector , the value to be 
  --|                                       translated.
  --|                      width   - input  NATURAL, length of the return vector.
  --|                                Default is IntegerBitLength (Machine integer length).
  --|
  --|     Result        : Std_logic_vector.
  --|
  --|     NOTE          : ****** this function not visible to the user **********
  --|-----------------------------------------------------------------------------

  -- ****  function modified so as not to produce an assertion for a zero length vector
  
  FUNCTION bv_To_StdLogicVector ( CONSTANT SrcVect  : IN Bit_Vector;
                                  CONSTANT width    : IN Natural := 0
                                ) RETURN Std_Logic_Vector IS
                                
   VARIABLE len        : INTEGER := SrcVect'LENGTH;
   VARIABLE result     : Std_Logic_Vector(width - 1 DOWNTO 0) := (OTHERS=>'0');
   VARIABLE loc_res    : Std_Logic_Vector(len  - 1 DOWNTO 0) := (OTHERS =>'0');
   VARIABLE vect_copy : Bit_Vector(len - 1 DOWNTO 0) := SrcVect;
     
   BEGIN

       IF (SrcVect'LENGTH = 0) THEN

         return loc_res;

       ELSE
           FOR i IN 0 TO len - 1  LOOP
              CASE vect_copy(i) IS 
                 WHEN '0'   =>
                                loc_res(i) := '0';
                 WHEN '1'   =>
                                loc_res(i) := '1';
              END CASE;
           END LOOP;  
           
           IF (width = 0)  THEN
               return loc_res;
           ELSIF (width <= SrcVect'LENGTH) THEN
               result := loc_res(width - 1 DOWNTO 0);
           ELSIF (width > SrcVect'LENGTH) THEN
               result := RegFill1(loc_res, width, '0');
           END IF;
           RETURN result;
        
       END IF;

    END;
    

    FUNCTION bv_to_hexstr ( CONSTANT val      : IN BIT_VECTOR
                          )  RETURN STRING IS
                          
      CONSTANT hex_len : integer := (val'LENGTH + 3) / 4;
      VARIABLE bin_str : STRING(1 to val'LENGTH);
      VARIABLE hex_str : STRING(1 to hex_len);
      VARIABLE hex_char : STRING(1 to 4);
      VARIABLE bit_index : integer;
      VARIABLE extended_bin_str : STRING(1 to hex_len * 4) := (others => '0');

            
    BEGIN
      bin_str := v_to_str (val);
      if ( (val'LENGTH mod 4) /= 0 ) then
         extended_bin_str ( 5 - (val'LENGTH mod 4) to hex_len * 4 ) := bin_str;
      else
         extended_bin_str := bin_str;
      end if;
      FOR i IN 1 TO hex_len LOOP
        bit_index := ((i - 1) * 4) + 1;
        hex_char := extended_bin_str(bit_index To bit_index + 3);
        CASE hex_char IS
          WHEN "0000" => hex_str(i) := '0'; 
	  WHEN "0001" => hex_str(i) := '1'; 
	  WHEN "0010" => hex_str(i) := '2'; 
	  WHEN "0011" => hex_str(i) := '3'; 
	  WHEN "0100" => hex_str(i) := '4'; 
	  WHEN "0101" => hex_str(i) := '5'; 
	  WHEN "0110" => hex_str(i) := '6'; 
	  WHEN "0111" => hex_str(i) := '7'; 
          WHEN "1000" => hex_str(i) := '8'; 
          WHEN "1001" => hex_str(i) := '9'; 
	  WHEN "1010" => hex_str(i) := 'A'; 
	  WHEN "1011" => hex_str(i) := 'B'; 
	  WHEN "1100" => hex_str(i) := 'C'; 
	  WHEN "1101" => hex_str(i) := 'D'; 
          WHEN "1110" => hex_str(i) := 'E'; 
	  WHEN "1111" => hex_str(i) := 'F'; 
          WHEN OTHERS => null; 
        END CASE;
      END LOOP;
      return (hex_str);
 
    END;
    
    ---------------------------------------------------------------------------
    --    Function Name   :  vector_size
    --
    --    PURPOSE         :  to determine the maximum number of bits needed to
    --                       represent an integer
    --
    --    Parameters      :  int - integer whose bit width is determined
    --
    --    Returned Value  :  NATURAL - # of bits needed
    --
    ---------------------------------------------------------------------------    

    function vector_size ( Constant int : IN integer ) return natural is

    variable i : integer := int;
    variable size : integer := 0;

    begin
        while i > 0 loop
            i := i / 2;
            size := size + 1;
        end loop;
        return size;
    end;
    
    ---------------------------------------------------------------------------
    --    Function Name   :  address_trans
    --
    --    Purpose         :  to translate an address in vector form to a
    --                       NATURAL
    --
    --    Parameters      :  addr    - address to be translated
    --
    --    Returned Value  :  NATURAL - address as a natural number
    --
    --    NOTE            :  *****  this procedure is NOT user visible *******
    --
    --    Use             :  address_trans(addr)
    ---------------------------------------------------------------------------

    Function address_trans ( Constant mem_length : IN POSITIVE;
                             Constant addr       : IN std_logic_vector
                           ) return NATURAL is

    Variable nad, power : NATURAL;
    Variable uonce : BOOLEAN := TRUE;
    Variable xonce : BOOLEAN := TRUE;
    Variable vect_size : integer := vector_size(mem_length - 1);
    Variable talias_addr : std_logic_vector(addr'length - 1 downto 0) := To_UX01(addr);
    Variable alias_addr : std_logic_vector(vect_size - 1 downto 0) := (others => To_StdULogic(ADDRESS_X_MAP));
    Variable temp_vect : bit_vector(vect_size - 1 downto 0);    
                                                      
    begin
        nad := 0;
        power := 1;
        alias_addr( minimum(vect_size, addr'length)  - 1 downto 0) :=
                                                 talias_addr( minimum(vect_size,addr'length) - 1 downto 0 );
        assert ( (vect_size >= addr'length) or NOT MEM_WARNINGS_ON )
            report "Bit width of address vector greater than that needed to access the entire memory."
                   & LF & SPACESTR & "passed address bit width:  " & i_to_str(addr'length)
                   & LF & SPACESTR & "required address bit width:  " & i_to_str(vect_size)
            severity WARNING;
        assert ( (vect_size <= addr'length) or NOT MEM_WARNINGS_ON )
            report "Bit width of address vector less than that needed to access the entire memory."
                   & LF & SPACESTR & "Resulting X's being mapped to:  " & to_str(ADDRESS_X_MAP)
                   & LF & SPACESTR & "passed address bit width:  " & i_to_str(addr'length)
                   & LF & SPACESTR & "required address bit width:  " & i_to_str(vect_size)
            severity WARNING;
            
        for i IN 0 to vect_size - 1 loop
            if ((alias_addr(i) = 'U') and MEM_WARNINGS_ON and uonce) then
                uonce := FALSE;
                assert FALSE
                   report "Address contains a U - it is being mapped to:  " & to_str(ADDRESS_U_MAP)
                          severity WARNING;
            end if;
            if ((alias_addr(i) = 'X') and MEM_WARNINGS_ON and xonce) then
                xonce := FALSE;
                assert false
                   report "Address contains an X - it is being mapped to:  " & to_str(ADDRESS_X_MAP)
                          severity WARNING;
            end if;
            temp_vect(i) := ADDRESS_MAP(alias_addr(i));
            nad := nad + (power * bit'pos(temp_vect(i)));
            power := power * 2;
        end loop;
        return nad;
    end;
           
    Function address_trans_u ( Constant mem_length :  IN POSITIVE;
                               Constant addr       :  IN std_ulogic_vector
                             ) return NATURAL is

    Variable nad, power : NATURAL;
    Variable uonce : BOOLEAN := TRUE;
    Variable xonce : BOOLEAN := TRUE;
    Variable talias_addr : std_ulogic_vector(addr'length - 1 downto 0) := To_UX01(addr);    
    Variable vect_size : integer := vector_size(mem_length - 1);
    Variable alias_addr : std_ulogic_vector(vect_size - 1 downto 0) := (others => To_StdULogic(ADDRESS_X_MAP));
    Variable temp_vect : bit_vector(vect_size - 1 downto 0);
                                                      
    begin
        nad := 0;
        power := 1;
        alias_addr( minimum(vect_size, addr'length)  - 1 downto 0) :=
                                                       talias_addr( minimum(vect_size,addr'length) - 1 downto 0);
        assert ( (vect_size >= addr'length) or NOT MEM_WARNINGS_ON )
            report "Bit width of address vector greater than that needed to access the entire memory."
                   & LF & SPACESTR & "passed address bit width:  " & i_to_str(addr'length)
                   & LF & SPACESTR & "required address bit width:  " & i_to_str(vect_size)
            severity WARNING;
        assert ( (vect_size <= addr'length) or NOT MEM_WARNINGS_ON )
            report "Bit width of address vector less than that needed to access the entire memory."
                   & LF & SPACESTR & "Resulting X's being mapped to:  " & to_str(ADDRESS_X_MAP)            
                   & LF & SPACESTR & "passed address bit width:  " & i_to_str(addr'length)
                   & LF & SPACESTR & "required address bit width:  " & i_to_str(vect_size)
            severity WARNING;
            
        for i IN 0 to vect_size - 1 loop
            if ((alias_addr(i) = 'U') and MEM_WARNINGS_ON and uonce) then
                uonce := FALSE;
                assert false
                   report "Address contains a U - it is being mapped to:  " & to_str(ADDRESS_U_MAP)
                          severity WARNING;
            end if;
            if ((alias_addr(i) = 'X') and MEM_WARNINGS_ON and xonce) then
                xonce := FALSE;
                assert false
                   report "Address contains an X - it is being mapped to:  " & to_str(ADDRESS_X_MAP)
                          severity WARNING;
            end if;
            temp_vect(i) := ADDRESS_MAP(alias_addr(i));
            nad := nad + (power * bit'pos(temp_vect(i)));
            power := power * 2;
        end loop;