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

Subversion Repositories fir_filter

[/] [fir_filter/] [tags/] [FIR_low_area.vhd] - Rev 10

Compare with Previous | Blame | View Log

 
--  CREATION DATE .......:  02 Jul 2007 (Filtro_FIR.vhd)
--  AUTHOR ..............:  DIEGO PARDO (arroxo2@yahoo.es)
--  REVISION ............:  2.0
--  LAST UPDATE .........:  08 April 2015
--  UPDATED BY ..........:  DIEGO PARDO 
 
--  TITLE "CONFIGURABLE FIR FILTER";
--
--  Generic VHDL (suitable for ALTERA, XILINX, MICROSEMI, etc)
--  Low resources occupation (fixed-point implementation)
--
 
 
--=============================================================================
--============================= LOCAL PACKAGE =================================
--=============================================================================
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_signed.all;
USE ieee.math_real.all;     
 
 
PACKAGE fir_package IS
 
    CONSTANT max_coef: NATURAL:= 128;   -- (increase if needed)
    TYPE COEFF_ARRAY IS ARRAY (0 to max_coef-1) OF REAL;
    FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED;
 
END fir_package;
 
 
PACKAGE body fir_package IS
 
    FUNCTION decimal_to_signed (c_real: IN REAL; CONSTANT precision: IN NATURAL) RETURN SIGNED IS
    -- SIGNED = REAL / 2^(-precision) = REAL * 2^precision, with IEEE rounding
        CONSTANT RESOLUCION : REAL := "**"(2,REAL(INTEGER(precision)));
    BEGIN
        RETURN (SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND ("*"(c_real,RESOLUCION))),precision+1)));
    END FUNCTION;
 
END fir_package;
 
 
 
--=============================================================================
--================================== ENTITY ===================================
--=============================================================================
 
LIBRARY work;
USE WORK.fir_package.all;
 
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_signed.all;
USE ieee.math_real.all;     
 
--.............................................................................
-- GAIN                1.0
-- SATURATION CONTROL  Yes (output)
-- OUTPUT ROUNDING     Yes (IEEE)
-- IMPLEMENTED BY      Fixed-Point (configurable resolution)
-- 3rd-PARTY IPs       No (generic VHDL)
--.............................................................................
 
ENTITY FIR_low_area IS
    GENERIC(        
        data_length  : NATURAL     := 8;                   -- input/output length (number of bits)
        data_signed  : BOOLEAN     := false;               -- input/output type (signed or unsigned)
        improv_t     : BOOLEAN     := false;               -- minimal timing improvement by adding one extra output cycle delay (use only if needed)        
        bits_resol   : NATURAL     := 16;                  -- number of bits for the internal operations with decimals in fixed point. Recommended: bits_resol > taps. THIS SETTING IS CRITICAL FOR P&R RESULTS (MAX FREQ)
        taps         : NATURAL     := 5;                   -- =order+1, 2 coefficients as minimum (order=1)
        coefficients : COEFF_ARRAY :=(                     -- normalized coefficients bi: (bo,b1, ..., bN). They must be symmetric (but sign)
                                     -0.11735685282030676,
                                      0.23471370564061372,
                                      0.7066280917835991,
                                      0.23471370564061372,
                                     -0.11735685282030676,
                                      OTHERS=>0.0)         -- (always end with "others=>0.0")
    );
    PORT(
        areset       : IN    STD_LOGIC;                    -- active high                            
        sreset       : IN    STD_LOGIC;                    -- active high    
        clock_fs     : IN    STD_LOGIC;                              
        enable       : IN    STD_LOGIC;                                  
        xn           : IN    STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);   -- FILTER INPUT  (any fixed-point format, e.g. whole numbers)
        yn           : OUT   STD_LOGIC_VECTOR(data_length-1 DOWNTO 0)    -- FILTER OUTPUT (keeps same fixed-point format of input)
    );
END FIR_low_area;
 
 
 
