OpenCores
URL https://opencores.org/ocsvn/special_functions_unit/special_functions_unit/trunk

Subversion Repositories special_functions_unit

[/] [special_functions_unit/] [Open_source_SFU/] [exp2_vhdl/] [exp2_fp.vhd] - Rev 4

Compare with Previous | Blame | View Log

-- Proyecto				: EXPONENT BASE 2 IEEE754
-- Nombre de archivo	: exp2_fp.vhd
--	Titulo				: operacion exponencial base 2
-----------------------------------------------------------------------------	
-- Descripcion			: calcula la potencia en base de dos de un numero en
--							  formato IEEE754.
--
--		MANTISBITS 		: Numero de bits de la mantisa
--		EXPBITS			: Numero de bits del exponente
-- 	SEG				: Numero de segmentos utilizados para la aproximacion
--		SEGBITS			: Ancho del segmento
-- 	i_x				: Numero en formato numerico IEEE754
-- 	o_exp2			: Resultado en formato numerico IEEE754
-- 
-- Notas: 
--		las constantes correspondientes a los segmentos se encuentran en 
-- 	complemento a 2.
--		c_BX controla la cantidad de desplazamientos hacia la derecha para el
--		dato de entrada. Conforme se incrementa se aumenta la precision para
--		valores de entrada con exponente negativo, a su vez se incrementa el
--		numero de multiplexores para realizar el desplazamiento.
-----------------------------------------------------------------------------	
-- Universidad Pedagogica y Tecnologica de Colombia.
-- Facultad de ingenieria.
-- Escuela de ingenieria Electronica - extension Tunja.
-- 
-- Autor: Cristhian Fernando Moreno Manrique
-- Mayo 2020
-----------------------------------------------------------------------------	
 
library ieee;
	use ieee.std_logic_1164.all;
	use ieee.numeric_std.all;
	use work.log2_pkg.all;
 
 
entity exp2_fp is
	generic (MANTISBITS				: 		natural:= 23;		-- Formato IEEE754:
				EXPBITS					: 		natural:= 8;		-- signo[1] & exponente[8] & mantisa[23]
				SEG						:		natural:= 64;
				SEGBITS					:		natural:= 23);
	port 	  (i_x						: in	std_logic_vector(EXPBITS+MANTISBITS downto 0);
				o_exp2					: out std_logic_vector(EXPBITS+MANTISBITS downto 0));	
