
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

package fixed_ja is


	type ufixed_t is array (integer range <>) of STD_LOGIC;
	type sfixed_t is array (integer range <>) of STD_LOGIC;
	type ufixed_array_t is array (natural range <>, integer range <>) of STD_LOGIC;
	type sfixed_array_t is array (natural range <>, integer range <>) of STD_LOGIC;

	type round_mode_t is (none, round_to_zero, round_pos_infinity, round_neg_infinity, round_half_up, round_half_down, round_nearest, round_convergent);
	type saturate_mode_t is (none, saturate);
	
		-- Declare functions and procedure

	constant ASSERT_NO_WARN : boolean := false;
	constant default_round_mode : round_mode_t := none;
	constant default_saturate_mode : saturate_mode_t := none;
	
	-- null array constants
	constant NAUF : ufixed_t (0 downto 1)         := (others => '0');
	constant NASF : sfixed_t (0 downto 1)         := (others => '0');
	constant NSLV : STD_LOGIC_VECTOR (0 downto 1) := (others => '0');

	-- Constructor helpers
	-- Use: variable v8u2 : ufixed_t(ufixed(8,2)'range);
	function uproto (nbits : integer; nbits_int : integer) return ufixed_t;

	-- Use: variable v8s2 : sfixed_t(sfixed(8,2)'range);
	function sproto (nbits : integer; nbits_int : integer) return sfixed_t;

	function uproto (a : ufixed_t; op : character; b : ufixed_t) return ufixed_t;
	function sproto (a : sfixed_t; op : character; b : sfixed_t) return sfixed_t;

	-- Conversion Functions
	function to_ufixed(src : ufixed_t) return ufixed_t;
	function to_sfixed(src : sfixed_t) return sfixed_t;
	function to_ufixed(src : sfixed_t) return ufixed_t;
	function to_sfixed(src : ufixed_t) return sfixed_t;

	function to_ufixed
	(
		src : ufixed_t;
		nbits : integer;
		nbits_int : integer;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return ufixed_t;
	
	function to_ufixed
	(
		src : ufixed_t; 
		proto : ufixed_t;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return ufixed_t;
	
	function to_sfixed
	(
		src : sfixed_t;
		nbits : integer;
		nbits_int : integer;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return sfixed_t;
	
	function to_sfixed
	(
		src : sfixed_t; 
		proto : sfixed_t;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return sfixed_t;

	-- fixed <= integer
	function to_ufixed (src : integer; nbits : integer; nbits_int : integer) return ufixed_t;
	function to_ufixed (src : integer; proto : ufixed_t) return ufixed_t;

	-- fixed <= integer
	function to_sfixed (src : integer; nbits : integer; nbits_int : integer) return sfixed_t;
	function to_sfixed (src : integer; proto : sfixed_t) return sfixed_t;

	-- ufixed <= unsigned
	function to_ufixed (src : unsigned; nbits : integer; nbits_int : integer) return ufixed_t;
	function to_ufixed (src : unsigned; proto : ufixed_t) return ufixed_t;
	
	-- sfixed <= signed
	function to_sfixed (src : signed; nbits : integer; nbits_int : integer) return sfixed_t;
	function to_sfixed (src : signed; proto : sfixed_t) return sfixed_t;

	-- fixed <= slv
	function to_ufixed (src : STD_LOGIC_VECTOR;	nbits : integer; nbits_int : integer) return ufixed_t;
	function to_ufixed (src : STD_LOGIC_VECTOR;	proto : ufixed_t) return ufixed_t;
	function to_sfixed (src : STD_LOGIC_VECTOR;	nbits : integer; nbits_int : integer) return sfixed_t;
	function to_sfixed (src : STD_LOGIC_VECTOR;	proto : sfixed_t) return sfixed_t;
	
	-- ufixed <= real
	function to_ufixed 
	(
		src : real;
		nbits : integer;
		nbits_int : integer;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return ufixed_t;
	
	function to_ufixed 
	(	
		src : real;
		proto : ufixed_t;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return ufixed_t;
	
	-- sfixed <= real
	function to_sfixed
	(
		src : real;
		nbits : integer;
		nbits_int : integer;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return sfixed_t;
	
	function to_sfixed 
	(
		src : real;
		proto : sfixed_t;
		rnd_mode : round_mode_t := default_round_mode;
		sat_mode : saturate_mode_t := default_saturate_mode
	) return sfixed_t;

	-- Slicing functions for unconstrained array types
	function to_ufixed(src : ufixed_array_t; index : integer) return ufixed_t;
	function to_sfixed(src : sfixed_array_t; index : integer) return sfixed_t;
	
	-- ufixed <= string
	function to_ufixed (src : string) return ufixed_t;

	-- sfixed <= string
	function to_sfixed (src : string) return sfixed_t;

	-- real <= ufixed
	function to_real(src : ufixed_t) return real;

	-- real <= sfixed
	function to_real(src : sfixed_t) return real;
	
	-- slv <= ufixed
	function to_slv(src : ufixed_t) return std_logic_vector;

	-- slv <= sfixed
	function to_slv(src : sfixed_t) return std_logic_vector;
	
	-- UNSIGNED <= ufixed
	function to_unsigned (src : ufixed_t) return UNSIGNED;

	-- SIGNED <= sfixed
	function to_signed (src : sfixed_t) return SIGNED;

	-- integer <= ufixed
	function to_integer (src : ufixed_t) return integer;

	-- integer <= sfixed
	function to_integer (src : sfixed_t) return integer;

	function to_string(src : ufixed_t) return string;
	function to_string(src : sfixed_t) return string;
	function to_string(src : std_logic_vector) return string;
	
	-------------------------------------------------------------
	-- Arithmetic shift left
	-------------------------------------------------------------
	function "sla" (src : ufixed_t; count : integer) return ufixed_t;
	function "sla" (src : sfixed_t; count : integer) return sfixed_t;

	-------------------------------------------------------------
	-- Arithmetic shift right
	-------------------------------------------------------------
	function "sra" (src : ufixed_t; count : integer) return ufixed_t;
	function "sra" (src : sfixed_t; count : integer) return sfixed_t;
	
	-------------------------------------------------------------
	-- Multiplication
	-------------------------------------------------------------
	function "*" (a : ufixed_t; b : ufixed_t) return ufixed_t;
	function "*" (a : sfixed_t; b : sfixed_t) return sfixed_t;
	function "*" (a : ufixed_t; b : sfixed_t) return sfixed_t;
	function "*" (a : sfixed_t; b : ufixed_t) return sfixed_t;

	-------------------------------------------------------------
	-- Sum
	-------------------------------------------------------------
	function "+" (a : ufixed_t; b : integer) return ufixed_t;
	function "+" (a : sfixed_t; b : integer) return sfixed_t;
	function "+" (a : ufixed_t; b : unsigned) return ufixed_t;
	function "+" (a : sfixed_t; b : signed) return sfixed_t;
	function "+" (a : ufixed_t; b : ufixed_t) return ufixed_t;
	function "+" (a : sfixed_t; b : sfixed_t) return sfixed_t;
	function "+" (a : ufixed_t; b : sfixed_t) return sfixed_t;
	function "+" (a : sfixed_t; b : ufixed_t) return sfixed_t;
	function "+" (a : ufixed_t; b : std_logic) return ufixed_t;
	function "+" (a : sfixed_t; b : std_logic) return sfixed_t;


	-------------------------------------------------------------
	-- Difference
	-------------------------------------------------------------
	function "-" (a : ufixed_t; b : integer) return ufixed_t;
	function "-" (a : sfixed_t; b : integer) return sfixed_t;
	function "-" (a : ufixed_t; b : unsigned) return ufixed_t;
	function "-" (a : sfixed_t; b : signed) return sfixed_t;
	function "-" (a : ufixed_t; b : ufixed_t) return ufixed_t;
	function "-" (a : sfixed_t; b : sfixed_t) return sfixed_t;
	function "-" (a : ufixed_t; b : sfixed_t) return sfixed_t;
	function "-" (a : sfixed_t; b : ufixed_t) return sfixed_t;
	function "-" (a : ufixed_t; b : std_logic) return ufixed_t;
	function "-" (a : sfixed_t; b : std_logic) return sfixed_t;

	-------------------------------------------------------------
	-- Equality
	-------------------------------------------------------------
	function "=" (a : ufixed_t; b : ufixed_t) return boolean;
	function "=" (a : sfixed_t; b : sfixed_t) return boolean;
	function "=" (a : ufixed_t; b : sfixed_t) return boolean;
	function "=" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Inequality
	-------------------------------------------------------------
	function "/=" (a : ufixed_t; b : ufixed_t) return boolean;
	function "/=" (a : sfixed_t; b : sfixed_t) return boolean;
	function "/=" (a : ufixed_t; b : sfixed_t) return boolean;
	function "/=" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Less than
	-------------------------------------------------------------
	function "<" (a : ufixed_t; b : ufixed_t) return boolean;
	function "<" (a : sfixed_t; b : sfixed_t) return boolean;
	function "<" (a : ufixed_t; b : sfixed_t) return boolean;
	function "<" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Greater than
	-------------------------------------------------------------
	function ">" (a : ufixed_t; b : ufixed_t) return boolean;
	function ">" (a : sfixed_t; b : sfixed_t) return boolean;
	function ">" (a : ufixed_t; b : sfixed_t) return boolean;
	function ">" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Less or equal than
	-------------------------------------------------------------
	function "<=" (a : ufixed_t; b : ufixed_t) return boolean;
	function "<=" (a : sfixed_t; b : sfixed_t) return boolean;
	function "<=" (a : ufixed_t; b : sfixed_t) return boolean;
	function "<=" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Greater or equal than
	-------------------------------------------------------------
	function ">=" (a : ufixed_t; b : ufixed_t) return boolean;
	function ">=" (a : sfixed_t; b : sfixed_t) return boolean;
	function ">=" (a : ufixed_t; b : sfixed_t) return boolean;
	function ">=" (a : sfixed_t; b : ufixed_t) return boolean;
	
	-------------------------------------------------------------
	-- Unary Arithmetic Operators
	-------------------------------------------------------------
	function "abs" (src : sfixed_t) return sfixed_t;
	function "-" (src : ufixed_t) return sfixed_t;
	function "-" (src : sfixed_t) return sfixed_t;

	-------------------------------------------------------------
	-- Misc. Operators
	-------------------------------------------------------------
	function ipart (src : ufixed_t) return ufixed_t;
	function fpart (src : ufixed_t) return ufixed_t;
	function ipart (src : sfixed_t) return sfixed_t;
	function fpart (src : sfixed_t) return sfixed_t;

	-------------------------------------------------------------
	-- Print function
	-------------------------------------------------------------
	procedure print_info(src : in ufixed_t; prefix : in string);
	procedure print_info(src : in sfixed_t; prefix : in string);
	procedure print_info(src : in string; prefix : in string);
	
	-------------------------------------------------------------
	-- Helpers
	-------------------------------------------------------------
	function cmsb(src : ufixed_t) return integer;
	function clsb(src : ufixed_t) return integer;

	function MIN (X, Y: INTEGER) return INTEGER;
	function MAX (X, Y: INTEGER) return INTEGER;

	function "MOD" (X, Y: in REAL ) return REAL;
	function ipart(src : real) return real;
	function fpart(src : real) return real;
	
	function and_red(arg  : ufixed_t) return STD_ULOGIC;
	function nand_red(arg : ufixed_t) return STD_ULOGIC;
	function or_red(arg   : ufixed_t) return STD_ULOGIC;
	function nor_red(arg  : ufixed_t) return STD_ULOGIC;
	function xor_red(arg  : ufixed_t) return STD_ULOGIC;
	function xnor_red(arg : ufixed_t) return STD_ULOGIC;
	function and_red(arg  : sfixed_t) return STD_ULOGIC;
	function nand_red(arg : sfixed_t) return STD_ULOGIC;
	function or_red(arg   : sfixed_t) return STD_ULOGIC;
	function nor_red(arg  : sfixed_t) return STD_ULOGIC;
	function xor_red(arg  : sfixed_t) return STD_ULOGIC;
	function xnor_red(arg : sfixed_t) return STD_ULOGIC;

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

end; -- package fixed_ja;