ARCHITECTURE FIR_low_area_arch OF FIR_low_area IS
 
    type ENTRADA_xn IS ARRAY (taps-2 DOWNTO 0) OF SIGNED(data_length DOWNTO 0);   -- A(data_length,0) : x[n-k]
    type VALORES_h  IS ARRAY (taps-1 DOWNTO 0) OF SIGNED(bits_resol  DOWNTO 0);   -- A(0,bits_resol)  : h[n-k]
 
    SIGNAL REGISTRO_xn  : ENTRADA_xn;       
 
    SIGNAL yn_1, yn_2   : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);
    SIGNAL yn_aux       : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0);  -- yn_1 + yn_2
    SIGNAL yn_comb      : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); 
    SIGNAL yn_sync      : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); 
 
    SIGNAL yn_unsigned  : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);
    SIGNAL yn_signed    : STD_LOGIC_VECTOR(data_length-1 DOWNTO 0);  
 
    CONSTANT SIGNED_MAX : INTEGER :=      2**(yn'length-1)-1;
    CONSTANT SIGNED_MIN : INTEGER := -1 * 2**(yn'length-1);
 
 
BEGIN
 
 
    ASSERT (bits_resol >= 4) 
    REPORT "PLEASE INCREASE RESOLUTION BITS (result will be poor)" SEVERITY FAILURE;
 
	-- pragma translate_off
	process
	  VARIABLE sum_coeff : real;
	begin	  
      sum_coeff := 0.0;
      FOR ind IN 0 TO (taps-1) LOOP
        sum_coeff := sum_coeff + coefficients(ind);
      END LOOP;
      ASSERT sum_coeff = 1.0
      REPORT "COEFFICIENTS ARE NOT NORMALIZED" SEVERITY WARNING;     
	  wait;
	end process;
	-- pragma translate_on
 
 
    -- =======================================================================================
    --  HALF FILTERING OPERATIONS (1/2)  
    --  (DOES NOT INCLUDE INITIAL AND FINAL COEFFICIENTS, INCLUDES CENTRE COEFFICIENT (WHEN "taps" EVEN)
    -- =======================================================================================
 
    process1:
    PROCESS (clock_fs, areset)                          
        VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0);                            -- to sum x[n-k] with symmetric coefficients
        VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0'));                   -- it stores the coefficients (avoids registers)
        VARIABLE producto   : SIGNED (data_length+1+bits_resol+1 DOWNTO 0);               -- product of xn_a_pares by symmetric coefficient
        VARIABLE yn_aux     : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
        VARIABLE signos_bi  : STD_LOGIC_VECTOR (1 DOWNTO 0);                              -- signs of the symmetric coefficients             
        VARIABLE indice1    : NATURAL;
        VARIABLE margen     : NATURAL;
 
    BEGIN
        IF (areset = '1') THEN
            yn_1 <= (OTHERS => '0');
 
        ELSIF rising_edge(clock_fs) THEN
          IF (sreset = '1') THEN
            yn_1 <= (OTHERS => '0');
          ELSE
 
            IF (enable = '1') THEN
 
                -- variable avoids h[n] register, REGISTRO_h(0) = bN 
                FOR ind IN 0 TO (taps-1) LOOP
                    REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
                END LOOP;           
 
                yn_aux := (OTHERS => '0');
 
                -- symmetric coefficients (but first and last ones):
                -- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
                IF (taps > 3) THEN
 
                    indice1 := (taps/2)+(taps MOD 2);
                    margen  := ((taps-1)-(taps/2))/2 - (taps MOD 2);
 
                    FOR i IN indice1 TO (indice1 + margen) LOOP
 
                        -- symmetric bi signs 
                        signos_bi(1):= REGISTRO_h(i)(bits_resol);
                        signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
 
                        CASE signos_bi IS
                            WHEN "00"   => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
                            WHEN "01"   => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
                            WHEN "10"   => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
                            WHEN OTHERS => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
                        END CASE;               
 
                        producto := "*"(xn_a_pares, ABS(REGISTRO_h(i)));
                        yn_aux   := "+"(yn_aux, producto);
                    END LOOP;       
                END IF;
 
                --------------------------------------------------------------- 
                -- central coefficient operation (when taps is even)
                ---------------------------------------------------------------
                -- non-symmetric coefficient
 
                IF (taps MOD 2)/=0 THEN
                    producto := "*"(CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps/2))),data_length+2), REGISTRO_h(taps/2));                    
                    yn_aux   := "+"(yn_aux, producto);
                END IF; 
 
                --------------------------------------------------------------- 
                -- output of processo1
                ---------------------------------------------------------------
                -- yn_1 has decimal part (bits_resol bits)
 
                yn_1 <= yn_aux;        
 
            END IF;     
          END IF;
        END IF;         
    END PROCESS process1;
 
 
    -- =======================================================================================
    --  HALF FILTERING OPERATIONS (2/2)  
    --  (INCLUDINF INITIAL AND FINAL COEFFICIENTS)
    -- =======================================================================================
 
    process2:
    PROCESS (clock_fs, areset)                         
        VARIABLE xn_a_pares : SIGNED (data_length+1 DOWNTO 0);                            -- to sum x[n-k] with symmetric coefficients
        VARIABLE REGISTRO_h : VALORES_h := (OTHERS => (OTHERS => '0'));                   -- it stores the coefficients (avoids registers)
        VARIABLE producto   : SIGNED (data_length+1+bits_resol+1 DOWNTO 0);               -- product of xn_a_pares by symmetric coefficient
        VARIABLE yn_aux     : SIGNED (data_length+1+bits_resol+1+(taps-2) DOWNTO 0); -- partial sum
        VARIABLE signos_bi  : STD_LOGIC_VECTOR (1 DOWNTO 0);                              -- signs of the symmetric coefficients
        VARIABLE indice1    : NATURAL;
        VARIABLE margen     : NATURAL;
 
    BEGIN
        IF (areset = '1') THEN
            yn_2 <= (OTHERS => '0');
 
        ELSIF rising_edge(clock_fs) THEN
          IF (sreset = '1') THEN
            yn_2 <= (OTHERS => '0');
          ELSE
 
            IF (enable = '1') THEN
 
                -- variable avoids h[n] register, REGISTRO_h(0) = bN   
                FOR ind IN 0 TO (taps-1) LOOP
                    REGISTRO_h(ind) := decimal_to_signed (coefficients(taps-1-ind),bits_resol);
                END LOOP;           
 
 
                yn_aux := (OTHERS => '0');
 
                -- symmetric coefficients (but first and last ones). When taps < 7 the operations are resolved by process1:
                -- In this cycle x[n-k] has not been applied yet to the shift register of x[n]
                IF (taps > 6) THEN
 
                    indice1 := (taps/2)+(taps MOD 2);
                    margen  := ((taps-1)-(taps/2))/2 - (taps MOD 2);
 
                    FOR i IN (indice1 + margen + 1) TO (taps-2) LOOP
 
                        -- symmetric bi signs 
                        signos_bi(1):= REGISTRO_h(i)(bits_resol);
                        signos_bi(0):= REGISTRO_h(taps-1-i)(bits_resol);
 
                        CASE signos_bi IS                           
                            WHEN "00"   => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));                          
                            WHEN "01"   => xn_a_pares:= "+"( CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));                          
                            WHEN "10"   => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));                      
                            WHEN OTHERS => xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(signed(REGISTRO_xn(i))),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(taps-1-i))),data_length+2));
                        END CASE;           
 
                        producto:= "*"(xn_a_pares, ABS(REGISTRO_h(i)));
                        yn_aux  := "+"(yn_aux, producto);
                    END LOOP;       
                END IF;
 
                ----------------------------------------------------------------                                                
                -- first and last coefficients operation (symmetric)
                ----------------------------------------------------------------               
                -- The initial coefficient multiplies x[n] (not registered yet)             
 
                signos_bi(1):= REGISTRO_h(taps-1)(bits_resol);
                signos_bi(0):= REGISTRO_h(0)(bits_resol);
 
                CASE signos_bi IS
 
                    WHEN "00"   => if (data_signed = true) then
                                     xn_a_pares:= "+"( CONV_SIGNED(conv_integer(  signed(xn)),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));                                
                                   else
                                     xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
                                   end if;
                    WHEN "01"   => if (data_signed = true) then
                                     xn_a_pares:= "+"( CONV_SIGNED(conv_integer(  signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));                                
                                   else
                                     xn_a_pares:= "+"( CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
                                   end if;    
                    WHEN "10"   => if (data_signed = true) then
                                     xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(  signed(xn)),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));                                
                                   else
                                     xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2),  CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
                                   end if;
                    WHEN OTHERS => if (data_signed = true) then
                                     xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(  signed(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));                                
                                   else
                                     xn_a_pares:= "+"(-CONV_SIGNED(conv_integer(unsigned(xn)),data_length+2), -CONV_SIGNED(conv_integer(signed(REGISTRO_xn(0))),data_length+2));
                                   end if;
                END CASE;                                   
 
                producto := "*"(xn_a_pares, ABS(REGISTRO_h(taps-1)));
                yn_aux   := "+"(yn_aux, producto);        
 
                --------------------------------------------------------------- 
                -- output of processo2
                ---------------------------------------------------------------             
                -- yn_2 has decimal part (bits_resol bits)
 
                yn_2 <= yn_aux;                     
 
            END IF;     
          END IF;
        END IF;         
    END PROCESS process2;
 
 
    -- =======================================================================================
    --  SHIT REGISTER: x[n-k]
    -- =======================================================================================
 
    process_reg:
    PROCESS (clock_fs, areset)  
    BEGIN   
        IF (areset = '1') THEN
            REGISTRO_xn <= (OTHERS => (OTHERS => '0'));
 
        ELSIF rising_edge(clock_fs) THEN
          IF (sreset = '1') THEN
            REGISTRO_xn <= (OTHERS => (OTHERS => '0'));         
          ELSE
 
            IF (enable = '1')THEN
 
                ---------------------------------------------------------------
                -- x[n-k], it is not applied instantaneously (scheduled)  
                ---------------------------------------------------------------             
                -- right-shift
 
                FOR i IN 0 TO (taps-3) LOOP        -- (ignored when taps=2)
                    REGISTRO_xn(i)<= REGISTRO_xn(i+1);
                END LOOP;
 
                if (data_signed = true) then
                  REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer(  signed(xn)),data_length+1); 
                else
                  REGISTRO_xn(taps-2) <= CONV_SIGNED(conv_integer(unsigned(xn)),data_length+1);
                end if;
 
            END IF;
          END IF;
        END IF;
 
    END PROCESS process_reg;
 
 
    -- =======================================================================================
    --  OUTPUT (neither saturation control nor IEEE rounding)
    -- =======================================================================================
    -- SUM of process1 and process2 outputs
 
    yn_comb <= yn_1 + yn_2;     
    yn_sync <= yn_1 + yn_2 when rising_edge(clock_fs);
 
    yn_aux  <= yn_sync when (improv_t = true) else yn_comb;
 
 
    --------------------------------------------------------------- 
    -- OUTPUT (with saturation control and IEEE rounding)
    ---------------------------------------------------------------
 
    -- yn_aux of type A(_,bits_resol): 
    --                  whole part:   'LEFT downto bits_resol 
    --                  decimal part: (bits_resol-1) downto 0           
    --
    --                 |<------------------------------------------ yn_aux ------------------------------------------->|
    --                  [yn_aux'left] ..... [bits_resol+data_length-1] ..... [bits_resol]   [bits_resol-1] .........[0]
    --                                     |<------------ yn_signed/unsigned ------------>|<----- (decimal part) ----->|
 
 
    -- unsigned output:
    yn_unsigned <=  
      (OTHERS => '0') WHEN yn_aux(bits_resol+data_length+1) = '1'                                                                                                                                          ELSE -- negative overflow 
      (OTHERS => '1') WHEN yn_aux(bits_resol+data_length)   = '1'                                                                                                                                          ELSE -- positive overflow                                                                          
      STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))+1 WHEN yn_aux(bits_resol-1) = '1' and STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 downto bits_resol)) /= (yn'range => '1') ELSE -- positive IEEE rounding (avoids positive overflow)
      STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol));                                                                                                                                     -- truncated
 
    -- signed output:
    yn_signed   <=  
      STD_LOGIC_VECTOR(CONV_SIGNED(SIGNED_MIN,data_length)) WHEN yn_aux(bits_resol+data_length) = '1' and yn_aux(bits_resol+data_length-1) = '0'                                              ELSE -- negative overflow 
      STD_LOGIC_VECTOR(CONV_SIGNED(SIGNED_MAX,data_length)) WHEN yn_aux(bits_resol+data_length) = '0' and yn_aux(bits_resol+data_length-1) = '1'                                              ELSE -- positive overflow
      STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol))+1 WHEN yn_aux(bits_resol-1) = '1' and                                                                                   -- positive or negative IEEE rounding (avoids positive overflow)
        (yn_aux(bits_resol+data_length-1) = '1' or STD_LOGIC_VECTOR(yn_aux(bits_resol+data_length-2 downto bits_resol)) /= (yn_aux(bits_resol+data_length-2 downto bits_resol)'range => '1')) ELSE    
      STD_LOGIC_VECTOR(signed(yn_aux(bits_resol+data_length-1 DOWNTO bits_resol)));                                                                                                                -- truncated
 
    -- FINAL OUTPUT
    yn <= yn_signed when (data_signed = true) else yn_unsigned;
 
 
END FIR_low_area_arch;
 
 
 
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
-------------------------------------------------------------------------------
--                                DESCRIPTION 
-------------------------------------------------------------------------------
--          
------------------
-- DELAY
------------------
--  clock_fs period x taps
--
------------------
-- AREA
------------------
--  bits_resol  stablishes the precision of the filtering operations (resources)
--
------------------
-- OUTPUT ERROR
------------------
--  maximum output error: 
-- 
--             ------------------------------------------------------
--            | taps * [2^(-bits_resol)] * [(2^data_length)-1)] |
--             ------------------------------------------------------
-- (taps = order+1)
--
------------------------------------------------------------------------------
-- Operations:
------------------------------------------------------------------------------
--
--          h[n] = A(0,bits_resol) with resolution = 2^(-bits_resol)
--          x[n] = A(data_length,0)
--
--  y[n] = sum{x[n-k] x h[k]}
--          x[n-i] x h[i] = A(data_length,0) x A(0,bits_resol) = A(data_length+0+1,bits_resol)
--          y[n] = A(data_length+1+[taps]-1,bits_resol) 
--
------------------------------------------------------------------------------
-- Implementation:
------------------------------------------------------------------------------
--
--  -FIR direct form II-
--
--  3 process() in parallel:
--
--    process1():    1/2 part of the filtering operations
--    process2():    2/2 part of the filtering operations
--    process_reg(): x[n-k]
--
--  FIR filters have symmetric coefficients (but sign):
--
--  e.g. taps=5 and positive h[n] coefficients: 
--      x[n-3]*h(3) + x[n-1]*h[1] = (x[n-3]+x[n-1])*h[3], because h[1]=h[3]
--
---------------
-- 
--  x: products by means of process1() and centre coefficient
--  o: products by means of process2() and first-last coefficients
--
--
--   taps  bi                              prod process1()               prod process2()
--
--      2       x x                             0                             1   bo=b1
--      3       o x o                           1   b1                        1   bo=b2
--      4       o x x o                         1   b1=b2                     1   bo=b3       
--      5       o x x x o                       2   b1=b3, b2                 1   bo=b4       
--      6       o x x x x o                     2   b1=b4, b2=b3              1   bo=b5           
--      7       o o x x x o o                   2   b2=b4, b3                 2   bo=b6,  b1=b5 
--      8       o o x x x x o o                 2   b2=b5, b3=b4              2   bo=b7,  b1=b6
--      9       o o x x x x x o o               3   b2=b6, b3=b5, b4          2   bo=b8,  b1=b7
--      10      o o x x x x x x o o             3   b2=b7, b3=b6, b4=b5       2   bo=b9,  b1=b8
--      11      o o o x x x x x o o o           3   b3=b7, b4=b6, b5          3   bo=b10, b1=b9,  b2=b8
--      12      o o o x x x x x x o o o         3   b3=b8, b4=b7, b5=b6       3   bo=b11, b1=b10, b2=b9
--      13      o o o x x x x x x x o o o       4   b3=b9, b4=b8, b5=b7, b6   3   bo=b12, b1=b11, b2=b10
--      14      o o o o x x x x x x o o o o     4   b4=b9, b5=b8, b6=b7       4   bo=b13, b1=b12, b2=b11, b3=b10
--      15      o o o o x x x x x x x o o o o   4   b4=b10,b5=b9, b6=b8, b7   4   bo=b14, b1=b13, b2=b12, b3=b11
--     (etc)...
 
-------------------------------------------------------------------------------
-- Fixed-Point Arithmetic: An Introduction
--   Randy Yates
--   March 3, 2001 11:52
-------------------------------------------------------------------------------
--
-- A(a,b):  a = whole part, b = decimal part
--  
--          length             = (a+b) +1 bits (sign)
--          resolution (steps) =  2^(-b)
--          maximum value      =  2^a - 2^(-b)
--          minimum value      = -2^(-a)
--
-- Operations:
--
--          A(x,y) * A(z,n)         =   A(x+z+1,y+n), length = (x+z+1+y+n) +1 bits (sign)
--          A(x,y) + A(x,y)         =   A(x+1,y)    , length = (x+1+y) +1 bits (sign)
--          A(x,y) + A(x,y) + A(x,y)=   A(x+2,y)    , length = (x+2+y) +1 bits (sign)
-- 
 
------------------------------------------------------------------------------          
--                 TYPES CONVERSION (OF CONSTANT VALUES)
------------------------------------------------------------------------------
--
--      REAL -> INTEGER -> STD_LOGIC_VECTOR -> SIGNED:
--
--          SIGNED(CONV_STD_LOGIC_VECTOR(INTEGER(ROUND(<real_value>))))
--
--      SIGNED -> STD_LOGIC_VECTOR -> INTEGER -> REAL:
--
--          ROUND(REAL(CONV_INTEGER(CONV_STD_LOGIC_VECTOR(<signed_value>))))
--
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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