end entity;
 
 
architecture arch of exp2_fp is
	constant c_BX						: natural	:= 16;  -- %errormax: BX=16: 0.00105,  BX=12: 0.0169
	constant c_64seg_23b				: std_logic_vector(SEGBITS-1 downto 0) := "11111111111111101011101";
	constant c_log2_seg				: natural	:= f_log2(SEG);
 
	signal w_mantis	 				: std_logic_vector(MANTISBITS-1 downto 0);
	signal w_exp		 				: std_logic_vector(EXPBITS-1 downto 0);
	signal w_sgn 						: std_logic;
 
	signal w_exp_adj					: std_logic_vector(EXPBITS-2 downto 0); -- se ajusta segun el valor maximo calculable
	signal w_adderA_iterm1			: std_logic_vector(EXPBITS-2 downto 0);
	signal w_adderA					: std_logic_vector(EXPBITS-2 downto 0);
	signal w_mantis_adj				: std_logic_vector(c_BX+EXPBITS+MANTISBITS-2 downto 0);
	signal w_lshifter					: std_logic_vector(w_mantis_adj'left downto 0);
	signal w_lshifter_ishifts		: std_logic_vector(f_log2(w_mantis_adj'length)-1 downto 0);
	signal w_c1_lshifter				: std_logic_vector(EXPBITS+MANTISBITS-2 downto 0);
 
	signal w_adderB					: std_logic_vector(EXPBITS-2 downto 0);
	signal w_comp_EQexp				: std_logic;
	signal w_exp_MSB_result			: std_logic;
 
	signal w_ctrl_seg					: std_logic;	
	signal w_addr_lutA				: std_logic_vector(c_log2_seg-2 downto 0);
	signal w_adderC					: std_logic_vector(c_log2_seg-2 downto 0);
	signal w_lutA						: std_logic_vector(SEGBITS-1 downto 0);
	signal w_comp_EQseg				: std_logic;
	signal w_muxA_idata				: std_logic_vector(2*SEGBITS-1 downto 0);
	--signal w_muxA_isel 				: std_logic_vector(0 downto 0);
	signal w_muxA 						: std_logic_vector(SEGBITS-1 downto 0);
	signal w_addr_lutB				: std_logic_vector(c_log2_seg-2 downto 0);
	signal w_lutB						: std_logic_vector(SEGBITS-1 downto 0);
 
	signal w_comp_ctrlsubs			: std_logic;
	signal w_xor_comp_ctrlsubs		: std_logic;
	signal w_nxor_comp_ctrlsubs	: std_logic;
	signal w_C1_muxA					: std_logic_vector(SEGBITS-1 downto 0);
	signal w_C1_lutB					: std_logic_vector(SEGBITS-1 downto 0);
	signal w_adderE					: std_logic_vector(SEGBITS-1 downto 0);
 
	signal w_muxB_idata				: std_logic_vector(2*SEGBITS-1 downto 0);
	--signal w_muxB_iselect			: std_logic_vector(0 downto 0);
	signal w_muxB						: std_logic_vector(SEGBITS-1 downto 0);
	signal w_adderD					: std_logic_vector(SEGBITS-1 downto 0);
	signal w_adderD_cout				: std_logic;
	signal w_slf_segx					: std_logic_vector(MANTISBITS-1 downto 0); -- (s*lf - segx)
	signal w_mult						: std_logic_vector(MANTISBITS*2-1 downto 0);
	signal w_C1_mult_idata			: std_logic_vector(MANTISBITS+1 downto 0);
	signal w_C1_mult					: std_logic_vector(w_C1_mult_idata'left downto 0);
	signal w_adderF_iterm1			: std_logic_vector(w_C1_mult_idata'left downto 0);
	signal w_adderF					: std_logic_vector(w_C1_mult_idata'left downto 0);
 
	signal mantis_result				: std_logic_vector(MANTISBITS-1 downto 0);
	signal exp_result 				: std_logic_vector(EXPBITS-1 downto 0);
	signal sgn_result					: std_logic;
 
	signal w_ieeecase					: std_logic_vector(i_x'left downto 0);
	signal w_case_en					: std_logic_vector(1 downto 0);
	signal w_mux_case_idata 		: std_logic_vector(i_x'length*2-1 downto 0);
	signal w_mux_case 				: std_logic_vector(i_x'left downto 0);
begin
 
	w_mantis								<= i_x(MANTISBITS-1 downto 0);
	w_exp									<= i_x(MANTISBITS+EXPBITS-1 downto MANTISBITS);
	w_sgn									<= i_x(MANTISBITS+EXPBITS);
 
 
	--------------------------------------------------------------------------	
	-- < Ajuste de dato >
	--------------------------------------------------------------------------	
 
	w_exp_adj							<= w_exp(w_exp_adj'left downto 0);
	w_adderA_iterm1					<= w_exp_adj;
 
	adderA 								:	entity work.sum_ripple_carry_adder 
	generic map(WIDE					=> EXPBITS-1,
				C1 => 0)
	port map   (i_term1				=> w_adderA_iterm1,
					i_term2 				=> std_logic_vector(to_unsigned(c_BX, EXPBITS-1)),
					i_cin					=> '1',
					o_sum					=> w_adderA);	
 
	w_mantis_adj						<= std_logic_vector(to_unsigned(0, c_BX)) & std_logic_vector(to_unsigned(1, EXPBITS-1)) & w_mantis;
	w_lshifter_ishifts				<= w_adderA(f_log2(w_mantis_adj'length)-1 downto 0);
 
	lshifter								: entity work.left_shifter
	generic map(DATA_BITS			=> w_mantis_adj'length)
	port map	  (i_data				=> w_mantis_adj,
					i_shifts				=> w_lshifter_ishifts,
					o_dataShift			=> w_lshifter);
 
	ones_complement_lshifter		: entity work.ones_complement
	generic map(WIDE					=>	w_c1_lshifter'length)
	port map	  (i_data				=> w_lshifter(c_BX+MANTISBITS+EXPBiTS-2 downto c_BX),
					i_en					=> w_sgn,
					o_data				=> w_c1_lshifter);
 
 
	--------------------------------------------------------------------------	
	-- < calculo de esxponente >
	--------------------------------------------------------------------------	
 
	adderB								:entity work.sum_ripple_carry_adder 
	generic map(WIDE					=> EXPBITS-1,
					C1						=> 2) 
	port map   (i_term1				=> w_c1_lshifter(w_c1_lshifter'left downto MANTISBITS),
					i_term2 				=> std_logic_vector(to_unsigned(1, EXPBITS-1)),
					i_cin					=> '1',
					o_sum					=> w_adderB);	
 
	comparator_EQexponent			: entity work.comparator
	generic map(WIDE 					=> w_exp'length,
					MODO					=> 1)
	port map	  (i_data1				=> w_exp,
					i_data2				=> std_logic_vector(to_unsigned(126, w_exp'length)),
					o_result				=> w_comp_EQexp);
 
	w_exp_MSB_result					<= w_comp_EQexp and not(w_sgn);
 
 
	--------------------------------------------------------------------------	
	-- < Seleccion de constantes >
	--------------------------------------------------------------------------	
 
	w_addr_lutA							<= w_c1_lshifter(w_mantis'left downto w_mantis'left-c_log2_seg+2);
	w_addr_lutB							<= w_c1_lshifter(w_mantis'left downto w_mantis'left-c_log2_seg+2);
	w_ctrl_seg							<= w_c1_lshifter(w_mantis'left-c_log2_seg+1);
 
	adderC								:	entity work.sum_ripple_carry_adder 
	generic map(WIDE					=> c_log2_seg-1,
				C1 => 0)
	port map   (i_term1				=> w_addr_lutA,
					i_term2 				=> std_logic_vector(to_unsigned(0, c_log2_seg-1)),
					i_cin					=> w_ctrl_seg,
					o_sum					=> w_adderC);	
 
--	LUT32C: if SEG = 32 generate
--		LUT32_23b							: luts_32x23b
--		port map	  (i_lutA_addr			=> w_adderC,
--						i_lutB_addr			=> w_addr_lutB,
--						o_lutA				=> w_lutA,
--						o_lutB				=> w_lutB);
--	end generate;
 
	LUT64C: if SEG = 64 generate
		LUT64_23b							: entity work.exp2_luts_64x23b
		generic map(SEG => SEG)
		port map	  (i_lutA_addr			=> w_adderC,
						i_lutB_addr			=> w_addr_lutB,
						o_lutA				=> w_lutA,
						o_lutB				=> w_lutB);
	end generate;	
 
	comparator_EQsegments			: entity work.comparator
	generic map(WIDE 					=> c_log2_seg,
					MODO					=> 0)
	port map	  (i_data1				=> w_c1_lshifter(w_mantis'left downto MANTISBITS-c_log2_seg),
					i_data2				=> std_logic_vector(to_unsigned(SEG-1, c_log2_seg)),
					o_result				=> w_comp_EQseg);
 
   --w_muxA_idata						<= c_64seg_23b & w_lutA;
 	--w_muxA_isel							<= w_comp_EQseg & std_logic_vector(to_unsigned(0, 0));  -- entidad mux requiere que el dato siempre sea std_logic_vector
 
--  	mux_lutA									: mux
--	generic map(SELECT_BITS			=> 1, 
--					DATA_BITS			=> SEGBITS)
--	port map	  (i_data 				=> w_muxA_idata,
--					i_select				=> w_muxA_isel, 	
--					o_data				=>	w_muxA);	
 
w_muxA <= w_lutA when w_comp_EQseg='0' else c_64seg_23b;
	--------------------------------------------------------------------------
	-- < control resta de constantes >
	--------------------------------------------------------------------------
 
	comparator_control_lut			:	entity work.comparator
	generic map(WIDE					=> c_log2_seg,
					MODO					=>	2)
	port map	  (i_data1				=> w_c1_lshifter(w_mantis'left downto MANTISBITS-c_log2_seg),
					i_data2				=> std_logic_vector(to_unsigned(34, c_log2_seg)), -- constante solo funciona para 64 segmentos 
					o_result				=>	w_comp_ctrlsubs);
 
	w_xor_comp_ctrlsubs				<= w_comp_ctrlsubs xor w_c1_lshifter(MANTISBITS-c_log2_seg);
	w_nxor_comp_ctrlsubs				<= not(w_xor_comp_ctrlsubs);
 
	ones_complement_muxA				: entity work.ones_complement
	generic map(WIDE					=>	SEGBITS)
	port map	  (i_data				=> w_muxA,
					i_en					=> w_nxor_comp_ctrlsubs,
					o_data				=> w_C1_muxA);
 
	ones_complement_lutB				: entity work.ones_complement
	generic map(WIDE					=>	SEGBITS)
	port map	  (i_data				=> w_lutB,
					i_en					=> w_xor_comp_ctrlsubs,
					o_data				=> w_C1_lutB);
 
	constants_sub						:	entity work.sum_ripple_carry_adder
	generic map(WIDE					=> SEGBITS,
				C1 => 0)
	port map   (i_term1				=> w_C1_muxA,
					i_term2 				=> w_C1_lutB,
					i_cin					=> '1',
					o_sum					=> w_adderE);
 
 
	--------------------------------------------------------------------------
	-- < Calculo de mantisa >
	--------------------------------------------------------------------------
 
	w_muxB_idata						<= w_lutB & w_muxA;
	--w_muxB_iselect						<= w_ctrl_seg & std_logic_vector(to_unsigned(0, 0));  -- entidad mux requiere que el dato siempre sea del tipo std_logic_vector
 
--	muxB									: mux
--	generic map(SELECT_BITS			=> 1, 
--					DATA_BITS			=> SEGBITS)
--	port map	  (i_data 				=> w_muxB_idata,
--					i_select				=> w_muxB_iselect, 	
--					o_data				=>	w_muxB);
w_muxB <= w_muxA when w_ctrl_seg='0' else w_lutB;
 
	adderD								: entity work.sum_ripple_carry_adder
	generic map(WIDE					=> SEGBITS,
				C1 => 0)
	port map	  (i_term1				=> w_muxB,
					i_term2 				=> w_c1_lshifter(w_mantis'left downto 0),
					i_cin					=> '0',
					o_sum					=> w_adderD,
					o_cout				=> w_adderD_cout);	
 
	w_slf_segx							<= w_c1_lshifter(MANTISBITS-c_log2_seg-1 downto 0) & std_logic_vector(to_unsigned(0, c_log2_seg));
 
	multiplier							: entity work.mult
	generic map(WIDE					=> SEGBITS)
	port map	  (i_term1 				=> w_adderE,
					i_term2				=> w_slf_segx,
					o_product			=> w_mult);
 
	w_C1_mult_idata					<= w_mult(MANTISBITS*2-1 downto MANTISBITS-2);
 
	ones_complement_mult				: entity work.ones_complement
	generic map(WIDE					=>	w_C1_mult_idata'length)
	port map	  (i_data				=> w_C1_mult_idata,
					i_en					=> w_comp_ctrlsubs,
					o_data				=> w_C1_mult);
 
	w_adderF_iterm1					<= w_adderD & "00";	
 
	adderF								: entity work.sum_ripple_carry_adder
	generic map(WIDE					=> w_C1_mult'length,
				C1 => 0)
	port map	  (i_term1				=> w_adderF_iterm1,
					i_term2 				=> w_C1_mult,
					i_cin					=> w_comp_ctrlsubs,
					o_sum					=> w_adderF,
					o_cout				=> open);
 
	--------------------------------------------------------------------------
	-- < deteccion de caso ieee>
	--------------------------------------------------------------------------
	sgn_result						<= '0';
	exp_result						<= w_exp_MSB_result  & w_adderB;
	mantis_result					<= w_adderF(w_adderF'left downto w_adderF'left-MANTISBITS+1); 
 
	ieee32_case							: entity work.exp2_ieee
	generic map(BX 					=> c_BX)
	port map	  (i_data 				=> i_x,
					o_case				=> w_ieeecase,
					o_case_en			=> w_case_en(0));
 
	w_mux_case_idata					<= w_ieeecase & sgn_result & exp_result & mantis_result;
 
--	mux_ieee32_case					: mux
--	generic map(SELECT_BITS			=> 1,
--					DATA_BITS			=> i_x'length)
--	port map	  (i_data 				=> w_mux_case_idata,
--					i_select				=> w_case_en,
--					o_data 				=> w_mux_case);
 
 
w_mux_case <= sgn_result & exp_result & mantis_result when w_case_en(0)='0' else w_ieeecase;
	--------------------------------------------------------------------------
	-- < RESULTADO >
	--------------------------------------------------------------------------	
 
	o_exp2								<= w_mux_case ;
 
 
end arch;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.