All code in the initial commit is as it was in the jop repo at the time. jop is under GPL 3.0
Note we are only taking the fpu from /vhdl/fpu - jop is a much larger project implementing the full JVM.
From this point onwards all changes are by the commit author(s).
--- /dev/null
+*.o
+*.d
+*~
+*.ipdf
+*.test
+*.out
+*.err
--- /dev/null
+This is a virtual floating point unit (FPU) implemented in VHDL.
+
+It is (or was as of the initial commit) stolen from the Java Optimised Processor https://github.com/jop-devel/jop
+
+A test bench is used to compile a simulator executable for the FPU that reads from stdin and writes results to stdout.
+
+The VFPU namespace in the ipdf/code repository (git://git.ucc.asn.au/ipdf/code.git) can be used to send floating
+point operations to this executable. This is in the files ipdf/code/src/vhdl.cpp and ipdf/code/src/vhdl.h
+
+In theory this will allow us to test different hardware representations of floating point numbers.
+In practice it might be beyond the scope of our project to do much with this.
+
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: addition/subtraction entity for the addition/subtraction unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+use IEEE.std_logic_arith.all;
+
+library work;
+use work.fpupack.all;
+
+entity addsub_28 is
+ port(
+ clk_i : in std_logic;
+ fpu_op_i : in std_logic;
+ fracta_i : in std_logic_vector(FRAC_WIDTH+4 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ fractb_i : in std_logic_vector(FRAC_WIDTH+4 downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ fract_o : out std_logic_vector(FRAC_WIDTH+4 downto 0);
+ sign_o : out std_logic);
+end addsub_28;
+
+
+architecture rtl of addsub_28 is
+
+signal s_fracta_i, s_fractb_i : std_logic_vector(FRAC_WIDTH+4 downto 0);
+signal s_fract_o : std_logic_vector(FRAC_WIDTH+4 downto 0);
+signal s_signa_i, s_signb_i, s_sign_o : std_logic;
+signal s_fpu_op_i : std_logic;
+
+signal fracta_lt_fractb : std_logic;
+signal s_addop: std_logic;
+
+begin
+
+-- Input Register
+--process(clk_i)
+--begin
+-- if rising_edge(clk_i) then
+ s_fracta_i <= fracta_i;
+ s_fractb_i <= fractb_i;
+ s_signa_i<= signa_i;
+ s_signb_i<= signb_i;
+ s_fpu_op_i <= fpu_op_i;
+-- end if;
+--end process;
+
+-- Output Register
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ fract_o <= s_fract_o;
+ sign_o <= s_sign_o;
+ end if;
+end process;
+
+fracta_lt_fractb <= '1' when s_fracta_i > s_fractb_i else '0';
+
+-- check if its a subtraction or an addition operation
+s_addop <= ((s_signa_i xor s_signb_i)and not (s_fpu_op_i)) or ((s_signa_i xnor s_signb_i)and (s_fpu_op_i));
+
+-- sign of result
+s_sign_o <= '0' when s_fract_o = conv_std_logic_vector(0,28) and (s_signa_i and s_signb_i)='0' else
+ ((not s_signa_i) and ((not fracta_lt_fractb) and (fpu_op_i xor s_signb_i))) or
+ ((s_signa_i) and (fracta_lt_fractb or (fpu_op_i xor s_signb_i)));
+
+-- add/substract
+process(s_fracta_i, s_fractb_i, s_addop, fracta_lt_fractb)
+begin
+ if s_addop='0' then
+ s_fract_o <= s_fracta_i + s_fractb_i;
+ else
+ if fracta_lt_fractb = '1' then
+ s_fract_o <= s_fracta_i - s_fractb_i;
+ else
+ s_fract_o <= s_fractb_i - s_fracta_i;
+ end if;
+ end if;
+end process;
+
+
+
+
+end rtl;
+
--- /dev/null
+==fpu_v16==
+1) Corrected an embarrassing sytax error in "tb_fpu.vhd": start_i <= 0 to start_i <= '0'
+2) In "serial_div.vhd" and "sqrt.vhd": unused bits in some signals were initialized.
+3)Not need line in "fpusim.bat" was removed.
+
+==fpu_v17==
+1)Corrected bug related to adding two denormalized operands.
+
+==fpu_v18==
+1)post_norm_addsub.vhd: Restructured and fixed a bug
+2)fpu.vhd: Altered add/sub COUNT
+3)tb_fpu.vhd: Added some boundary values.
+
+==fpu_v19== 26. April 2007
+1)A minor bug was found and corrected when the serial multiplier is used (thanks to Chris Basson!)
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: component package
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+library work;
+use work.fpupack.all;
+
+package comppack is
+
+
+--- Component Declartions ---
+
+ --***Add/Substract units***
+
+ component pre_norm_addsub is
+ port(clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ opb_i : in std_logic_vector(31 downto 0);
+ fracta_28_o : out std_logic_vector(27 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ fractb_28_o : out std_logic_vector(27 downto 0);
+ exp_o : out std_logic_vector(7 downto 0));
+ end component;
+
+ component addsub_28 is
+ port(clk_i : in std_logic;
+ fpu_op_i : in std_logic;
+ fracta_i : in std_logic_vector(27 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ fractb_i : in std_logic_vector(27 downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ fract_o : out std_logic_vector(27 downto 0);
+ sign_o : out std_logic);
+ end component;
+
+ component post_norm_addsub is
+ port(clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ opb_i : in std_logic_vector(31 downto 0);
+ fract_28_i : in std_logic_vector(27 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ exp_i : in std_logic_vector(7 downto 0);
+ sign_i : in std_logic;
+ fpu_op_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(31 downto 0);
+ ine_o : out std_logic
+ );
+ end component;
+
+ --***Multiplication units***
+
+ component pre_norm_mul is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ opb_i : in std_logic_vector(31 downto 0);
+ exp_10_o : out std_logic_vector(9 downto 0);
+ fracta_24_o : out std_logic_vector(23 downto 0); -- hidden(1) & fraction(23)
+ fractb_24_o : out std_logic_vector(23 downto 0)
+ );
+ end component;
+
+ component mul_24 is
+ port(
+ clk_i : in std_logic;
+ fracta_i : in std_logic_vector(23 downto 0); -- hidden(1) & fraction(23)
+ fractb_i : in std_logic_vector(23 downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ start_i : in std_logic;
+ fract_o : out std_logic_vector(47 downto 0);
+ sign_o : out std_logic;
+ ready_o : out std_logic
+ );
+ end component;
+
+ component serial_mul is
+ port(
+ clk_i : in std_logic;
+ fracta_i : in std_logic_vector(FRAC_WIDTH downto 0); -- hidden(1) & fraction(23)
+ fractb_i : in std_logic_vector(FRAC_WIDTH downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ start_i : in std_logic;
+ fract_o : out std_logic_vector(2*FRAC_WIDTH+1 downto 0);
+ sign_o : out std_logic;
+ ready_o : out std_logic
+ );
+ end component;
+
+ component post_norm_mul is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ opb_i : in std_logic_vector(31 downto 0);
+ exp_10_i : in std_logic_vector(9 downto 0);
+ fract_48_i : in std_logic_vector(47 downto 0); -- hidden(1) & fraction(23)
+ sign_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(31 downto 0);
+ ine_o : out std_logic
+ );
+ end component;
+
+ --***Division units***
+
+ component pre_norm_div is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ exp_10_o : out std_logic_vector(EXP_WIDTH+1 downto 0);
+ dvdnd_50_o : out std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0);
+ dvsor_27_o : out std_logic_vector(FRAC_WIDTH+3 downto 0)
+ );
+ end component;
+
+ component serial_div is
+ port(
+ clk_i : in std_logic;
+ dvdnd_i : in std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0); -- hidden(1) & fraction(23)
+ dvsor_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ sign_dvd_i : in std_logic;
+ sign_div_i : in std_logic;
+ start_i : in std_logic;
+ ready_o : out std_logic;
+ qutnt_o : out std_logic_vector(FRAC_WIDTH+3 downto 0);
+ rmndr_o : out std_logic_vector(FRAC_WIDTH+3 downto 0);
+ sign_o : out std_logic;
+ div_zero_o : out std_logic
+ );
+ end component;
+
+ component post_norm_div is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ qutnt_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ rmndr_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ exp_10_i : in std_logic_vector(EXP_WIDTH+1 downto 0);
+ sign_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+ end component;
+
+
+ --***Square units***
+
+ component pre_norm_sqrt is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ fracta_52_o : out std_logic_vector(51 downto 0);
+ exp_o : out std_logic_vector(7 downto 0));
+ end component;
+
+ component sqrt is
+ generic (RD_WIDTH: integer; SQ_WIDTH: integer); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
+ port(
+ clk_i : in std_logic;
+ rad_i : in std_logic_vector(RD_WIDTH-1 downto 0); -- hidden(1) & fraction(23)
+ start_i : in std_logic;
+ ready_o : out std_logic;
+ sqr_o : out std_logic_vector(SQ_WIDTH-1 downto 0);
+ ine_o : out std_logic);
+ end component;
+
+
+ component post_norm_sqrt is
+ port( clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ fract_26_i : in std_logic_vector(25 downto 0); -- hidden(1) & fraction(11)
+ exp_i : in std_logic_vector(7 downto 0);
+ ine_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(31 downto 0);
+ ine_o : out std_logic);
+ end component;
+
+
+end comppack;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: top entity
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.comppack.all;
+use work.fpupack.all;
+
+
+entity fpu is
+ port (
+ clk_i : in std_logic;
+
+ -- Input Operands A & B
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0); -- Default: FP_WIDTH=32
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+
+ -- fpu operations (fpu_op_i):
+ -- ========================
+ -- 000 = add,
+ -- 001 = substract,
+ -- 010 = multiply,
+ -- 011 = divide,
+ -- 100 = square root
+ -- 101 = unused
+ -- 110 = unused
+ -- 111 = unused
+ fpu_op_i : in std_logic_vector(2 downto 0);
+
+ -- Rounding Mode:
+ -- ==============
+ -- 00 = round to nearest even(default),
+ -- 01 = round to zero,
+ -- 10 = round up,
+ -- 11 = round down
+ rmode_i : in std_logic_vector(1 downto 0);
+
+ -- Output port
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+
+ -- Control signals
+ start_i : in std_logic; -- is also restart signal
+ ready_o : out std_logic;
+
+ -- Exceptions
+ ine_o : out std_logic; -- inexact
+ overflow_o : out std_logic; -- overflow
+ underflow_o : out std_logic; -- underflow
+ div_zero_o : out std_logic; -- divide by zero
+ inf_o : out std_logic; -- infinity
+ zero_o : out std_logic; -- zero
+ qnan_o : out std_logic; -- queit Not-a-Number
+ snan_o : out std_logic -- signaling Not-a-Number
+ );
+end fpu;
+
+architecture rtl of fpu is
+
+
+ constant MUL_SERIAL: integer range 0 to 1 := 1; -- 0 for parallel multiplier, 1 for serial
+ constant MUL_COUNT: integer:= 34; --11 for parallel multiplier, 34 for serial
+
+ -- Input/output registers
+ signal s_opa_i, s_opb_i : std_logic_vector(FP_WIDTH-1 downto 0);
+ signal s_fpu_op_i : std_logic_vector(2 downto 0);
+ signal s_rmode_i : std_logic_vector(1 downto 0);
+ signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
+ signal s_ine_o, s_overflow_o, s_underflow_o, s_div_zero_o, s_inf_o, s_zero_o, s_qnan_o, s_snan_o : std_logic;
+
+ type t_state is (waiting,busy);
+ signal s_state : t_state;
+ signal s_start_i : std_logic;
+ signal s_count : integer;
+ signal s_output1 : std_logic_vector(FP_WIDTH-1 downto 0);
+ signal s_infa, s_infb : std_logic;
+
+ -- ***Add/Substract units signals***
+
+ signal prenorm_addsub_fracta_28_o, prenorm_addsub_fractb_28_o : std_logic_vector(27 downto 0);
+ signal prenorm_addsub_exp_o : std_logic_vector(7 downto 0);
+
+ signal addsub_fract_o : std_logic_vector(27 downto 0);
+ signal addsub_sign_o : std_logic;
+
+ signal postnorm_addsub_output_o : std_logic_vector(31 downto 0);
+ signal postnorm_addsub_ine_o : std_logic;
+
+ -- ***Multiply units signals***
+
+ signal pre_norm_mul_exp_10 : std_logic_vector(9 downto 0);
+ signal pre_norm_mul_fracta_24 : std_logic_vector(23 downto 0);
+ signal pre_norm_mul_fractb_24 : std_logic_vector(23 downto 0);
+
+ signal mul_24_fract_48 : std_logic_vector(47 downto 0);
+ signal mul_24_sign : std_logic;
+ signal serial_mul_fract_48 : std_logic_vector(47 downto 0);
+ signal serial_mul_sign : std_logic;
+
+ signal mul_fract_48: std_logic_vector(47 downto 0);
+ signal mul_sign: std_logic;
+
+ signal post_norm_mul_output : std_logic_vector(31 downto 0);
+ signal post_norm_mul_ine : std_logic;
+
+ -- ***Division units signals***
+
+ signal pre_norm_div_dvdnd : std_logic_vector(49 downto 0);
+ signal pre_norm_div_dvsor : std_logic_vector(26 downto 0);
+ signal pre_norm_div_exp : std_logic_vector(EXP_WIDTH+1 downto 0);
+
+ signal serial_div_qutnt : std_logic_vector(26 downto 0);
+ signal serial_div_rmndr : std_logic_vector(26 downto 0);
+ signal serial_div_sign : std_logic;
+ signal serial_div_div_zero : std_logic;
+
+ signal post_norm_div_output : std_logic_vector(31 downto 0);
+ signal post_norm_div_ine : std_logic;
+
+ -- ***Square units***
+
+ signal pre_norm_sqrt_fracta_o : std_logic_vector(51 downto 0);
+ signal pre_norm_sqrt_exp_o : std_logic_vector(7 downto 0);
+
+ signal sqrt_sqr_o : std_logic_vector(25 downto 0);
+ signal sqrt_ine_o : std_logic;
+
+ signal post_norm_sqrt_output : std_logic_vector(31 downto 0);
+ signal post_norm_sqrt_ine_o : std_logic;
+
+
+begin
+ --***Add/Substract units***
+
+ i_prenorm_addsub: pre_norm_addsub
+ port map (
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ fracta_28_o => prenorm_addsub_fracta_28_o,
+ fractb_28_o => prenorm_addsub_fractb_28_o,
+ exp_o=> prenorm_addsub_exp_o);
+
+ i_addsub: addsub_28
+ port map(
+ clk_i => clk_i,
+ fpu_op_i => s_fpu_op_i(0),
+ fracta_i => prenorm_addsub_fracta_28_o,
+ fractb_i => prenorm_addsub_fractb_28_o,
+ signa_i => s_opa_i(31),
+ signb_i => s_opb_i(31),
+ fract_o => addsub_fract_o,
+ sign_o => addsub_sign_o);
+
+ i_postnorm_addsub: post_norm_addsub
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ fract_28_i => addsub_fract_o,
+ exp_i => prenorm_addsub_exp_o,
+ sign_i => addsub_sign_o,
+ fpu_op_i => s_fpu_op_i(0),
+ rmode_i => s_rmode_i,
+ output_o => postnorm_addsub_output_o,
+ ine_o => postnorm_addsub_ine_o
+ );
+
+ --***Multiply units***
+
+ i_pre_norm_mul: pre_norm_mul
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ exp_10_o => pre_norm_mul_exp_10,
+ fracta_24_o => pre_norm_mul_fracta_24,
+ fractb_24_o => pre_norm_mul_fractb_24);
+
+ i_mul_24 : mul_24
+ port map(
+ clk_i => clk_i,
+ fracta_i => pre_norm_mul_fracta_24,
+ fractb_i => pre_norm_mul_fractb_24,
+ signa_i => s_opa_i(31),
+ signb_i => s_opb_i(31),
+ start_i => start_i,
+ fract_o => mul_24_fract_48,
+ sign_o => mul_24_sign,
+ ready_o => open);
+
+ i_serial_mul : serial_mul
+ port map(
+ clk_i => clk_i,
+ fracta_i => pre_norm_mul_fracta_24,
+ fractb_i => pre_norm_mul_fractb_24,
+ signa_i => s_opa_i(31),
+ signb_i => s_opb_i(31),
+ start_i => s_start_i,
+ fract_o => serial_mul_fract_48,
+ sign_o => serial_mul_sign,
+ ready_o => open);
+
+ -- serial or parallel multiplier will be choosed depending on constant MUL_SERIAL
+ mul_fract_48 <= mul_24_fract_48 when MUL_SERIAL=0 else serial_mul_fract_48;
+ mul_sign <= mul_24_sign when MUL_SERIAL=0 else serial_mul_sign;
+
+ i_post_norm_mul : post_norm_mul
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ exp_10_i => pre_norm_mul_exp_10,
+ fract_48_i => mul_fract_48,
+ sign_i => mul_sign,
+ rmode_i => s_rmode_i,
+ output_o => post_norm_mul_output,
+ ine_o => post_norm_mul_ine
+ );
+
+ --***Division units***
+
+ i_pre_norm_div : pre_norm_div
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ exp_10_o => pre_norm_div_exp,
+ dvdnd_50_o => pre_norm_div_dvdnd,
+ dvsor_27_o => pre_norm_div_dvsor);
+
+ i_serial_div : serial_div
+ port map(
+ clk_i=> clk_i,
+ dvdnd_i => pre_norm_div_dvdnd,
+ dvsor_i => pre_norm_div_dvsor,
+ sign_dvd_i => s_opa_i(31),
+ sign_div_i => s_opb_i(31),
+ start_i => s_start_i,
+ ready_o => open,
+ qutnt_o => serial_div_qutnt,
+ rmndr_o => serial_div_rmndr,
+ sign_o => serial_div_sign,
+ div_zero_o => serial_div_div_zero);
+
+ i_post_norm_div : post_norm_div
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ opb_i => s_opb_i,
+ qutnt_i => serial_div_qutnt,
+ rmndr_i => serial_div_rmndr,
+ exp_10_i => pre_norm_div_exp,
+ sign_i => serial_div_sign,
+ rmode_i => s_rmode_i,
+ output_o => post_norm_div_output,
+ ine_o => post_norm_div_ine);
+
+
+ --***Square units***
+
+ i_pre_norm_sqrt : pre_norm_sqrt
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ fracta_52_o => pre_norm_sqrt_fracta_o,
+ exp_o => pre_norm_sqrt_exp_o);
+
+ i_sqrt: sqrt
+ generic map(RD_WIDTH=>52, SQ_WIDTH=>26)
+ port map(
+ clk_i => clk_i,
+ rad_i => pre_norm_sqrt_fracta_o,
+ start_i => s_start_i,
+ ready_o => open,
+ sqr_o => sqrt_sqr_o,
+ ine_o => sqrt_ine_o);
+
+ i_post_norm_sqrt : post_norm_sqrt
+ port map(
+ clk_i => clk_i,
+ opa_i => s_opa_i,
+ fract_26_i => sqrt_sqr_o,
+ exp_i => pre_norm_sqrt_exp_o,
+ ine_i => sqrt_ine_o,
+ rmode_i => s_rmode_i,
+ output_o => post_norm_sqrt_output,
+ ine_o => post_norm_sqrt_ine_o);
+
+
+
+-----------------------------------------------------------------
+
+ -- Input Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ s_opa_i <= opa_i;
+ s_opb_i <= opb_i;
+ s_fpu_op_i <= fpu_op_i;
+ s_rmode_i <= rmode_i;
+ s_start_i <= start_i;
+ end if;
+ end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ output_o <= s_output_o;
+ ine_o <= s_ine_o;
+ overflow_o <= s_overflow_o;
+ underflow_o <= s_underflow_o;
+ div_zero_o <= s_div_zero_o;
+ inf_o <= s_inf_o;
+ zero_o <= s_zero_o;
+ qnan_o <= s_qnan_o;
+ snan_o <= s_snan_o;
+ end if;
+ end process;
+
+
+ -- FSM
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_start_i ='1' then
+ s_state <= busy;
+ s_count <= 0;
+ elsif s_count=6 and ((fpu_op_i="000") or (fpu_op_i="001")) then
+ s_state <= waiting;
+ ready_o <= '1';
+ s_count <=0;
+ elsif s_count=MUL_COUNT and fpu_op_i="010" then
+ s_state <= waiting;
+ ready_o <= '1';
+ s_count <=0;
+ elsif s_count=33 and fpu_op_i="011" then
+ s_state <= waiting;
+ ready_o <= '1';
+ s_count <=0;
+ elsif s_count=33 and fpu_op_i="100" then
+ s_state <= waiting;
+ ready_o <= '1';
+ s_count <=0;
+ elsif s_state=busy then
+ s_count <= s_count + 1;
+ else
+ s_state <= waiting;
+ ready_o <= '0';
+ end if;
+ end if;
+ end process;
+
+ -- Output Multiplexer
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if fpu_op_i="000" or fpu_op_i="001" then
+ s_output1 <= postnorm_addsub_output_o;
+ s_ine_o <= postnorm_addsub_ine_o;
+ elsif fpu_op_i="010" then
+ s_output1 <= post_norm_mul_output;
+ s_ine_o <= post_norm_mul_ine;
+ elsif fpu_op_i="011" then
+ s_output1 <= post_norm_div_output;
+ s_ine_o <= post_norm_div_ine;
+-- elsif fpu_op_i="100" then
+-- s_output1 <= post_norm_sqrt_output;
+-- s_ine_o <= post_norm_sqrt_ine_o;
+ else
+ s_output1 <= (others => '0');
+ s_ine_o <= '0';
+ end if;
+ end if;
+ end process;
+
+
+ s_infa <= '1' when s_opa_i(30 downto 23)="11111111" else '0';
+ s_infb <= '1' when s_opb_i(30 downto 23)="11111111" else '0';
+
+
+ --In round down: the subtraction of two equal numbers other than zero are always -0!!!
+ process(s_output1, s_rmode_i, s_div_zero_o, s_infa, s_infb, s_qnan_o, s_snan_o, s_zero_o, s_fpu_op_i, s_opa_i, s_opb_i )
+ begin
+ if s_rmode_i="00" or (s_div_zero_o or (s_infa or s_infb) or s_qnan_o or s_snan_o)='1' then --round-to-nearest-even
+ s_output_o <= s_output1;
+ elsif s_rmode_i="01" and s_output1(30 downto 23)="11111111" then
+ --In round-to-zero: the sum of two non-infinity operands is never infinity,even if an overflow occures
+ s_output_o <= s_output1(31) & "1111111011111111111111111111111";
+ elsif s_rmode_i="10" and s_output1(31 downto 23)="111111111" then
+ --In round-up: the sum of two non-infinity operands is never negative infinity,even if an overflow occures
+ s_output_o <= "11111111011111111111111111111111";
+ elsif s_rmode_i="11" then
+ --In round-down: a-a= -0
+ if (s_fpu_op_i="000" or s_fpu_op_i="001") and s_zero_o='1' and (s_opa_i(31) or (s_fpu_op_i(0) xor s_opb_i(31)))='1' then
+ s_output_o <= "1" & s_output1(30 downto 0);
+ --In round-down: the sum of two non-infinity operands is never postive infinity,even if an overflow occures
+ elsif s_output1(31 downto 23)="011111111" then
+ s_output_o <= "01111111011111111111111111111111";
+ else
+ s_output_o <= s_output1;
+ end if;
+ else
+ s_output_o <= s_output1;
+ end if;
+ end process;
+
+
+ -- Generate Exceptions
+ s_underflow_o <= '1' when s_output1(30 downto 23)="00000000" and s_ine_o='1' else '0';
+ s_overflow_o <= '1' when s_output1(30 downto 23)="11111111" and s_ine_o='1' else '0';
+ s_div_zero_o <= serial_div_div_zero when fpu_op_i="011" else '0';
+ s_inf_o <= '1' when s_output1(30 downto 23)="11111111" and (s_qnan_o or s_snan_o)='0' else '0';
+ s_zero_o <= '1' when or_reduce(s_output1(30 downto 0))='0' else '0';
+ s_qnan_o <= '1' when s_output1(30 downto 0)=QNAN else '0';
+ s_snan_o <= '1' when s_opa_i(30 downto 0)=SNAN or s_opb_i(30 downto 0)=SNAN else '0';
+
+
+end rtl;
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: FPU package wich contains constants and functions needed in the FPU core
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+package fpupack is
+
+
+ -- Data width of floating-point number. Deafult: 32
+ constant FP_WIDTH : integer := 32;
+
+ -- Data width of fraction. Deafult: 23
+ constant FRAC_WIDTH : integer := 23;
+
+ -- Data width of exponent. Deafult: 8
+ constant EXP_WIDTH : integer := 8;
+
+ --Zero vector
+ constant ZERO_VECTOR: std_logic_vector(30 downto 0) := "0000000000000000000000000000000";
+
+ -- Infinty FP format
+ constant INF : std_logic_vector(30 downto 0) := "1111111100000000000000000000000";
+
+ -- QNaN (Quit Not a Number) FP format (without sign bit)
+ constant QNAN : std_logic_vector(30 downto 0) := "1111111110000000000000000000000";
+
+ -- SNaN (Signaling Not a Number) FP format (without sign bit)
+ constant SNAN : std_logic_vector(30 downto 0) := "1111111100000000000000000000001";
+
+ -- count the zeros starting from left
+ function count_l_zeros (signal s_vector: std_logic_vector) return std_logic_vector;
+
+ -- count the zeros starting from right
+ function count_r_zeros (signal s_vector: std_logic_vector) return std_logic_vector;
+
+end fpupack;
+
+package body fpupack is
+
+ -- count the zeros starting from left
+ function count_l_zeros (signal s_vector: std_logic_vector) return std_logic_vector is
+ variable v_count : std_logic_vector(5 downto 0);
+ begin
+ v_count := "000000";
+ for i in s_vector'range loop
+ case s_vector(i) is
+ when '0' => v_count := v_count + "000001";
+ when others => exit;
+ end case;
+ end loop;
+ return v_count;
+ end count_l_zeros;
+
+
+ -- count the zeros starting from right
+ function count_r_zeros (signal s_vector: std_logic_vector) return std_logic_vector is
+ variable v_count : std_logic_vector(5 downto 0);
+ begin
+ v_count := "000000";
+ for i in 0 to s_vector'length-1 loop
+ case s_vector(i) is
+ when '0' => v_count := v_count + "000001";
+ when others => exit;
+ end case;
+ end loop;
+ return v_count;
+ end count_r_zeros;
+
+
+
+end fpupack;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: multiplication entity for the multiplication unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+library work;
+use work.fpupack.all;
+
+entity mul_24 is
+ port(
+ clk_i : in std_logic;
+ fracta_i : in std_logic_vector(FRAC_WIDTH downto 0); -- hidden(1) & fraction(23)
+ fractb_i : in std_logic_vector(FRAC_WIDTH downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ start_i : in std_logic;
+ fract_o : out std_logic_vector(2*FRAC_WIDTH+1 downto 0);
+ sign_o : out std_logic;
+ ready_o : out std_logic
+ );
+end mul_24;
+
+architecture rtl of mul_24 is
+
+
+
+signal s_fracta_i, s_fractb_i : std_logic_vector(FRAC_WIDTH downto 0);
+signal s_signa_i, s_signb_i, s_sign_o : std_logic;
+signal s_fract_o: std_logic_vector(2*FRAC_WIDTH+1 downto 0);
+signal s_start_i, s_ready_o : std_logic;
+
+signal a_h, a_l, b_h, b_l : std_logic_vector(11 downto 0);
+signal a_h_h, a_h_l, b_h_h, b_h_l, a_l_h, a_l_l, b_l_h, b_l_l : std_logic_vector(5 downto 0);
+
+type op_6 is array (7 downto 0) of std_logic_vector(5 downto 0);
+type prod_6 is array (3 downto 0) of op_6;
+
+type prod_48 is array (4 downto 0) of std_logic_vector(47 downto 0);
+type sum_24 is array (3 downto 0) of std_logic_vector(23 downto 0);
+
+type a is array (3 downto 0) of std_logic_vector(23 downto 0);
+type prod_24 is array (3 downto 0) of a;
+
+signal prod : prod_6;
+signal sum : sum_24;
+signal prod_a_b : prod_48;
+
+signal count : integer range 0 to 4;
+
+
+type t_state is (waiting,busy);
+signal s_state : t_state;
+
+signal prod2 : prod_24;
+begin
+
+
+-- Input Register
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ s_fracta_i <= fracta_i;
+ s_fractb_i <= fractb_i;
+ s_signa_i<= signa_i;
+ s_signb_i<= signb_i;
+ s_start_i<=start_i;
+ end if;
+end process;
+
+-- Output Register
+--process(clk_i)
+--begin
+-- if rising_edge(clk_i) then
+ fract_o <= s_fract_o;
+ sign_o <= s_sign_o;
+ ready_o<=s_ready_o;
+-- end if;
+--end process;
+
+
+-- FSM
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ if s_start_i ='1' then
+ s_state <= busy;
+ count <= 0;
+ elsif count=4 and s_state=busy then
+ s_state <= waiting;
+ s_ready_o <= '1';
+ count <=0;
+ elsif s_state=busy then
+ count <= count + 1;
+ else
+ s_state <= waiting;
+ s_ready_o <= '0';
+ end if;
+ end if;
+end process;
+
+s_sign_o <= s_signa_i xor s_signb_i;
+
+--"000000000000"
+-- A = A_h x 2^N + A_l , B = B_h x 2^N + B_l
+-- A x B = A_hxB_hx2^2N + (A_h xB_l + A_lxB_h)2^N + A_lxB_l
+a_h <= s_fracta_i(23 downto 12);
+a_l <= s_fracta_i(11 downto 0);
+b_h <= s_fractb_i(23 downto 12);
+b_l <= s_fractb_i(11 downto 0);
+
+
+
+a_h_h <= a_h(11 downto 6);
+a_h_l <= a_h(5 downto 0);
+b_h_h <= b_h(11 downto 6);
+b_h_l <= b_h(5 downto 0);
+
+a_l_h <= a_l(11 downto 6);
+a_l_l <= a_l(5 downto 0);
+b_l_h <= b_l(11 downto 6);
+b_l_l <= b_l(5 downto 0);
+
+
+prod(0)(0) <= a_h_h; prod(0)(1) <= b_h_h;
+prod(0)(2) <= a_h_h; prod(0)(3) <= b_h_l;
+prod(0)(4) <= a_h_l; prod(0)(5) <= b_h_h;
+prod(0)(6) <= a_h_l; prod(0)(7) <= b_h_l;
+
+
+prod(1)(0) <= a_h_h; prod(1)(1) <= b_l_h;
+prod(1)(2) <= a_h_h; prod(1)(3) <= b_l_l;
+prod(1)(4) <= a_h_l; prod(1)(5) <= b_l_h;
+prod(1)(6) <= a_h_l; prod(1)(7) <= b_l_l;
+
+prod(2)(0) <= a_l_h; prod(2)(1) <= b_h_h;
+prod(2)(2) <= a_l_h; prod(2)(3) <= b_h_l;
+prod(2)(4) <= a_l_l; prod(2)(5) <= b_h_h;
+prod(2)(6) <= a_l_l; prod(2)(7) <= b_h_l;
+
+prod(3)(0) <= a_l_h; prod(3)(1) <= b_l_h;
+prod(3)(2) <= a_l_h; prod(3)(3) <= b_l_l;
+prod(3)(4) <= a_l_l; prod(3)(5) <= b_l_h;
+prod(3)(6) <= a_l_l; prod(3)(7) <= b_l_l;
+
+
+
+process(clk_i)
+begin
+if rising_edge(clk_i) then
+ if count < 4 then
+ prod2(count)(0) <= (prod(count)(0)*prod(count)(1))&"000000000000";
+ prod2(count)(1) <= "000000"&(prod(count)(2)*prod(count)(3))&"000000";
+ prod2(count)(2) <= "000000"&(prod(count)(4)*prod(count)(5))&"000000";
+ prod2(count)(3) <= "000000000000"&(prod(count)(6)*prod(count)(7));
+ end if;
+end if;
+end process;
+
+
+
+process(clk_i)
+begin
+if rising_edge(clk_i) then
+ if count > 0 and s_state=busy then
+ sum(count-1) <= prod2(count-1)(0) + prod2(count-1)(1) + prod2(count-1)(2) + prod2(count-1)(3);
+ end if;
+end if;
+end process;
+
+
+
+-- Last stage
+
+
+ prod_a_b(0) <= sum(0)&"000000000000000000000000";
+ prod_a_b(1) <= "000000000000"&sum(1)&"000000000000";
+ prod_a_b(2) <= "000000000000"&sum(2)&"000000000000";
+ prod_a_b(3) <= "000000000000000000000000"&sum(3);
+
+ prod_a_b(4) <= prod_a_b(0) + prod_a_b(1) + prod_a_b(2) + prod_a_b(3);
+
+ s_fract_o <= prod_a_b(4);
+
+
+
+end rtl;
+
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: post-normalization entity for the addition/subtraction unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity post_norm_addsub is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ fract_28_i : in std_logic_vector(FRAC_WIDTH+4 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ exp_i : in std_logic_vector(EXP_WIDTH-1 downto 0);
+ sign_i : in std_logic;
+ fpu_op_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+end post_norm_addsub;
+
+
+architecture rtl of post_norm_addsub is
+
+
+signal s_opa_i, s_opb_i : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_fract_28_i : std_logic_vector(FRAC_WIDTH+4 downto 0);
+signal s_exp_i : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_sign_i : std_logic;
+signal s_fpu_op_i : std_logic;
+signal s_rmode_i : std_logic_vector(1 downto 0);
+signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_ine_o : std_logic;
+signal s_overflow : std_logic;
+
+signal s_zeros, s_shr1, s_shl1 : std_logic_vector(5 downto 0);
+signal s_shr2, s_carry : std_logic;
+
+signal s_exp10: std_logic_vector(9 downto 0);
+signal s_expo9_1, s_expo9_2, s_expo9_3: std_logic_vector(EXP_WIDTH downto 0);
+
+signal s_fracto28_1, s_fracto28_2, s_fracto28_rnd : std_logic_vector(FRAC_WIDTH+4 downto 0);
+
+signal s_roundup : std_logic;
+signal s_sticky : std_logic;
+
+signal s_zero_fract : std_logic;
+signal s_lost : std_logic;
+signal s_infa, s_infb : std_logic;
+signal s_nan_in, s_nan_op, s_nan_a, s_nan_b, s_nan_sign : std_logic;
+
+begin
+
+ -- Input Register
+ --process(clk_i)
+ --begin
+ -- if rising_edge(clk_i) then
+ s_opa_i <= opa_i;
+ s_opb_i <= opb_i;
+ s_fract_28_i <= fract_28_i;
+ s_exp_i <= exp_i;
+ s_sign_i <= sign_i;
+ s_fpu_op_i <= fpu_op_i;
+ s_rmode_i <= rmode_i;
+ -- end if;
+ --end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ output_o <= s_output_o;
+ ine_o <= s_ine_o;
+ end if;
+ end process;
+
+ --*** Stage 1 ****
+ -- figure out the output exponent and howmuch the fraction has to be shiftd right/left
+
+ s_carry <= s_fract_28_i(27);
+
+
+ s_zeros <= count_l_zeros(s_fract_28_i(26 downto 0)) when s_fract_28_i(27)='0' else "000000";
+
+
+ s_exp10 <= ("00"&s_exp_i) + ("000000000"&s_carry) - ("0000"&s_zeros); -- negative flag & large flag & exp
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_exp10(9)='1' or s_exp10="0000000000" then
+ s_shr1 <= (others =>'0');
+ if or_reduce(s_exp_i)/='0' then
+ s_shl1 <= s_exp_i(5 downto 0) - "000001";
+ else
+ s_shl1 <= "000000";
+ end if;
+ s_expo9_1 <= "000000001";
+ elsif s_exp10(8)='1' then
+ s_shr1 <= (others =>'0');
+ s_shl1 <= (others =>'0');
+ s_expo9_1 <= "011111111";
+ else
+ s_shr1 <= ("00000"&s_carry);
+ s_shl1 <= s_zeros;
+ s_expo9_1 <= s_exp10(8 downto 0);
+ end if;
+ end if;
+ end process;
+
+---
+ -- *** Stage 2 ***
+ -- Shifting the fraction and rounding
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_shr1 /= "000000" then
+ s_fracto28_1 <= shr(s_fract_28_i, s_shr1);
+ else
+ s_fracto28_1 <= shl(s_fract_28_i, s_shl1);
+ end if;
+ end if;
+ end process;
+
+ s_expo9_2 <= s_expo9_1 - "000000001" when s_fracto28_1(27 downto 26)="00" else s_expo9_1;
+
+ -- round
+ s_sticky <='1' when s_fracto28_1(0)='1' or (s_fract_28_i(0) and s_fract_28_i(27))='1' else '0'; --check last bit, before and after right-shift
+
+ s_roundup <= s_fracto28_1(2) and ((s_fracto28_1(1) or s_sticky)or s_fracto28_1(3)) when s_rmode_i="00" else -- round to nearset even
+ (s_fracto28_1(2) or s_fracto28_1(1) or s_sticky) and (not s_sign_i) when s_rmode_i="10" else -- round up
+ (s_fracto28_1(2) or s_fracto28_1(1) or s_sticky) and (s_sign_i) when s_rmode_i="11" else -- round down
+ '0'; -- round to zero(truncate = no rounding)
+
+ s_fracto28_rnd <= s_fracto28_1 + "0000000000000000000000001000" when s_roundup='1' else s_fracto28_1;
+
+ -- ***Stage 3***
+ -- right-shift after rounding (if necessary)
+ s_shr2 <= s_fracto28_rnd(27);
+
+ s_expo9_3 <= s_expo9_2 + "000000001" when s_shr2='1' and s_expo9_2 /= "011111111" else s_expo9_2;
+ s_fracto28_2 <= ("0"&s_fracto28_rnd(27 downto 1)) when s_shr2='1' else s_fracto28_rnd;
+-----
+
+ s_infa <= '1' when s_opa_i(30 downto 23)="11111111" else '0';
+ s_infb <= '1' when s_opb_i(30 downto 23)="11111111" else '0';
+
+ s_nan_a <= '1' when (s_infa='1' and or_reduce (s_opa_i(22 downto 0))='1') else '0';
+ s_nan_b <= '1' when (s_infb='1' and or_reduce (s_opb_i(22 downto 0))='1') else '0';
+ s_nan_in <= '1' when s_nan_a='1' or s_nan_b='1' else '0';
+ s_nan_op <= '1' when (s_infa and s_infb)='1' and (s_opa_i(31) xor (s_fpu_op_i xor s_opb_i(31)) )='1' else '0'; -- inf-inf=Nan
+
+ s_nan_sign <= s_sign_i when (s_nan_a and s_nan_b)='1' else
+ s_opa_i(31) when s_nan_a='1' else
+ s_opb_i(31);
+
+ -- check if result is inexact;
+ s_lost <= (s_shr1(0) and s_fract_28_i(0)) or (s_shr2 and s_fracto28_rnd(0)) or or_reduce(s_fracto28_2(2 downto 0));
+ s_ine_o <= '1' when (s_lost or s_overflow)='1' and (s_infa or s_infb)='0' else '0';
+
+ s_overflow <='1' when s_expo9_3="011111111" and (s_infa or s_infb)='0' else '0';
+ s_zero_fract <= '1' when s_zeros=27 and s_fract_28_i(27)='0' else '0'; -- '1' if fraction result is zero
+
+ process(s_sign_i, s_expo9_3, s_fracto28_2, s_nan_in, s_nan_op, s_nan_sign, s_infa, s_infb, s_overflow, s_zero_fract)
+ begin
+ if (s_nan_in or s_nan_op)='1' then
+ s_output_o <= s_nan_sign & QNAN;
+ elsif (s_infa or s_infb)='1' or s_overflow='1' then
+ s_output_o <= s_sign_i & INF;
+ elsif s_zero_fract='1' then
+ s_output_o <= s_sign_i & ZERO_VECTOR;
+ else
+ s_output_o <= s_sign_i & s_expo9_3(7 downto 0) & s_fracto28_2(25 downto 3);
+ end if;
+ end process;
+
+
+end rtl;
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: post-normalization entity for the division unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+
+entity post_norm_div is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ qutnt_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ rmndr_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ exp_10_i : in std_logic_vector(EXP_WIDTH+1 downto 0);
+ sign_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+end post_norm_div;
+
+architecture rtl of post_norm_div is
+
+
+-- input&output register signals
+signal s_opa_i, s_opb_i : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_qutnt_i, s_rmndr_i : std_logic_vector(FRAC_WIDTH+3 downto 0);
+signal s_r_zeros : std_logic_vector(5 downto 0);
+signal s_exp_10_i : std_logic_vector(EXP_WIDTH+1 downto 0);
+signal s_sign_i : std_logic;
+signal s_rmode_i : std_logic_vector(1 downto 0);
+signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_ine_o, s_overflow : std_logic;
+
+signal s_opa_dn, s_opb_dn : std_logic;
+signal s_qutdn : std_logic;
+
+signal s_exp_10b : std_logic_vector(9 downto 0);
+signal s_shr1, s_shl1 : std_logic_vector(5 downto 0);
+signal s_shr2 : std_logic;
+signal s_expo1, s_expo2, s_expo3 : std_logic_vector(8 downto 0);
+signal s_fraco1 : std_logic_vector(26 downto 0);
+signal s_frac_rnd, s_fraco2 : std_logic_vector(24 downto 0);
+signal s_guard, s_round, s_sticky, s_roundup : std_logic;
+signal s_lost : std_logic;
+
+signal s_op_0, s_opab_0, s_opb_0 : std_logic;
+signal s_infa, s_infb : std_logic;
+signal s_nan_in, s_nan_op, s_nan_a, s_nan_b : std_logic;
+signal s_inf_result: std_logic;
+
+begin
+
+ -- Input Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ s_opa_i <= opa_i;
+ s_opb_i <= opb_i;
+ s_expa <= opa_i(30 downto 23);
+ s_expb <= opb_i(30 downto 23);
+ s_qutnt_i <= qutnt_i;
+ s_rmndr_i <= rmndr_i;
+ s_exp_10_i <= exp_10_i;
+ s_sign_i <= sign_i;
+ s_rmode_i <= rmode_i;
+ end if;
+ end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ output_o <= s_output_o;
+ ine_o <= s_ine_o;
+ end if;
+ end process;
+
+ -- qutnt_i
+ -- 26 25 3
+ -- | | |
+ -- h fffffffffffffffffffffff grs
+
+ --*** Stage 1 ****
+ -- figure out the exponent and howmuch the fraction has to be shiftd right/left
+
+ s_opa_dn <= '1' when or_reduce(s_expa)='0' and or_reduce(opa_i(22 downto 0))='1' else '0';
+ s_opb_dn <= '1' when or_reduce(s_expb)='0' and or_reduce(opb_i(22 downto 0))='1' else '0';
+
+ s_qutdn <= not s_qutnt_i(26);
+
+
+ s_exp_10b <= s_exp_10_i - ("000000000"&s_qutdn);
+
+
+
+ process(clk_i)
+ variable v_shr, v_shl : std_logic_vector(9 downto 0);
+ begin
+ if rising_edge(clk_i) then
+ if s_exp_10b(9)='1' or s_exp_10b="0000000000" then
+ v_shr := ("0000000001" - s_exp_10b) - s_qutdn;
+ v_shl := (others =>'0');
+ s_expo1 <= "000000001";
+ elsif s_exp_10b(8)='1' then
+ v_shr := (others =>'0');
+ v_shl := (others =>'0');
+ s_expo1 <= s_exp_10b(8 downto 0);
+ else
+ v_shr := (others =>'0');
+ v_shl := "000000000"& s_qutdn;
+ s_expo1 <= s_exp_10b(8 downto 0);
+ end if;
+ if v_shr(6)='1' then
+ s_shr1 <= "111111";
+ else
+ s_shr1 <= v_shr(5 downto 0);
+ end if;
+ s_shl1 <= v_shl(5 downto 0);
+ end if;
+ end process;
+
+
+ -- *** Stage 2 ***
+ -- Shifting the fraction and rounding
+
+
+ -- shift the fraction
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_shr1 /= "000000" then
+ s_fraco1 <= shr(s_qutnt_i, s_shr1);
+ else
+ s_fraco1 <= shl(s_qutnt_i, s_shl1);
+ end if;
+ end if;
+ end process;
+
+ s_expo2 <= s_expo1 - "000000001" when s_fraco1(26)='0' else s_expo1;
+
+
+ s_r_zeros <= count_r_zeros(s_qutnt_i);
+
+
+ s_lost <= '1' when (s_shr1+("00000"&s_shr2)) > s_r_zeros else '0';
+
+ -- ***Stage 3***
+ -- Rounding
+
+ s_guard <= s_fraco1(2);
+ s_round <= s_fraco1(1);
+ s_sticky <= s_fraco1(0) or or_reduce(s_rmndr_i);
+
+ s_roundup <= s_guard and ((s_round or s_sticky)or s_fraco1(3)) when s_rmode_i="00" else -- round to nearset even
+ ( s_guard or s_round or s_sticky) and (not s_sign_i) when s_rmode_i="10" else -- round up
+ ( s_guard or s_round or s_sticky) and (s_sign_i) when s_rmode_i="11" else -- round down
+ '0'; -- round to zero(truncate = no rounding)
+
+
+ s_frac_rnd <= ("0"&s_fraco1(26 downto 3)) + '1' when s_roundup='1' else "0"&s_fraco1(26 downto 3);
+ s_shr2 <= s_frac_rnd(24);
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_shr2='1' then
+ s_expo3 <= s_expo2 + "1";
+ s_fraco2 <= "0"&s_frac_rnd(24 downto 1);
+ else
+ s_expo3 <= s_expo2;
+ s_fraco2 <= s_frac_rnd;
+ end if;
+ end if;
+ end process;
+
+
+ ---
+
+ ---***Stage 4****
+ -- Output
+
+ s_op_0 <= not ( or_reduce(s_opa_i(30 downto 0)) and or_reduce(s_opb_i(30 downto 0)) );
+ s_opab_0 <= not ( or_reduce(s_opa_i(30 downto 0)) or or_reduce(s_opb_i(30 downto 0)) );
+ s_opb_0 <= not or_reduce(s_opb_i(30 downto 0));
+
+ s_infa <= '1' when s_expa="11111111" else '0';
+ s_infb <= '1' when s_expb="11111111" else '0';
+
+ s_nan_a <= '1' when (s_infa='1' and or_reduce (s_opa_i(22 downto 0))='1') else '0';
+ s_nan_b <= '1' when (s_infb='1' and or_reduce (s_opb_i(22 downto 0))='1') else '0';
+ s_nan_in <= '1' when s_nan_a='1' or s_nan_b='1' else '0';
+ s_nan_op <= '1' when (s_infa and s_infb)='1' or s_opab_0='1' else '0';-- 0 / 0, inf / inf
+
+ s_inf_result <= '1' when (and_reduce(s_expo3(7 downto 0)) or s_expo3(8))='1' or s_opb_0='1' else '0';
+
+ s_overflow <= '1' when s_inf_result='1' and (s_infa or s_infb)='0' and s_opb_0='0' else '0';
+
+ s_ine_o <= '1' when s_op_0='0' and (s_lost or or_reduce(s_fraco1(2 downto 0)) or s_overflow or or_reduce(s_rmndr_i))='1' else '0';
+
+ process(s_sign_i, s_expo3, s_fraco2, s_nan_in, s_nan_op, s_infa, s_infb, s_overflow, s_inf_result, s_op_0)
+ begin
+ if (s_nan_in or s_nan_op)='1' then
+ s_output_o <= '1' & QNAN;
+ elsif (s_infa or s_infb)='1' or s_overflow='1' or s_inf_result='1' then
+ s_output_o <= s_sign_i & INF;
+ elsif s_op_0='1' then
+ s_output_o <= s_sign_i & ZERO_VECTOR;
+ else
+ s_output_o <= s_sign_i & s_expo3(7 downto 0) & s_fraco2(22 downto 0);
+ end if;
+ end process;
+
+end rtl;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: post-normalization entity for the multiplication unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity post_norm_mul is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ exp_10_i : in std_logic_vector(EXP_WIDTH+1 downto 0);
+ fract_48_i : in std_logic_vector(2*FRAC_WIDTH+1 downto 0); -- hidden(1) & fraction(23)
+ sign_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+end post_norm_mul;
+
+architecture rtl of post_norm_mul is
+
+signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_exp_10_i : std_logic_vector(EXP_WIDTH+1 downto 0);
+signal s_fract_48_i : std_logic_vector(2*FRAC_WIDTH+1 downto 0);
+signal s_sign_i : std_logic;
+signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_ine_o, s_overflow : std_logic;
+signal s_opa_i, s_opb_i : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_rmode_i : std_logic_vector(1 downto 0);
+
+signal s_zeros : std_logic_vector(5 downto 0);
+signal s_carry : std_logic;
+signal s_shr2, s_shl2 : std_logic_vector(5 downto 0);
+signal s_expo1, s_expo2b : std_logic_vector(8 downto 0);
+signal s_exp_10a, s_exp_10b : std_logic_vector(9 downto 0);
+signal s_frac2a : std_logic_vector(47 downto 0);
+
+signal s_sticky, s_guard, s_round : std_logic;
+signal s_roundup : std_logic;
+signal s_frac_rnd, s_frac3 : std_logic_vector(24 downto 0);
+signal s_shr3 : std_logic;
+signal s_r_zeros : std_logic_vector(5 downto 0);
+signal s_lost : std_logic;
+signal s_op_0 : std_logic;
+signal s_expo3 : std_logic_vector(8 downto 0);
+
+signal s_infa, s_infb : std_logic;
+signal s_nan_in, s_nan_op, s_nan_a, s_nan_b : std_logic;
+
+begin
+
+ -- Input Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ s_opa_i <= opa_i;
+ s_opb_i <= opb_i;
+ s_expa <= opa_i(30 downto 23);
+ s_expb <= opb_i(30 downto 23);
+ s_exp_10_i <= exp_10_i;
+ s_fract_48_i <= fract_48_i;
+ s_sign_i <= sign_i;
+ s_rmode_i <= rmode_i;
+ end if;
+ end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ output_o <= s_output_o;
+ ine_o <= s_ine_o;
+ end if;
+ end process;
+
+ --*** Stage 1 ****
+ -- figure out the exponent and howmuch the fraction has to be shiftd right/left
+
+ s_carry <= s_fract_48_i(47);
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_fract_48_i(47)='0' then
+ s_zeros <= count_l_zeros(s_fract_48_i(46 downto 1));
+ else
+ s_zeros <= "000000";
+ end if;
+ s_r_zeros <= count_r_zeros(s_fract_48_i);
+ end if;
+ end process;
+
+ s_exp_10a <= s_exp_10_i + ("000000000"&s_carry);
+ s_exp_10b <= s_exp_10a - ("0000"&s_zeros);
+
+ process(clk_i)
+ variable v_shr1, v_shl1 : std_logic_vector(9 downto 0);
+ begin
+ if rising_edge(clk_i) then
+ if s_exp_10a(9)='1' or s_exp_10a="0000000000" then
+ v_shr1 := "0000000001" - s_exp_10a + ("000000000"&s_carry);
+ v_shl1 := (others =>'0');
+ s_expo1 <= "000000001";
+ else
+ if s_exp_10b(9)='1' or s_exp_10b="0000000000" then
+ v_shr1 := (others =>'0');
+ v_shl1 := ("0000"&s_zeros) - s_exp_10a;
+ s_expo1 <= "000000001";
+ elsif s_exp_10b(8)='1' then
+ v_shr1 := (others =>'0');
+ v_shl1 := (others =>'0');
+ s_expo1 <= "011111111";
+ else
+ v_shr1 := ("000000000"&s_carry);
+ v_shl1 := ("0000"&s_zeros);
+ s_expo1 <= s_exp_10b(8 downto 0);
+ end if;
+ end if;
+ if v_shr1(6)='1' then --"110000" = 48; maximal shift-right postions
+ s_shr2 <= "111111";
+ else
+ s_shr2 <= v_shr1(5 downto 0);
+ end if;
+ s_shl2 <= v_shl1(5 downto 0);
+ end if;
+ end process;
+
+
+ -- *** Stage 2 ***
+ -- Shifting the fraction and rounding
+
+
+ -- shift the fraction
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_shr2 /= "000000" then
+ s_frac2a <= shr(s_fract_48_i, s_shr2);
+ else
+ s_frac2a <= shl(s_fract_48_i, s_shl2);
+ end if;
+ end if;
+ end process;
+
+ s_expo2b <= s_expo1 - "000000001" when s_frac2a(46)='0' else s_expo1;
+
+
+
+ -- signals if precision was last during the right-shift above
+ s_lost <= '1' when (s_shr2+("00000"&s_shr3)) > s_r_zeros else '0';
+
+
+ -- ***Stage 3***
+ -- Rounding
+
+ -- 23
+ -- |
+ -- xx00000000000000000000000grsxxxxxxxxxxxxxxxxxxxx
+ -- guard bit: s_frac2a(23) (LSB of output)
+ -- round bit: s_frac2a(22)
+ s_guard <= s_frac2a(22);
+ s_round <= s_frac2a(21);
+ s_sticky <= or_reduce(s_frac2a(20 downto 0)) or s_lost;
+
+ s_roundup <= s_guard and ((s_round or s_sticky)or s_frac2a(23)) when s_rmode_i="00" else -- round to nearset even
+ ( s_guard or s_round or s_sticky) and (not s_sign_i) when s_rmode_i="10" else -- round up
+ ( s_guard or s_round or s_sticky) and (s_sign_i) when s_rmode_i="11" else -- round down
+ '0'; -- round to zero(truncate = no rounding)
+
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_roundup='1' then
+ s_frac_rnd <= (s_frac2a(47 downto 23)) + "1";
+ else
+ s_frac_rnd <= (s_frac2a(47 downto 23));
+ end if;
+ end if;
+ end process;
+
+ s_shr3 <= s_frac_rnd(24);
+
+
+
+ s_expo3 <= s_expo2b + '1' when s_shr3='1' and s_expo2b /= "011111111" else s_expo2b;
+ s_frac3 <= ("0"&s_frac_rnd(24 downto 1)) when s_shr3='1' and s_expo2b /= "011111111" else s_frac_rnd;
+
+
+ ---***Stage 4****
+ -- Output
+
+ s_op_0 <= not ( or_reduce(s_opa_i(30 downto 0)) and or_reduce(s_opb_i(30 downto 0)) );
+
+ s_infa <= '1' when s_expa="11111111" else '0';
+ s_infb <= '1' when s_expb="11111111" else '0';
+
+ s_nan_a <= '1' when (s_infa='1' and or_reduce (s_opa_i(22 downto 0))='1') else '0';
+ s_nan_b <= '1' when (s_infb='1' and or_reduce (s_opb_i(22 downto 0))='1') else '0';
+ s_nan_in <= '1' when s_nan_a='1' or s_nan_b='1' else '0';
+ s_nan_op <= '1' when (s_infa or s_infb)='1' and s_op_0='1' else '0';-- 0 * inf = nan
+
+
+ s_overflow <= '1' when s_expo3 = "011111111" and (s_infa or s_infb)='0' else '0';
+
+ s_ine_o <= '1' when s_op_0='0' and (s_lost or or_reduce(s_frac2a(22 downto 0)) or s_overflow)='1' else '0';
+
+ process(s_sign_i, s_expo3, s_frac3, s_nan_in, s_nan_op, s_infa, s_infb, s_overflow, s_r_zeros)
+ begin
+ if (s_nan_in or s_nan_op)='1' then
+ s_output_o <= s_sign_i & QNAN;
+ elsif (s_infa or s_infb)='1' or s_overflow='1' then
+ s_output_o <= s_sign_i & INF;
+ elsif s_r_zeros=48 then
+ s_output_o <= s_sign_i & ZERO_VECTOR;
+ else
+ s_output_o <= s_sign_i & s_expo3(7 downto 0) & s_frac3(22 downto 0);
+
+ end if;
+ end process;
+
+end rtl;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: post-normalization entity for the square-root unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity post_norm_sqrt is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ fract_26_i : in std_logic_vector(FRAC_WIDTH+2 downto 0); -- hidden(1) & fraction(11)
+ exp_i : in std_logic_vector(EXP_WIDTH-1 downto 0);
+ ine_i : in std_logic;
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(FP_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+end post_norm_sqrt;
+
+architecture rtl of post_norm_sqrt is
+
+signal s_expa, s_exp_i : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_fract_26_i : std_logic_vector(FRAC_WIDTH+2 downto 0);
+signal s_ine_i : std_logic;
+signal s_rmode_i : std_logic_vector(1 downto 0);
+signal s_output_o : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_sign_i : std_logic;
+signal s_opa_i : std_logic_vector(FP_WIDTH-1 downto 0);
+signal s_ine_o : std_logic;
+
+signal s_expo : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_fraco1 : std_logic_vector(FRAC_WIDTH+2 downto 0);
+
+signal s_guard, s_round, s_sticky, s_roundup : std_logic;
+signal s_frac_rnd : std_logic_vector(FRAC_WIDTH downto 0);
+
+
+signal s_infa : std_logic;
+signal s_nan_op, s_nan_a: std_logic;
+
+begin
+
+ -- Input Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ s_opa_i <= opa_i;
+ s_expa <= opa_i(30 downto 23);
+ s_sign_i <= opa_i(31);
+ s_fract_26_i <= fract_26_i;
+ s_ine_i <= ine_i;
+ s_exp_i <= exp_i;
+ s_rmode_i <= rmode_i;
+ end if;
+ end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ output_o <= s_output_o;
+ ine_o <= s_ine_o;
+ end if;
+ end process;
+
+
+ -- *** Stage 1 ***
+
+ s_expo <= s_exp_i;
+
+ s_fraco1 <= s_fract_26_i;
+
+
+ -- ***Stage 2***
+ -- Rounding
+
+ s_guard <= s_fraco1(1);
+ s_round <= s_fraco1(0);
+ s_sticky <= s_ine_i;
+
+ s_roundup <= s_guard and ((s_round or s_sticky)or s_fraco1(3)) when s_rmode_i="00" else -- round to nearset even
+ ( s_guard or s_round or s_sticky) and (not s_sign_i) when s_rmode_i="10" else -- round up
+ ( s_guard or s_round or s_sticky) and (s_sign_i) when s_rmode_i="11" else -- round down
+ '0'; -- round to zero(truncate = no rounding)
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_roundup='1' then
+ s_frac_rnd <= s_fraco1(25 downto 2) + '1';
+ else
+ s_frac_rnd <= s_fraco1(25 downto 2);
+ end if;
+ end if;
+ end process;
+
+
+
+ -- ***Stage 3***
+ -- Output
+
+ s_infa <= '1' when s_expa="11111111" else '0';
+ s_nan_a <= '1' when (s_infa='1' and or_reduce (s_opa_i(22 downto 0))='1') else '0';
+ s_nan_op <= '1' when s_sign_i='1' and or_reduce(s_opa_i(30 downto 0))='1' else '0'; -- sqrt(-x) = NaN
+
+ s_ine_o <= '1' when s_ine_i='1' and (s_infa or s_nan_a or s_nan_op)='0' else '0';
+
+ process( s_nan_a, s_nan_op, s_infa, s_sign_i, s_expo, s_frac_rnd)
+ begin
+ if (s_nan_a or s_nan_op)='1' then
+ s_output_o <= s_sign_i & QNAN;
+ elsif s_infa ='1' then
+ s_output_o <= s_sign_i & INF;
+ else
+ s_output_o <= s_sign_i & s_expo & s_frac_rnd(22 downto 0);
+
+ end if;
+ end process;
+
+end rtl;
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: pre-normalization entity for the addition/subtraction unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity pre_norm_addsub is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ fracta_28_o : out std_logic_vector(FRAC_WIDTH+4 downto 0); -- carry(1) & hidden(1) & fraction(23) & guard(1) & round(1) & sticky(1)
+ fractb_28_o : out std_logic_vector(FRAC_WIDTH+4 downto 0);
+ exp_o : out std_logic_vector(EXP_WIDTH-1 downto 0)
+ );
+end pre_norm_addsub;
+
+
+architecture rtl of pre_norm_addsub is
+
+
+ signal s_exp_o : std_logic_vector(EXP_WIDTH-1 downto 0);
+ signal s_fracta_28_o, s_fractb_28_o : std_logic_vector(FRAC_WIDTH+4 downto 0);
+ signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
+ signal s_fracta, s_fractb : std_logic_vector(FRAC_WIDTH-1 downto 0);
+
+ signal s_fracta_28, s_fractb_28, s_fract_sm_28, s_fract_shr_28 : std_logic_vector(FRAC_WIDTH+4 downto 0);
+
+ signal s_exp_diff : std_logic_vector(EXP_WIDTH-1 downto 0);
+ signal s_rzeros : std_logic_vector(5 downto 0);
+
+ signal s_expa_eq_expb : std_logic;
+ signal s_expa_lt_expb : std_logic;
+ signal s_fracta_1 : std_logic;
+ signal s_fractb_1 : std_logic;
+ signal s_op_dn,s_opa_dn, s_opb_dn : std_logic;
+ signal s_mux_diff : std_logic_vector(1 downto 0);
+ signal s_mux_exp : std_logic;
+ signal s_sticky : std_logic;
+begin
+
+ -- Input Register
+ --process(clk_i)
+ --begin
+ -- if rising_edge(clk_i) then
+ s_expa <= opa_i(30 downto 23);
+ s_expb <= opb_i(30 downto 23);
+ s_fracta <= opa_i(22 downto 0);
+ s_fractb <= opb_i(22 downto 0);
+ -- end if;
+ --end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ exp_o <= s_exp_o;
+ fracta_28_o <= s_fracta_28_o;
+ fractb_28_o <= s_fractb_28_o;
+ end if;
+ end process;
+
+ s_expa_eq_expb <= '1' when s_expa = s_expb else '0';
+ s_expa_lt_expb <= '1' when s_expa > s_expb else '0';
+
+ -- '1' if fraction is not zero
+ s_fracta_1 <= or_reduce(s_fracta);
+ s_fractb_1 <= or_reduce(s_fractb);
+
+ -- opa or Opb is denormalized
+ s_op_dn <= s_opa_dn or s_opb_dn;
+ s_opa_dn <= not or_reduce(s_expa);
+ s_opb_dn <= not or_reduce(s_expb);
+
+ -- output the larger exponent
+ s_mux_exp <= s_expa_lt_expb;
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ case s_mux_exp is
+ when '0' => s_exp_o <= s_expb;
+ when '1' => s_exp_o <= s_expa;
+ when others => s_exp_o <= "11111111";
+ end case;
+ end if;
+ end process;
+
+ -- convert to an easy to handle floating-point format
+ s_fracta_28 <= "01" & s_fracta & "000" when s_opa_dn='0' else "00" & s_fracta & "000";
+ s_fractb_28 <= "01" & s_fractb & "000" when s_opb_dn='0' else "00" & s_fractb & "000";
+
+
+ s_mux_diff <= s_expa_lt_expb & (s_opa_dn xor s_opb_dn);
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ -- calculate howmany postions the fraction will be shifted
+ case s_mux_diff is
+ when "00"=> s_exp_diff <= s_expb - s_expa;
+ when "01"=> s_exp_diff <= s_expb - (s_expa+"00000001");
+ when "10"=> s_exp_diff <= s_expa - s_expb;
+ when "11"=> s_exp_diff <= s_expa - (s_expb+"00000001");
+ when others => s_exp_diff <= "11110000";
+ end case;
+ end if;
+ end process;
+
+
+ s_fract_sm_28 <= s_fracta_28 when s_expa_lt_expb='0' else s_fractb_28;
+
+ -- shift-right the fraction if necessary
+ s_fract_shr_28 <= shr(s_fract_sm_28, s_exp_diff);
+
+ -- count the zeros from right to check if result is inexact
+ s_rzeros <= count_r_zeros(s_fract_sm_28);
+ s_sticky <= '1' when s_exp_diff > s_rzeros and or_reduce(s_fract_sm_28)='1' else '0';
+
+ s_fracta_28_o <= s_fracta_28 when s_expa_lt_expb='1' else s_fract_shr_28(27 downto 1) & (s_sticky or s_fract_shr_28(0));
+ s_fractb_28_o <= s_fractb_28 when s_expa_lt_expb='0' else s_fract_shr_28(27 downto 1) & (s_sticky or s_fract_shr_28(0));
+
+
+end rtl;
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: pre-normalization entity for the division unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity pre_norm_div is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ exp_10_o : out std_logic_vector(EXP_WIDTH+1 downto 0);
+ dvdnd_50_o : out std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0);
+ dvsor_27_o : out std_logic_vector(FRAC_WIDTH+3 downto 0)
+ );
+end pre_norm_div;
+
+architecture rtl of pre_norm_div is
+
+
+signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_fracta, s_fractb : std_logic_vector(FRAC_WIDTH-1 downto 0);
+signal s_dvdnd_50_o : std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0);
+signal s_dvsor_27_o : std_logic_vector(FRAC_WIDTH+3 downto 0);
+signal s_dvd_zeros, s_div_zeros: std_logic_vector(5 downto 0);
+signal s_exp_10_o : std_logic_vector(EXP_WIDTH+1 downto 0);
+
+signal s_expa_in, s_expb_in : std_logic_vector(EXP_WIDTH+1 downto 0);
+signal s_opa_dn, s_opb_dn : std_logic;
+signal s_fracta_24, s_fractb_24 : std_logic_vector(FRAC_WIDTH downto 0);
+
+begin
+
+ s_expa <= opa_i(30 downto 23);
+ s_expb <= opb_i(30 downto 23);
+ s_fracta <= opa_i(22 downto 0);
+ s_fractb <= opb_i(22 downto 0);
+ dvdnd_50_o <= s_dvdnd_50_o;
+ dvsor_27_o <= s_dvsor_27_o;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ exp_10_o <= s_exp_10_o;
+ end if;
+ end process;
+
+
+ s_opa_dn <= not or_reduce(s_expa);
+ s_opb_dn <= not or_reduce(s_expb);
+
+ s_fracta_24 <= (not s_opa_dn) & s_fracta;
+ s_fractb_24 <= (not s_opb_dn) & s_fractb;
+
+ -- count leading zeros
+ s_dvd_zeros <= count_l_zeros( s_fracta_24 );
+ s_div_zeros <= count_l_zeros( s_fractb_24 );
+
+ -- left-shift the dividend and divisor
+ s_dvdnd_50_o <= shl(s_fracta_24, s_dvd_zeros) & "00000000000000000000000000";
+ s_dvsor_27_o <= "000" & shl(s_fractb_24, s_div_zeros);
+
+
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ -- pre-calculate exponent
+ s_expa_in <= ("00"&s_expa) + ("000000000"&s_opa_dn);
+ s_expb_in <= ("00"&s_expb) + ("000000000"&s_opb_dn);
+ s_exp_10_o <= s_expa_in - s_expb_in + "0001111111" -("0000"&s_dvd_zeros) + ("0000"&s_div_zeros);
+ end if;
+ end process;
+
+
+
+
+end rtl;
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: pre-normalization entity for the multiplication unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity pre_norm_mul is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ opb_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ exp_10_o : out std_logic_vector(EXP_WIDTH+1 downto 0);
+ fracta_24_o : out std_logic_vector(FRAC_WIDTH downto 0); -- hidden(1) & fraction(23)
+ fractb_24_o : out std_logic_vector(FRAC_WIDTH downto 0)
+ );
+end pre_norm_mul;
+
+architecture rtl of pre_norm_mul is
+
+signal s_expa, s_expb : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_fracta, s_fractb : std_logic_vector(FRAC_WIDTH-1 downto 0);
+signal s_exp_10_o, s_expa_in, s_expb_in : std_logic_vector(EXP_WIDTH+1 downto 0);
+
+signal s_opa_dn, s_opb_dn : std_logic;
+
+begin
+
+
+ s_expa <= opa_i(30 downto 23);
+ s_expb <= opb_i(30 downto 23);
+ s_fracta <= opa_i(22 downto 0);
+ s_fractb <= opb_i(22 downto 0);
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ exp_10_o <= s_exp_10_o;
+ end if;
+ end process;
+
+ -- opa or opb is denormalized
+ s_opa_dn <= not or_reduce(s_expa);
+ s_opb_dn <= not or_reduce(s_expb);
+
+
+ fracta_24_o <= not(s_opa_dn) & s_fracta;
+ fractb_24_o <= not(s_opb_dn) & s_fractb;
+
+ s_expa_in <= ("00"&s_expa) + ("000000000"&s_opa_dn);
+ s_expb_in <= ("00"&s_expb) + ("000000000"&s_opb_dn);
+
+
+
+ s_exp_10_o <= s_expa_in + s_expb_in - "0001111111";
+
+
+
+end rtl;
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: pre-normalization entity for the square-root unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+entity pre_norm_sqrt is
+ port(
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(FP_WIDTH-1 downto 0);
+ fracta_52_o : out std_logic_vector(2*(FRAC_WIDTH+3)-1 downto 0);
+ exp_o : out std_logic_vector(EXP_WIDTH-1 downto 0)
+ );
+end pre_norm_sqrt;
+
+architecture rtl of pre_norm_sqrt is
+
+signal s_expa : std_logic_vector(EXP_WIDTH-1 downto 0);
+signal s_exp_o, s_exp_tem : std_logic_vector(EXP_WIDTH downto 0);
+signal s_fracta : std_logic_vector(FRAC_WIDTH-1 downto 0);
+signal s_fracta_24 : std_logic_vector(FRAC_WIDTH downto 0);
+signal s_fracta_52_o, s_fracta1_52_o, s_fracta2_52_o : std_logic_vector(2*(FRAC_WIDTH+3)-1 downto 0);
+signal s_sqr_zeros_o : std_logic_vector(5 downto 0);
+
+
+signal s_opa_dn : std_logic;
+
+begin
+
+ s_expa <= opa_i(30 downto 23);
+ s_fracta <= opa_i(22 downto 0);
+
+
+ exp_o <= s_exp_o(7 downto 0);
+ fracta_52_o <= s_fracta_52_o;
+
+ -- opa or opb is denormalized
+ s_opa_dn <= not or_reduce(s_expa);
+
+ s_fracta_24 <= (not s_opa_dn) & s_fracta;
+
+ -- count leading zeros
+ s_sqr_zeros_o <= count_l_zeros(s_fracta_24 );
+
+ -- adjust the exponent
+ s_exp_tem <= ("0"&s_expa)+"001111111" - ("000"&s_sqr_zeros_o);
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if or_reduce(opa_i(30 downto 0))='1' then
+ s_exp_o <= ("0"&s_exp_tem(8 downto 1));
+ else
+ s_exp_o <= "000000000";
+ end if;
+ end if;
+ end process;
+
+ -- left-shift the radicand
+ s_fracta1_52_o <= shl(s_fracta_24, s_sqr_zeros_o) & "0000000000000000000000000000";
+ s_fracta2_52_o <= '0' & shl(s_fracta_24, s_sqr_zeros_o) & "000000000000000000000000000";
+
+ s_fracta_52_o <= s_fracta1_52_o when s_expa(0)='0' else s_fracta2_52_o;
+
+end rtl;
--- /dev/null
+The Compilation order is:
+
+fpupack.vhd
+pre_norm_addsub.vhd
+addsub_28.vhd
+post_norm_addsub.vhd
+pre_norm_mul.vhd
+mul_24.vhd
+vcom serial_mul.vhd
+post_norm_mul.vhd
+pre_norm_div.vhd
+serial_div.vhd
+post_norm_div.vhd
+pre_norm_sqrt.vhd
+sqrt.vhd
+post_norm_sqrt.vhd
+comppack.vhd
+fpu.vhd
+
+***For simulation ****
+To run the simulation read readme.txt in folder test_bench.
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: division entity for the division unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_misc.all;
+
+library work;
+use work.fpupack.all;
+
+
+entity serial_div is
+ port(
+ clk_i : in std_logic;
+ dvdnd_i : in std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0); -- hidden(1) & fraction(23)
+ dvsor_i : in std_logic_vector(FRAC_WIDTH+3 downto 0);
+ sign_dvd_i : in std_logic;
+ sign_div_i : in std_logic;
+ start_i : in std_logic;
+ ready_o : out std_logic;
+ qutnt_o : out std_logic_vector(FRAC_WIDTH+3 downto 0);
+ rmndr_o : out std_logic_vector(FRAC_WIDTH+3 downto 0);
+ sign_o : out std_logic;
+ div_zero_o : out std_logic
+ );
+end serial_div;
+
+architecture rtl of serial_div is
+
+type t_state is (waiting,busy);
+
+signal s_qutnt_o, s_rmndr_o : std_logic_vector(FRAC_WIDTH+3 downto 0);
+
+signal s_dvdnd_i : std_logic_vector(2*(FRAC_WIDTH+2)-1 downto 0);
+signal s_dvsor_i : std_logic_vector(FRAC_WIDTH+3 downto 0);
+signal s_sign_dvd_i, s_sign_div_i, s_sign_o : std_logic;
+signal s_div_zero_o : std_logic;
+signal s_start_i, s_ready_o : std_logic;
+signal s_state : t_state;
+signal s_count : integer range 0 to FRAC_WIDTH+3;
+signal s_dvd : std_logic_vector(FRAC_WIDTH+3 downto 0);
+
+begin
+
+
+-- Input Register
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ s_dvdnd_i <= dvdnd_i;
+ s_dvsor_i <= dvsor_i;
+ s_sign_dvd_i<= sign_dvd_i;
+ s_sign_div_i<= sign_div_i;
+ s_start_i <= start_i;
+ end if;
+end process;
+
+-- Output Register
+--process(clk_i)
+--begin
+-- if rising_edge(clk_i) then
+ qutnt_o <= s_qutnt_o;
+ rmndr_o <= s_rmndr_o;
+ sign_o <= s_sign_o;
+ ready_o <= s_ready_o;
+ div_zero_o <= s_div_zero_o;
+-- end if;
+--end process;
+
+s_sign_o <= sign_dvd_i xor sign_div_i;
+s_div_zero_o <= '1' when or_reduce(s_dvsor_i)='0' and or_reduce(s_dvdnd_i)='1' else '0';
+
+-- FSM
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ if s_start_i ='1' then
+ s_state <= busy;
+ s_count <= 26;
+ elsif s_count=0 and s_state=busy then
+ s_state <= waiting;
+ s_ready_o <= '1';
+ s_count <=26;
+ elsif s_state=busy then
+ s_count <= s_count - 1;
+ else
+ s_state <= waiting;
+ s_ready_o <= '0';
+ end if;
+ end if;
+end process;
+
+
+process(clk_i)
+variable v_div : std_logic_vector(26 downto 0);
+begin
+ if rising_edge(clk_i) then
+ --Reset
+ if s_start_i ='1' then
+ s_qutnt_o <= (others =>'0');
+ s_rmndr_o <= (others =>'0');
+ elsif s_state=busy then
+ if s_count=26 then
+ v_div := "000" & s_dvdnd_i(49 downto 26);
+ else
+ v_div:= s_dvd;
+ end if;
+ if v_div < s_dvsor_i then
+ s_qutnt_o(s_count) <= '0';
+ else
+ s_qutnt_o(s_count) <= '1';
+ v_div:=v_div-s_dvsor_i;
+ end if;
+ s_rmndr_o <= v_div;
+ s_dvd <= v_div(25 downto 0)&'0';
+ end if;
+ end if;
+end process;
+
+end rtl;
+
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: Serial multiplication entity for the multiplication unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+library work;
+use work.fpupack.all;
+
+entity serial_mul is
+ port(
+ clk_i : in std_logic;
+ fracta_i : in std_logic_vector(FRAC_WIDTH downto 0); -- hidden(1) & fraction(23)
+ fractb_i : in std_logic_vector(FRAC_WIDTH downto 0);
+ signa_i : in std_logic;
+ signb_i : in std_logic;
+ start_i : in std_logic;
+ fract_o : out std_logic_vector(2*FRAC_WIDTH+1 downto 0);
+ sign_o : out std_logic;
+ ready_o : out std_logic
+ );
+end serial_mul;
+
+architecture rtl of serial_mul is
+
+type t_state is (waiting,busy);
+
+signal s_fract_o: std_logic_vector(47 downto 0);
+
+signal s_fracta_i, s_fractb_i : std_logic_vector(23 downto 0);
+signal s_signa_i, s_signb_i, s_sign_o : std_logic;
+signal s_start_i, s_ready_o : std_logic;
+signal s_state : t_state;
+signal s_count : integer range 0 to 23;
+signal s_tem_prod : std_logic_vector(23 downto 0);
+
+begin
+
+-- Input Register
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ s_fracta_i <= fracta_i;
+ s_fractb_i <= fractb_i;
+ s_signa_i<= signa_i;
+ s_signb_i<= signb_i;
+ s_start_i <= start_i;
+ end if;
+end process;
+
+-- Output Register
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ fract_o <= s_fract_o;
+ sign_o <= s_sign_o;
+ ready_o <= s_ready_o;
+ end if;
+end process;
+
+s_sign_o <= signa_i xor signb_i;
+
+-- FSM
+process(clk_i)
+begin
+ if rising_edge(clk_i) then
+ if s_start_i ='1' then
+ s_state <= busy;
+ s_count <= 0;
+ elsif s_count=23 then
+ s_state <= waiting;
+ s_ready_o <= '1';
+ s_count <=0;
+ elsif s_state=busy then
+ s_count <= s_count + 1;
+ else
+ s_state <= waiting;
+ s_ready_o <= '0';
+ end if;
+ end if;
+end process;
+
+g1: for i in 0 to 23 generate
+ s_tem_prod(i) <= s_fracta_i(i) and s_fractb_i(s_count);
+end generate;
+
+process(clk_i)
+variable v_prod_shl : std_logic_vector(47 downto 0);
+begin
+ if rising_edge(clk_i) then
+ if s_state=busy then
+ v_prod_shl := shl(conv_std_logic_vector(0,24)&s_tem_prod, conv_std_logic_vector(s_count,5));
+ if s_count /= 0 then
+ s_fract_o <= v_prod_shl + s_fract_o;
+ else
+ s_fract_o <= v_prod_shl;
+ end if;
+ end if;
+ end if;
+end process;
+
+end rtl;
+
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: square-root entity for the square-root unit
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee ;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity sqrt is
+ generic (RD_WIDTH: integer:=52; SQ_WIDTH: integer:=26); -- SQ_WIDTH = RD_WIDTH/2 (+ 1 if odd)
+ port(
+ clk_i : in std_logic;
+ rad_i : in std_logic_vector(RD_WIDTH-1 downto 0); -- hidden(1) & fraction(23)
+ start_i : in std_logic;
+ ready_o : out std_logic;
+ sqr_o : out std_logic_vector(SQ_WIDTH-1 downto 0);
+ ine_o : out std_logic
+ );
+end sqrt;
+
+architecture rtl of sqrt is
+
+signal s_rad_i: std_logic_vector(RD_WIDTH-1 downto 0);
+signal s_start_i, s_ready_o : std_logic;
+signal s_sqr_o: std_logic_vector(RD_WIDTH-1 downto 0);
+signal s_ine_o : std_logic;
+
+constant ITERATIONS : integer:= RD_WIDTH/2; -- iterations = N/2
+constant WIDTH_C : integer:= 5; -- log2(ITERATIONS)
+ --0000000000000000000000000000000000000000000000000000
+constant CONST_B : std_logic_vector(RD_WIDTH-1 downto 0) :="0000000000000000000000000010000000000000000000000000"; -- b = 2^(N/2 - 1)
+constant CONST_B_2: std_logic_vector(RD_WIDTH-1 downto 0):="0100000000000000000000000000000000000000000000000000"; -- b^2
+constant CONST_C : std_logic_vector(WIDTH_C-1 downto 0):= "11010"; -- c = N/2
+
+
+signal s_count : integer range 0 to ITERATIONS;
+
+type t_state is (waiting,busy);
+signal s_state : t_state;
+
+signal b, b_2, r0, r0_2, r1, r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
+signal c : std_logic_vector(WIDTH_C-1 downto 0);
+
+ signal s_op1, s_op2, s_sum1a, s_sum1b, s_sum2a, s_sum2b : std_logic_vector(RD_WIDTH-1 downto 0);
+
+begin
+
+
+ -- Input Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ s_rad_i <= rad_i;
+ s_start_i <= start_i;
+ end if;
+ end process;
+
+ -- Output Register
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ sqr_o <= s_sqr_o(SQ_WIDTH-1 downto 0);
+ ine_o <= s_ine_o;
+ ready_o <= s_ready_o;
+ end if;
+ end process;
+
+
+ -- FSM
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_start_i ='1' then
+ s_state <= busy;
+ s_count <= ITERATIONS;
+ elsif s_count=0 and s_state=busy then
+ s_state <= waiting;
+ s_ready_o <= '1';
+ s_count <=ITERATIONS;
+ elsif s_state=busy then
+ s_count <= s_count - 1;
+ else
+ s_state <= waiting;
+ s_ready_o <= '0';
+ end if;
+ end if;
+ end process;
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_start_i='1' then
+ b <= CONST_B;
+ b_2 <= CONST_B_2;
+ c <= CONST_C;
+ else
+ b <= '0'&b(RD_WIDTH-1 downto 1); -- shr 1
+ b_2 <= "00"&b_2(RD_WIDTH-1 downto 2);-- shr 2
+ c <= c - '1';
+ end if;
+ end if;
+ end process;
+
+
+
+ s_op1 <= r0_2 + b_2;
+ s_op2 <= shl(r0, c);
+ s_sum1a <= "00000000000000000000000000"& (r0(25 downto 0) - b(25 downto 0));
+ s_sum2a <= "00000000000000000000000000"& (r0(25 downto 0) + b(25 downto 0));
+ s_sum1b <= s_op1 - s_op2;
+ s_sum2b <= s_op1 + s_op2;
+
+
+
+ process(clk_i)
+ variable v_r1, v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
+ begin
+ if rising_edge(clk_i) then
+ if s_start_i='1' then
+ r0 <= (others =>'0');
+ r0_2 <= (others =>'0');
+ elsif s_state=busy then
+ if r0_2 > s_rad_i then
+ v_r1 := s_sum1a;
+ v_r1_2 := s_sum1b;
+ else
+ v_r1 := s_sum2a;
+ v_r1_2 := s_sum2b;
+ end if;
+ r0 <= v_r1;
+ r0_2 <= v_r1_2;
+ r1 <= v_r1;
+ r1_2 <= v_r1_2;
+ end if;
+ end if;
+ end process;
+
+ process(clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if s_start_i = '1' then
+ s_sqr_o <= (others =>'0');
+ elsif s_count=0 then
+ if r1_2 > s_rad_i then
+ s_sqr_o <= r1 - '1';
+ else
+ s_sqr_o <= r1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ -- check if result is inexact. In this way we saved 1 clk cycle!
+ process(clk_i)
+ variable v_r1_2 : std_logic_vector(RD_WIDTH-1 downto 0);
+ begin
+ if rising_edge(clk_i) then
+ v_r1_2 := r1_2 - (r1(RD_WIDTH-2 downto 0)&"0") + '1';
+ if s_count=0 then
+ if r1_2 = s_rad_i or v_r1_2=s_rad_i then
+ s_ine_o <= '0';
+ else
+ s_ine_o <= '1';
+ end if;
+ end if;
+
+ end if;
+ end process;
+
+end rtl;
\ No newline at end of file
--- /dev/null
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -format Logic /tb_fpu/clk_i
+add wave -noupdate -format Literal /tb_fpu/opa_i
+add wave -noupdate -format Literal /tb_fpu/opb_i
+add wave -noupdate -format Literal /tb_fpu/fpu_op_i
+add wave -noupdate -format Literal /tb_fpu/rmode_i
+add wave -noupdate -format Literal /tb_fpu/output_o
+add wave -noupdate -format Logic /tb_fpu/start_i
+add wave -noupdate -format Logic /tb_fpu/ready_o
+add wave -noupdate -format Logic /tb_fpu/ine_o
+add wave -noupdate -format Logic /tb_fpu/overflow_o
+add wave -noupdate -format Logic /tb_fpu/underflow_o
+add wave -noupdate -format Logic /tb_fpu/div_zero_o
+add wave -noupdate -format Logic /tb_fpu/inf_o
+add wave -noupdate -format Logic /tb_fpu/zero_o
+add wave -noupdate -format Logic /tb_fpu/qnan_o
+add wave -noupdate -format Logic /tb_fpu/snan_o
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {16182 ns} 0}
+configure wave -namecolwidth 255
+configure wave -valuecolwidth 317
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+update
+WaveRestoreZoom {0 ns} {544 ns}
--- /dev/null
+set REL= ..\
+
+vlib work
+
+vcom %REL%fpupack.vhd
+vcom %REL%pre_norm_addsub.vhd
+vcom %REL%addsub_28.vhd
+vcom %REL%post_norm_addsub.vhd
+vcom %REL%pre_norm_mul.vhd
+vcom %REL%mul_24.vhd
+vcom %REL%serial_mul.vhd
+vcom %REL%post_norm_mul.vhd
+vcom %REL%pre_norm_div.vhd
+vcom %REL%serial_div.vhd
+vcom %REL%post_norm_div.vhd
+vcom %REL%pre_norm_sqrt.vhd
+vcom %REL%sqrt.vhd
+vcom %REL%post_norm_sqrt.vhd
+vcom %REL%comppack.vhd
+vcom %REL%fpu.vhd
+
+vcom txt_util.vhd
+vcom tb_fpu.vhd
+
+pause Start simulation?
+
+vsim -do fpu_wave.do tb_fpu
+
+
--- /dev/null
+timesoftfloat -nearesteven float32_add > testcases.txt
+timesoftfloat -nearesteven float32_sub >> testcases.txt
+timesoftfloat -nearesteven float32_mul >> testcases.txt
+timesoftfloat -nearesteven float32_div >> testcases.txt
+timesoftfloat -nearesteven float32_sqrt >> testcases.txt
+
+timesoftfloat -tozero float32_add >> testcases.txt
+timesoftfloat -tozero float32_sub >> testcases.txt
+timesoftfloat -tozero float32_mul >> testcases.txt
+timesoftfloat -tozero float32_div >> testcases.txt
+timesoftfloat -tozero float32_sqrt >> testcases.txt
+
+timesoftfloat -up float32_add >> testcases.txt
+timesoftfloat -up float32_sub >> testcases.txt
+timesoftfloat -up float32_mul >> testcases.txt
+timesoftfloat -up float32_div >> testcases.txt
+timesoftfloat -up float32_sqrt >> testcases.txt
+
+timesoftfloat -down float32_add >> testcases.txt
+timesoftfloat -down float32_sub >> testcases.txt
+timesoftfloat -down float32_mul >> testcases.txt
+timesoftfloat -down float32_div >> testcases.txt
+timesoftfloat -down float32_sqrt >> testcases.txt
\ No newline at end of file
--- /dev/null
+To test the FPU core, do the following:
+
+1) Build timesoftfloat.exe for your specific platform(read instructions in folder SoftFloat for howto do that).
+ Before you do that, try the already included file.
+
+2) Create the testcases by running maketest.bat in folder test_bench. Default value is 100000 cases for each
+ arithmetic operation and for each rounding mode. This comes up to 2 million test cases.
+
+3) run fpusim.bat to simulate and test the FPU core using modelsim.
\ No newline at end of file
--- /dev/null
+-------------------------------------------------------------------------------
+--
+-- Project: <Floating Point Unit Core>
+--
+-- Description: test bench for the FPU core
+-------------------------------------------------------------------------------
+--
+-- 100101011010011100100
+-- 110000111011100100000
+-- 100000111011000101101
+-- 100010111100101111001
+-- 110000111011101101001
+-- 010000001011101001010
+-- 110100111001001100001
+-- 110111010000001100111
+-- 110110111110001011101
+-- 101110110010111101000
+-- 100000010111000000000
+--
+-- Author: Jidan Al-eryani
+--
+-- Copyright (C) 2006
+--
+-- This source file may be used and distributed without
+-- restriction provided that this copyright statement is not
+-- removed from the file and that any derivative work contains
+-- the original copyright notice and the associated disclaimer.
+--
+-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.math_real.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_misc.all;
+use std.textio.all;
+use work.txt_util.all;
+
+ -- fpu operations (fpu_op_i):
+ -- ========================
+ -- 000 = add,
+ -- 001 = substract,
+ -- 010 = multiply,
+ -- 011 = divide,
+ -- 100 = square root
+ -- 101 = unused
+ -- 110 = unused
+ -- 111 = unused
+
+ -- Rounding Mode:
+ -- ==============
+ -- 00 = round to nearest even(default),
+ -- 01 = round to zero,
+ -- 10 = round up,
+ -- 11 = round down
+
+
+entity tb_fpu is
+end tb_fpu;
+
+architecture rtl of tb_fpu is
+
+component fpu
+ port (
+ clk_i : in std_logic;
+ opa_i : in std_logic_vector(31 downto 0);
+ opb_i : in std_logic_vector(31 downto 0);
+ fpu_op_i : in std_logic_vector(2 downto 0);
+ rmode_i : in std_logic_vector(1 downto 0);
+ output_o : out std_logic_vector(31 downto 0);
+ ine_o : out std_logic;
+ overflow_o : out std_logic;
+ underflow_o : out std_logic;
+ div_zero_o : out std_logic;
+ inf_o : out std_logic;
+ zero_o : out std_logic;
+ qnan_o : out std_logic;
+ snan_o : out std_logic;
+ start_i : in std_logic;
+ ready_o : out std_logic
+ );
+end component;
+
+
+signal clk_i : std_logic:= '1';
+signal opa_i, opb_i : std_logic_vector(31 downto 0);
+signal fpu_op_i : std_logic_vector(2 downto 0);
+signal rmode_i : std_logic_vector(1 downto 0);
+signal output_o : std_logic_vector(31 downto 0);
+signal start_i, ready_o : std_logic ;
+signal ine_o, overflow_o, underflow_o, div_zero_o, inf_o, zero_o, qnan_o, snan_o: std_logic;
+
+
+
+signal slv_out : std_logic_vector(31 downto 0);
+
+constant CLK_PERIOD :time := 10 ns; -- period of clk period
+
+
+begin
+
+ -- instantiate fpu
+ i_fpu: fpu port map (
+ clk_i => clk_i,
+ opa_i => opa_i,
+ opb_i => opb_i,
+ fpu_op_i => fpu_op_i,
+ rmode_i => rmode_i,
+ output_o => output_o,
+ ine_o => ine_o,
+ overflow_o => overflow_o,
+ underflow_o => underflow_o,
+ div_zero_o => div_zero_o,
+ inf_o => inf_o,
+ zero_o => zero_o,
+ qnan_o => qnan_o,
+ snan_o => snan_o,
+ start_i => start_i,
+ ready_o => ready_o);
+
+
+ ---------------------------------------------------------------------------
+ -- toggle clock
+ ---------------------------------------------------------------------------
+ clk_i <= not(clk_i) after 5 ns;
+
+
+ verify : process
+ --The operands and results are in Hex format. The test vectors must be placed in a strict order for the verfication to work.
+ file testcases_file: TEXT open read_mode is "testcases.txt"; --Name of the file containing the test cases.
+
+ variable file_line: line;
+ variable str_in: string(8 downto 1);
+ variable str_fpu_op: string(3 downto 1);
+ variable str_rmode: string(2 downto 1);
+ begin
+
+
+ ---------------------------------------------------------------------------------------------------------------------------------------------------
+ ---------------------------------------------------SoftFloat test vectors (10000 test cases for each operation) --------------------------------------------------------------------
+ start_i <= '0';
+ while not endfile(testcases_file) loop
+
+ wait for CLK_PERIOD; start_i <= '1';
+
+ str_read(testcases_file,str_in);
+ opa_i <= strhex_to_slv(str_in);
+
+ str_read(testcases_file,str_in);
+ opb_i <= strhex_to_slv(str_in);
+
+ str_read(testcases_file,str_fpu_op);
+ fpu_op_i <= to_std_logic_vector(str_fpu_op);
+
+ str_read(testcases_file,str_rmode);
+ rmode_i <= to_std_logic_vector(str_rmode);
+
+ str_read(testcases_file,str_in);
+ slv_out <= strhex_to_slv(str_in);
+
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+
+ assert output_o = slv_out
+ report "Error!!!"
+ severity failure;
+ str_read(testcases_file,str_in);
+
+ end loop;
+
+ -------- Boundary values-----
+
+ start_i <= '0';
+ -- seeeeeeeefffffffffffffffffffffff
+ --infinity
+ wait for CLK_PERIOD; start_i <= '1';
+ opa_i <= "01111111011111111111111111111111";
+ opb_i <= "01111111011111111111111111111111";
+ fpu_op_i <= "000";
+ rmode_i <= "00";
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+ assert output_o="01111111100000000000000000000000"
+ report "Error!!!"
+ severity failure;
+
+ -- seeeeeeeefffffffffffffffffffffff
+ -- 1 x1.001 - 1x1.000 = 0x0.001
+ wait for CLK_PERIOD; start_i <= '1';
+ opa_i <= "00000000100100000000000000000000";
+ opb_i <= "10000000100000000000000000000000";
+ fpu_op_i <= "000";
+ rmode_i <= "00";
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+ assert output_o="00000000000100000000000000000000"
+ report "Error!!!"
+ severity failure;
+
+ -- seeeeeeeefffffffffffffffffffffff
+ -- 10 x 1.0001 - 10 x 1.0000 =
+ wait for CLK_PERIOD; start_i <= '1';
+ opa_i <= "00000001000010000000000000000000";
+ opb_i <= "10000001000000000000000000000000";
+ fpu_op_i <= "000";
+ rmode_i <= "00";
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+ assert output_o="00000000000100000000000000000000"
+ report "Error!!!"
+ severity failure;
+
+
+ -- seeeeeeeefffffffffffffffffffffff
+ -- -0 -0 = -0
+ wait for CLK_PERIOD; start_i <= '1';
+ opa_i <= "10000000000000000000000000000000";
+ opb_i <= "10000000000000000000000000000000";
+ fpu_op_i <= "000";
+ rmode_i <= "00";
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+ assert output_o="10000000000000000000000000000000"
+ report "Error!!!"
+ severity failure;
+
+ -- seeeeeeeefffffffffffffffffffffff
+ -- 0 + x = x
+ wait for CLK_PERIOD; start_i <= '1';
+ opa_i <= "00000000000000000000000000000000";
+ opb_i <= "01000010001000001000000000100000";
+ fpu_op_i <= "000";
+ rmode_i <= "00";
+ wait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';
+ assert output_o="01000010001000001000000000100000"
+ report "Error!!!"
+ severity failure;
+
+
+ ----------------------------------------------------------------------------------------------------------------------------------------------------
+ assert false
+ report "Success!!!.......Yahoooooooooooooo"
+ severity failure;
+
+ wait;
+
+ end process verify;
+
+end rtl;
\ No newline at end of file
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use std.textio.all;
+
+
+package txt_util is
+
+ -- prints a message to the screen
+ procedure print(text: string);
+
+ -- prints the message when active
+ -- useful for debug switches
+ procedure print(active: boolean; text: string);
+
+ -- converts std_logic into a character
+ function chr(sl: std_logic) return character;
+
+ -- converts std_logic into a string (1 to 1)
+ function str(sl: std_logic) return string;
+
+ -- converts std_logic_vector into a string (binary base)
+ function str(slv: std_logic_vector) return string;
+
+ -- converts boolean into a string
+ function str(b: boolean) return string;
+
+ -- converts an integer into a single character
+ -- (can also be used for hex conversion and other bases)
+ function chr(int: integer) return character;
+
+ -- converts integer into string using specified base
+ function str(int: integer; base: integer) return string;
+
+ -- converts integer to string, using base 10
+ function str(int: integer) return string;
+
+ -- convert std_logic_vector into a string in hex format
+ function hstr(slv: std_logic_vector) return string;
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+ -- convert a character to upper case
+ function to_upper(c: character) return character;
+
+ -- convert a character to lower case
+ function to_lower(c: character) return character;
+
+ -- convert a string to upper case
+ function to_upper(s: string) return string;
+
+ -- convert a string to lower case
+ function to_lower(s: string) return string;
+
+
+
+ -- functions to convert strings into other formats
+ --------------------------------------------------
+
+ -- converts a character into std_logic
+ function to_std_logic(c: character) return std_logic;
+
+ -- converts a string into std_logic_vector
+ function to_std_logic_vector(s: string) return std_logic_vector;
+
+ -- convert Hex string to 32-bit into std_logic_vector
+ function strhex_to_slv(s : string) return std_logic_vector;
+
+
+
+ -- file I/O
+ -----------
+
+ -- read variable length string from input file
+ procedure str_read(file in_file: TEXT;
+ res_string: out string);
+
+ -- print string to a file and start new line
+ procedure print(file out_file: TEXT;
+ new_string: in string);
+
+ -- print character to a file and start new line
+ procedure print(file out_file: TEXT;
+ char: in character);
+
+end txt_util;
+
+
+
+
+package body txt_util is
+
+
+
+
+ -- prints text to the screen
+
+ procedure print(text: string) is
+ variable msg_line: line;
+ begin
+ write(msg_line, text);
+ writeline(output, msg_line);
+ end print;
+
+
+
+
+ -- prints text to the screen when active
+
+ procedure print(active: boolean; text: string) is
+ begin
+ if active then
+ print(text);
+ end if;
+ end print;
+
+
+ -- converts std_logic into a character
+
+ function chr(sl: std_logic) return character is
+ variable c: character;
+ begin
+ case sl is
+ when 'U' => c:= 'U';
+ when 'X' => c:= 'X';
+ when '0' => c:= '0';
+ when '1' => c:= '1';
+ when 'Z' => c:= 'Z';
+ when 'W' => c:= 'W';
+ when 'L' => c:= 'L';
+ when 'H' => c:= 'H';
+ when '-' => c:= '-';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- converts std_logic into a string (1 to 1)
+
+ function str(sl: std_logic) return string is
+ variable s: string(1 to 1);
+ begin
+ s(1) := chr(sl);
+ return s;
+ end str;
+
+
+
+ -- converts std_logic_vector into a string (binary base)
+ -- (this also takes care of the fact that the range of
+ -- a string is natural while a std_logic_vector may
+ -- have an integer range)
+
+ function str(slv: std_logic_vector) return string is
+ variable result : string (1 to slv'length);
+ variable r : integer;
+ begin
+ r := 1;
+ for i in slv'range loop
+ result(r) := chr(slv(i));
+ r := r + 1;
+ end loop;
+ return result;
+ end str;
+
+
+ function str(b: boolean) return string is
+
+ begin
+ if b then
+ return "true";
+ else
+ return "false";
+ end if;
+ end str;
+
+
+ -- converts an integer into a character
+ -- for 0 to 9 the obvious mapping is used, higher
+ -- values are mapped to the characters A-Z
+ -- (this is usefull for systems with base > 10)
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function chr(int: integer) return character is
+ variable c: character;
+ begin
+ case int is
+ when 0 => c := '0';
+ when 1 => c := '1';
+ when 2 => c := '2';
+ when 3 => c := '3';
+ when 4 => c := '4';
+ when 5 => c := '5';
+ when 6 => c := '6';
+ when 7 => c := '7';
+ when 8 => c := '8';
+ when 9 => c := '9';
+ when 10 => c := 'A';
+ when 11 => c := 'B';
+ when 12 => c := 'C';
+ when 13 => c := 'D';
+ when 14 => c := 'E';
+ when 15 => c := 'F';
+ when 16 => c := 'G';
+ when 17 => c := 'H';
+ when 18 => c := 'I';
+ when 19 => c := 'J';
+ when 20 => c := 'K';
+ when 21 => c := 'L';
+ when 22 => c := 'M';
+ when 23 => c := 'N';
+ when 24 => c := 'O';
+ when 25 => c := 'P';
+ when 26 => c := 'Q';
+ when 27 => c := 'R';
+ when 28 => c := 'S';
+ when 29 => c := 'T';
+ when 30 => c := 'U';
+ when 31 => c := 'V';
+ when 32 => c := 'W';
+ when 33 => c := 'X';
+ when 34 => c := 'Y';
+ when 35 => c := 'Z';
+ when others => c := '?';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- convert integer to string using specified base
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function str(int: integer; base: integer) return string is
+
+ variable temp: string(1 to 10);
+ variable num: integer;
+ variable abs_int: integer;
+ variable len: integer := 1;
+ variable power: integer := 1;
+
+ begin
+
+ -- bug fix for negative numbers
+ abs_int := abs(int);
+
+ num := abs_int;
+
+ while num >= base loop -- Determine how many
+ len := len + 1; -- characters required
+ num := num / base; -- to represent the
+ end loop ; -- number.
+
+ for i in len downto 1 loop -- Convert the number to
+ temp(i) := chr(abs_int/power mod base); -- a string starting
+ power := power * base; -- with the right hand
+ end loop ; -- side.
+
+ -- return result and add sign if required
+ if int < 0 then
+ return '-'& temp(1 to len);
+ else
+ return temp(1 to len);
+ end if;
+
+ end str;
+
+
+ -- convert integer to string, using base 10
+ function str(int: integer) return string is
+
+ begin
+
+ return str(int, 10) ;
+
+ end str;
+
+
+
+ -- converts a std_logic_vector into a hex string.
+ function hstr(slv: std_logic_vector) return string is
+ variable hexlen: integer;
+ variable longslv : std_logic_vector(67 downto 0) := (others => '0');
+ variable hex : string(1 to 16);
+ variable fourbit : std_logic_vector(3 downto 0);
+ begin
+ hexlen := (slv'left+1)/4;
+ if (slv'left+1) mod 4 /= 0 then
+ hexlen := hexlen + 1;
+ end if;
+ longslv(slv'left downto 0) := slv;
+ for i in (hexlen -1) downto 0 loop
+ fourbit := longslv(((i*4)+3) downto (i*4));
+ case fourbit is
+ when "0000" => hex(hexlen -I) := '0';
+ when "0001" => hex(hexlen -I) := '1';
+ when "0010" => hex(hexlen -I) := '2';
+ when "0011" => hex(hexlen -I) := '3';
+ when "0100" => hex(hexlen -I) := '4';
+ when "0101" => hex(hexlen -I) := '5';
+ when "0110" => hex(hexlen -I) := '6';
+ when "0111" => hex(hexlen -I) := '7';
+ when "1000" => hex(hexlen -I) := '8';
+ when "1001" => hex(hexlen -I) := '9';
+ when "1010" => hex(hexlen -I) := 'A';
+ when "1011" => hex(hexlen -I) := 'B';
+ when "1100" => hex(hexlen -I) := 'C';
+ when "1101" => hex(hexlen -I) := 'D';
+ when "1110" => hex(hexlen -I) := 'E';
+ when "1111" => hex(hexlen -I) := 'F';
+ when "ZZZZ" => hex(hexlen -I) := 'z';
+ when "UUUU" => hex(hexlen -I) := 'u';
+ when "XXXX" => hex(hexlen -I) := 'x';
+ when others => hex(hexlen -I) := '?';
+ end case;
+ end loop;
+ return hex(1 to hexlen);
+ end hstr;
+
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+
+ -- convert a character to upper case
+
+ function to_upper(c: character) return character is
+
+ variable u: character;
+
+ begin
+
+ case c is
+ when 'a' => u := 'A';
+ when 'b' => u := 'B';
+ when 'c' => u := 'C';
+ when 'd' => u := 'D';
+ when 'e' => u := 'E';
+ when 'f' => u := 'F';
+ when 'g' => u := 'G';
+ when 'h' => u := 'H';
+ when 'i' => u := 'I';
+ when 'j' => u := 'J';
+ when 'k' => u := 'K';
+ when 'l' => u := 'L';
+ when 'm' => u := 'M';
+ when 'n' => u := 'N';
+ when 'o' => u := 'O';
+ when 'p' => u := 'P';
+ when 'q' => u := 'Q';
+ when 'r' => u := 'R';
+ when 's' => u := 'S';
+ when 't' => u := 'T';
+ when 'u' => u := 'U';
+ when 'v' => u := 'V';
+ when 'w' => u := 'W';
+ when 'x' => u := 'X';
+ when 'y' => u := 'Y';
+ when 'z' => u := 'Z';
+ when others => u := c;
+ end case;
+
+ return u;
+
+ end to_upper;
+
+
+ -- convert a character to lower case
+
+ function to_lower(c: character) return character is
+
+ variable l: character;
+
+ begin
+
+ case c is
+ when 'A' => l := 'a';
+ when 'B' => l := 'b';
+ when 'C' => l := 'c';
+ when 'D' => l := 'd';
+ when 'E' => l := 'e';
+ when 'F' => l := 'f';
+ when 'G' => l := 'g';
+ when 'H' => l := 'h';
+ when 'I' => l := 'i';
+ when 'J' => l := 'j';
+ when 'K' => l := 'k';
+ when 'L' => l := 'l';
+ when 'M' => l := 'm';
+ when 'N' => l := 'n';
+ when 'O' => l := 'o';
+ when 'P' => l := 'p';
+ when 'Q' => l := 'q';
+ when 'R' => l := 'r';
+ when 'S' => l := 's';
+ when 'T' => l := 't';
+ when 'U' => l := 'u';
+ when 'V' => l := 'v';
+ when 'W' => l := 'w';
+ when 'X' => l := 'x';
+ when 'Y' => l := 'y';
+ when 'Z' => l := 'z';
+ when others => l := c;
+ end case;
+
+ return l;
+
+ end to_lower;
+
+
+
+ -- convert a string to upper case
+
+ function to_upper(s: string) return string is
+
+ variable uppercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ uppercase(i):= to_upper(s(i));
+ end loop;
+ return uppercase;
+
+ end to_upper;
+
+
+
+ -- convert a string to lower case
+
+ function to_lower(s: string) return string is
+
+ variable lowercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ lowercase(i):= to_lower(s(i));
+ end loop;
+ return lowercase;
+
+ end to_lower;
+
+
+
+-- functions to convert strings into other types
+
+
+-- converts a character into a std_logic
+
+function to_std_logic(c: character) return std_logic is
+ variable sl: std_logic;
+ begin
+ case c is
+ when 'U' =>
+ sl := 'U';
+ when 'X' =>
+ sl := 'X';
+ when '0' =>
+ sl := '0';
+ when '1' =>
+ sl := '1';
+ when 'Z' =>
+ sl := 'Z';
+ when 'W' =>
+ sl := 'W';
+ when 'L' =>
+ sl := 'L';
+ when 'H' =>
+ sl := 'H';
+ when '-' =>
+ sl := '-';
+ when others =>
+ sl := 'X';
+ end case;
+ return sl;
+ end to_std_logic;
+
+
+-- converts a string into std_logic_vector
+
+function to_std_logic_vector(s: string) return std_logic_vector is
+ variable slv: std_logic_vector(s'high-s'low downto 0);
+ variable k: integer;
+begin
+ k := s'high-s'low;
+ for i in s'range loop
+ slv(k) := to_std_logic(s(i));
+ k := k - 1;
+ end loop;
+ return slv;
+end to_std_logic_vector;
+
+
+-- convert Hex string to 32-bit SLV
+ function strhex_to_slv(s : string) return std_logic_vector is
+ variable int : string(1 to s'length) := s;
+ variable ptr : integer range 0 to 32 := 0;
+ variable slv: std_logic_vector(31 downto 0) := (others=>'0');
+ begin
+ for i in int'reverse_range loop
+ case int(i) is
+ when '0' => slv(ptr+3 downto ptr) := "0000"; ptr := ptr+4;
+ when '1' => slv(ptr+3 downto ptr) := "0001"; ptr := ptr+4;
+ when '2' => slv(ptr+3 downto ptr) := "0010"; ptr := ptr+4;
+ when '3' => slv(ptr+3 downto ptr) := "0011"; ptr := ptr+4;
+ when '4' => slv(ptr+3 downto ptr) := "0100"; ptr := ptr+4;
+ when '5' => slv(ptr+3 downto ptr) := "0101"; ptr := ptr+4;
+ when '6' => slv(ptr+3 downto ptr) := "0110"; ptr := ptr+4;
+ when '7' => slv(ptr+3 downto ptr) := "0111"; ptr := ptr+4;
+ when '8' => slv(ptr+3 downto ptr) := "1000"; ptr := ptr+4;
+ when '9' => slv(ptr+3 downto ptr) := "1001"; ptr := ptr+4;
+ when 'a'|'A' => slv(ptr+3 downto ptr) := "1010"; ptr := ptr+4;
+ when 'b'|'B' => slv(ptr+3 downto ptr) := "1011"; ptr := ptr+4;
+ when 'c'|'C' => slv(ptr+3 downto ptr) := "1100"; ptr := ptr+4;
+ when 'd'|'D' => slv(ptr+3 downto ptr) := "1101"; ptr := ptr+4;
+ when 'e'|'E' => slv(ptr+3 downto ptr) := "1110"; ptr := ptr+4;
+ when 'f'|'F' => slv(ptr+3 downto ptr) := "1111"; ptr := ptr+4;
+ when others => null;
+ end case;
+ end loop;
+ return slv;
+ end strhex_to_slv;
+----------------
+-- file I/O --
+----------------
+
+
+
+-- read variable length string from input file
+
+procedure str_read(file in_file: TEXT;
+ res_string: out string) is
+
+ variable l: line;
+ variable c: character;
+ variable is_string: boolean;
+
+ begin
+
+ readline(in_file, l);
+ -- clear the contents of the result string
+ for i in res_string'range loop
+ res_string(i) := ' ';
+ end loop;
+ -- read all characters of the line, up to the length
+ -- of the results string
+ for i in res_string'range loop
+ read(l, c, is_string);
+ res_string(i) := c;
+ if not is_string then -- found end of line
+ exit;
+ end if;
+ end loop;
+
+end str_read;
+
+
+-- print string to a file
+procedure print(file out_file: TEXT;
+ new_string: in string) is
+
+ variable l: line;
+
+ begin
+
+ write(l, new_string);
+ writeline(out_file, l);
+
+end print;
+
+
+-- print character to a file and start new line
+procedure print(file out_file: TEXT;
+ char: in character) is
+
+ variable l: line;
+
+ begin
+
+ write(l, char);
+ writeline(out_file, l);
+
+end print;
+
+
+
+-- appends contents of a string to a file until line feed occurs
+-- (LF is considered to be the end of the string)
+
+procedure str_write(file out_file: TEXT;
+ new_string: in string) is
+ begin
+
+ for i in new_string'range loop
+ print(out_file, new_string(i));
+ if new_string(i) = LF then -- end of string
+ exit;
+ end if;
+ end loop;
+
+end str_write;
+
+
+
+
+end txt_util;
+
+
+
+