📄 numeric_bit-body.vhdl
字号:
-- --------------------------------------------------------------------------------- Copyright 1995 by IEEE. All rights reserved.---- This source file is considered by the IEEE to be an essential part of the use-- of the standard 1076.3 and as such may be distributed without change, except-- as permitted by the standard. This source file may not be sold or distributed-- for profit. This package may be modified to include additional data required-- by tools, but must in no way change the external interfaces or simulation-- behaviour of the description. It is permissible to add comments and/or-- attributes to the package declarations, but not to change or delete any-- original lines of the approved package declaration. The package body may be-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the-- standard.---- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT)---- Library : This package shall be compiled into a library symbolically-- : named IEEE.---- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3---- Purpose : This package defines numeric types and arithmetic functions-- : for use with synthesis tools. Two numeric types are defined:-- : -- > UNSIGNED: represents an UNSIGNED number in vector form-- : -- > SIGNED: represents a SIGNED number in vector form-- : The base element type is type BIT.-- : The leftmost bit is treated as the most significant bit.-- : Signed vectors are represented in two's complement form.-- : This package contains overloaded arithmetic operators on-- : the SIGNED and UNSIGNED types. The package also contains-- : useful type conversions functions, clock detection-- : functions, and other utility functions.-- :-- : If any argument to a function is a null array, a null array is-- : returned (exceptions, if any, are noted individually).---- Limitation :---- Note : No declarations or definitions shall be included in,-- : or excluded from this package. The "package declaration"-- : defines the types, subtypes and declarations of-- : NUMERIC_BIT. The NUMERIC_BIT package body shall be-- : considered the formal definition of the semantics of-- : this package. Tool developers may choose to implement-- : the package body in the most efficient manner available-- : to them.-- :-- ------------------------------------------------------------------------------- Version : 2.4-- Date : 12 April 1995-- -------------------------------------------------------------------------------==============================================================================--======================= Package Body =========================================--==============================================================================package body NUMERIC_BIT is -- null range array constants constant NAU: UNSIGNED(0 downto 1) := (others => '0'); constant NAS: SIGNED(0 downto 1) := (others => '0'); -- implementation controls constant NO_WARNING: BOOLEAN := FALSE; -- default to emit warnings --=========================Local Subprograms ================================= function MAX (LEFT, RIGHT: INTEGER) return INTEGER is begin if LEFT > RIGHT then return LEFT; else return RIGHT; end if; end MAX; function MIN (LEFT, RIGHT: INTEGER) return INTEGER is begin if LEFT < RIGHT then return LEFT; else return RIGHT; end if; end MIN; function SIGNED_NUM_BITS (ARG: INTEGER) return NATURAL is variable NBITS: NATURAL; variable N: NATURAL; begin if ARG >= 0 then N := ARG; else N := -(ARG+1); end if; NBITS := 1; while N > 0 loop NBITS := NBITS+1; N := N / 2; end loop; return NBITS; end SIGNED_NUM_BITS; function UNSIGNED_NUM_BITS (ARG: NATURAL) return NATURAL is variable NBITS: NATURAL; variable N: NATURAL; begin N := ARG; NBITS := 1; while N > 1 loop NBITS := NBITS+1; N := N / 2; end loop; return NBITS; end UNSIGNED_NUM_BITS; ------------------------------------------------------------------------------ -- this internal function computes the addition of two UNSIGNED -- with input carry -- * the two arguments are of the same length function ADD_UNSIGNED (L, R: UNSIGNED; C: BIT) return UNSIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; alias XL: UNSIGNED(L_LEFT downto 0) is L; alias XR: UNSIGNED(L_LEFT downto 0) is R; variable RESULT: UNSIGNED(L_LEFT downto 0); variable CBIT: BIT := C; begin for I in 0 to L_LEFT loop RESULT(I) := CBIT xor XL(I) xor XR(I); CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); end loop; return RESULT; end ADD_UNSIGNED; -- this internal function computes the addition of two SIGNED -- with input carry -- * the two arguments are of the same length function ADD_SIGNED (L, R: SIGNED; C: BIT) return SIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; alias XL: SIGNED(L_LEFT downto 0) is L; alias XR: SIGNED(L_LEFT downto 0) is R; variable RESULT: SIGNED(L_LEFT downto 0); variable CBIT: BIT := C; begin for I in 0 to L_LEFT loop RESULT(I) := CBIT xor XL(I) xor XR(I); CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); end loop; return RESULT; end ADD_SIGNED; ------------------------------------------------------------------------------ -- this internal procedure computes UNSIGNED division -- giving the quotient and remainder. procedure DIVMOD (NUM, XDENOM: UNSIGNED; XQUOT, XREMAIN: out UNSIGNED) is variable TEMP: UNSIGNED(NUM'LENGTH downto 0); variable QUOT: UNSIGNED(MAX(NUM'LENGTH, XDENOM'LENGTH)-1 downto 0); alias DENOM: UNSIGNED(XDENOM'LENGTH-1 downto 0) is XDENOM; variable TOPBIT: INTEGER; begin TEMP := "0"&NUM; QUOT := (others => '0'); TOPBIT := -1; for J in DENOM'RANGE loop if DENOM(J)='1' then TOPBIT := J; exit; end if; end loop; assert TOPBIT >= 0 report "DIV, MOD, or REM by zero" severity ERROR; for J in NUM'LENGTH-(TOPBIT+1) downto 0 loop if TEMP(TOPBIT+J+1 downto J) >= "0"&DENOM(TOPBIT downto 0) then TEMP(TOPBIT+J+1 downto J) := (TEMP(TOPBIT+J+1 downto J)) -("0"&DENOM(TOPBIT downto 0)); QUOT(J) := '1'; end if; assert TEMP(TOPBIT+J+1)='0' report "internal error in the division algorithm" severity ERROR; end loop; XQUOT := RESIZE(QUOT, XQUOT'LENGTH); XREMAIN := RESIZE(TEMP, XREMAIN'LENGTH); end DIVMOD; -----------------Local Subprograms - shift/rotate ops------------------------- function XSLL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is constant ARG_L: INTEGER := ARG'LENGTH-1; alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); begin if COUNT <= ARG_L then RESULT(ARG_L downto COUNT) := XARG(ARG_L-COUNT downto 0); end if; return RESULT; end XSLL; function XSRL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is constant ARG_L: INTEGER := ARG'LENGTH-1; alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); begin if COUNT <= ARG_L then RESULT(ARG_L-COUNT downto 0) := XARG(ARG_L downto COUNT); end if; return RESULT; end XSRL; function XSRA (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is constant ARG_L: INTEGER := ARG'LENGTH-1; alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; variable RESULT: BIT_VECTOR(ARG_L downto 0); variable XCOUNT: NATURAL := COUNT; begin if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG; else if (XCOUNT > ARG_L) then XCOUNT := ARG_L; end if; RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT); RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); end if; return RESULT; end XSRA; function XROL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is constant ARG_L: INTEGER := ARG'LENGTH-1; alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; variable COUNTM: INTEGER; begin COUNTM := COUNT mod (ARG_L + 1); if COUNTM /= 0 then RESULT(ARG_L downto COUNTM) := XARG(ARG_L-COUNTM downto 0); RESULT(COUNTM-1 downto 0) := XARG(ARG_L downto ARG_L-COUNTM+1); end if; return RESULT; end XROL; function XROR (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is constant ARG_L: INTEGER := ARG'LENGTH-1; alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; variable COUNTM: INTEGER; begin COUNTM := COUNT mod (ARG_L + 1); if COUNTM /= 0 then RESULT(ARG_L-COUNTM downto 0) := XARG(ARG_L downto COUNTM); RESULT(ARG_L downto ARG_L-COUNTM+1) := XARG(COUNTM-1 downto 0); end if; return RESULT; end XROR; ---------------- Local Subprograms - Relational Operators -------------------- -- General "=" for UNSIGNED vectors, same length -- function UNSIGNED_EQUAL (L, R: UNSIGNED) return BOOLEAN is begin return BIT_VECTOR(L) = BIT_VECTOR(R); end UNSIGNED_EQUAL; -- -- General "=" for SIGNED vectors, same length -- function SIGNED_EQUAL (L, R: SIGNED) return BOOLEAN is begin return BIT_VECTOR(L) = BIT_VECTOR(R); end SIGNED_EQUAL; -- -- General "<" for UNSIGNED vectors, same length -- function UNSIGNED_LESS (L, R: UNSIGNED) return BOOLEAN is begin return BIT_VECTOR(L) < BIT_VECTOR(R); end UNSIGNED_LESS; -- -- General "<" function for SIGNED vectors, same length -- function SIGNED_LESS (L, R: SIGNED) return BOOLEAN is -- Need aliases to assure index direction variable INTERN_L: SIGNED(0 to L'LENGTH-1); variable INTERN_R: SIGNED(0 to R'LENGTH-1); begin INTERN_L := L; INTERN_R := R; INTERN_L(0) := not INTERN_L(0); INTERN_R(0) := not INTERN_R(0); return BIT_VECTOR(INTERN_L) < BIT_VECTOR(INTERN_R); end SIGNED_LESS; -- -- General "<=" function for UNSIGNED vectors, same length -- function UNSIGNED_LESS_OR_EQUAL (L, R: UNSIGNED) return BOOLEAN is begin return BIT_VECTOR(L) <= BIT_VECTOR(R); end UNSIGNED_LESS_OR_EQUAL; -- -- General "<=" function for SIGNED vectors, same length -- function SIGNED_LESS_OR_EQUAL (L, R: SIGNED) return BOOLEAN is -- Need aliases to assure index direction variable INTERN_L: SIGNED(0 to L'LENGTH-1); variable INTERN_R: SIGNED(0 to R'LENGTH-1); begin INTERN_L := L; INTERN_R := R; INTERN_L(0) := not INTERN_L(0); INTERN_R(0) := not INTERN_R(0); return BIT_VECTOR(INTERN_L) <= BIT_VECTOR(INTERN_R); end SIGNED_LESS_OR_EQUAL; --====================== Exported Functions ================================== -- Id: A.1 function "abs" (ARG: SIGNED) return SIGNED is constant ARG_LEFT: INTEGER := ARG'LENGTH-1; variable RESULT: SIGNED(ARG_LEFT downto 0); begin if ARG'LENGTH < 1 then return NAS; end if; RESULT := ARG; if RESULT(RESULT'LEFT) = '1' then RESULT := -RESULT; end if; return RESULT; end "abs"; -- Id: A.2 function "-" (ARG: SIGNED) return SIGNED is constant ARG_LEFT: INTEGER := ARG'LENGTH-1; alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; variable RESULT: SIGNED(ARG_LEFT downto 0); variable CBIT: BIT := '1'; begin if ARG'LENGTH < 1 then return NAS; end if; for I in 0 to RESULT'LEFT loop RESULT(I) := not(XARG(I)) xor CBIT; CBIT := CBIT and not(XARG(I)); end loop; return RESULT; end "-"; --============================================================================ -- Id: A.3 function "+" (L, R: UNSIGNED) return UNSIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; constant R_LEFT: INTEGER := R'LENGTH-1; constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); begin if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; end if; return ADD_UNSIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); end "+"; -- Id: A.4 function "+" (L, R: SIGNED) return SIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; constant R_LEFT: INTEGER := R'LENGTH-1; constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); begin if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; end if; return ADD_SIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); end "+"; -- Id: A.5 function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED is begin return L + TO_UNSIGNED(R, L'LENGTH); end "+"; -- Id: A.6 function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED is begin return TO_UNSIGNED(L, R'LENGTH) + R; end "+"; -- Id: A.7 function "+" (L: SIGNED; R: INTEGER) return SIGNED is begin return L + TO_SIGNED(R, L'LENGTH); end "+"; -- Id: A.8 function "+" (L: INTEGER; R: SIGNED) return SIGNED is begin return TO_SIGNED(L, R'LENGTH) + R; end "+"; --============================================================================ -- Id: A.9 function "-" (L, R: UNSIGNED) return UNSIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; constant R_LEFT: INTEGER := R'LENGTH-1; constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); begin if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; end if; return ADD_UNSIGNED(RESIZE(L, SIZE), not(RESIZE(R, SIZE)), '1'); end "-"; -- Id: A.10 function "-" (L, R: SIGNED) return SIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; constant R_LEFT: INTEGER := R'LENGTH-1; constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); begin if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; end if; return ADD_SIGNED(RESIZE(L, SIZE), not(RESIZE(R, SIZE)), '1'); end "-"; -- Id: A.11 function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED is begin return L - TO_UNSIGNED(R, L'LENGTH); end "-"; -- Id: A.12 function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED is begin return TO_UNSIGNED(L, R'LENGTH) - R; end "-"; -- Id: A.13 function "-" (L: SIGNED; R: INTEGER) return SIGNED is begin return L - TO_SIGNED(R, L'LENGTH); end "-"; -- Id: A.14 function "-" (L: INTEGER; R: SIGNED) return SIGNED is begin return TO_SIGNED(L, R'LENGTH) - R; end "-"; --============================================================================ -- Id: A.15 function "*" (L, R: UNSIGNED) return UNSIGNED is constant L_LEFT: INTEGER := L'LENGTH-1; constant R_LEFT: INTEGER := R'LENGTH-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -