1
\$\begingroup\$

I am designing a 32 bit floating point pipelined and synthesizable adder/multiplier as part of group for a class in school. I was put in charge of the re-normalization. Part of this is left or right shifting a 48 bus which represents the mantissa output. The code that I have so far is this

library ieee;
use ieee.std_logic_1164.all;
USE ieee.numeric_std.ALL;

entity renormalizer is
    PORT(
        enableIN : in std_logic;
        signIN : in std_logic;
        exponentIN : in std_logic_vector(7 downto 0);
        mantissaIN : in std_logic_vector(47 downto 0);
        zOUT : out std_logic_vector(31 downto 0)
    );
end renormalizer;

architecture behave of renormalizer IS
begin
    process(enableIN,signIN,exponentIN,mantissaIN)
    variable mantissaHEAD : std_logic_vector(1 downto 0);
    variable exponentNORM : std_logic_vector(7 downto 0);
    variable exponentONE : std_logic_vector(7 downto 0) := "00000001";
    variable exponentNEGONE : std_logic_vector(7 downto 0) := "11111110";
    variable exponentCARRY : std_logic_vector(7 downto 0);
    begin
    mantissaHEAD := mantissaIN(47 downto 46); --First bits of mantissa
    case enableIN is
        when '0' => 
            --Pass things through
            zOUT <= signIN & exponentIN & mantissaIN(45 downto 23);
        when '1' => 
            --Do the normalization
            case mantissaHEAD is
                --DONT KNOW HOW TO IMPLEMENT THIS
                when "00" => 
                    zOUT <= (others => 'Z')
                ;
                --NUMBER IS RENORMALIZED PASS IT THROUGH
                when "01" => 
                    zOUT <= signIN & exponentIN & mantissaIN(45 downto 23)
                ;
                --THESE BOTTOM TWO DO THE SAME THING
                when "10" => 
                    --SUBTRACT ONE FROM THE EXPONENT AND OUTPUT SHIFTED MANTISSA 
                    exponentNORM(0) := exponentIN(0) xor exponentNEGONE(0) xor '1';
                    exponentCARRY(0) := (exponentIN(0) and exponentNEGONE(0)) or ('1' and (exponentIN(0) xor exponentNEGONE(0)));
                    for i in 1 to 7 loop
                        exponentNORM(i) := exponentIN(i) xor exponentNEGONE(i) xor exponentCARRY(i-1);
                        exponentCARRY(i) := (exponentIN(i) and exponentNEGONE(i)) or (exponentCARRY(i-1) and (exponentIN(i) xor exponentNEGONE(i)));
                    end loop;
                    zOUT <= signIN & exponentNORM & mantissaIN(46 downto 24); --46 downto 24 instead of 45 downto 23
                when "11" => 
                    exponentNORM(0) := exponentIN(0) xor exponentNEGONE(0) xor '1';
                    exponentCARRY(0) := (exponentIN(0) and exponentNEGONE(0)) or ('1' and (exponentIN(0) xor exponentNEGONE(0)));
                    for i in 1 to 7 loop
                        exponentNORM(i) := exponentIN(i) xor exponentNEGONE(i) xor exponentCARRY(i-1);
                        exponentCARRY(i) := (exponentIN(i) and exponentNEGONE(i)) or (exponentCARRY(i-1) and (exponentIN(i) xor exponentNEGONE(i)));
                    end loop;
                    zOUT <= signIN & exponentNORM & mantissaIN(46 downto 24);
                when others => zOUT <= (others => 'Z'); 
            end case;

        when others =>  zOUT <= (others => 'Z');
    end case;
    end process;
end behave;

The above code checks that the inputted mantissa is in the form 01.xxxxxxxxx... (47 downto 0) before setting it to the output. If it is not, it shifts the mantissa respectively and adds or subtracts to the exponent for each shift.. For one shift right this is trivial but for shifting left an N number of times I don't know how to implement it combinationally as part of a pipeline stage. I really am lost, if I was doing it problematically I would continue shifting left and check the first two bits of the mantissa after each shift but I don't think this is possible to synthesize this. Could someone give me a point in the right direction and some guidance with solving this problem.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You really have three pieces of logic here, a priority encoder outputting the position of the leftmost '1' and a shifter and an adder.

Looks like a for loop for the priority encoder, could do it with nested if statements, but a for loop is probably cleaner.

Completely untested idea:

std_logic_vector m (47 downto 0); -- mantissa
std_logic_vector z (47 downto 0) := (others => '0'); -- a load of zeros
integer s range -2 to 45 := 6; -- Or whatever your priority encoder logic gets you, this is the amount to shift
-- left shift, only good if shift > 0
m <= m(47-s downto 0) & z(s -1 downto 0);

You might also find the fact that ieee.numeric_std has shift_left and shift_right operators defined useful, or even the fact that sla,sra,sll,srl are defined for std_logic_vector.

Personally I usually write shifts with concatenation, but you have to be a little careful with signed quantities when doing this if you want the sign extension to be correct, just personal preference.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.