VHDL de desplazamiento lineal combinacional

1

Estoy diseñando un sumador / multiplicador segmentado y sintetizable de punto flotante de 32 bits como parte de un grupo para una clase en la escuela. Me pusieron a cargo de la re-normalización. Parte de esto es la izquierda o la derecha desplazando un bus 48 que representa la salida de la mantisa. El código que tengo hasta ahora es este

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;

El código anterior verifica que la mantisa ingresada esté en el formulario 01.xxxxxxxxx ... (de 47 a 0) antes de configurarlo en la salida. Si no es así, cambia la mantisa respectivamente y agrega o resta al exponente de cada cambio. Para un cambio a la derecha, esto es trivial, pero para el desplazamiento a la izquierda un número N de veces no sé cómo implementarlo de manera combinada como parte de una etapa de oleoducto. Realmente estoy perdido, si lo estuviera haciendo problemáticamente, continuaría moviéndome a la izquierda y revisando los dos primeros bits de la mantisa después de cada turno, pero no creo que esto sea posible sintetizarlo. ¿Podría alguien darme un punto en la dirección correcta y alguna orientación para resolver este problema?

    
pregunta jackana3

1 respuesta

2

Aquí realmente tienes tres piezas de lógica, un codificador de prioridad que emite la posición del '1' más a la izquierda y un desplazador y un sumador.

Parece un bucle for para el codificador de prioridad, podría hacerlo con sentencias if anidadas, pero un bucle for es probablemente más limpio.

Idea completamente no probada:

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);

También puede encontrar útil el hecho de que ieee.numeric_std tenga definidos los operadores shift_left y shift_right, o incluso el hecho de que sla, sra, sll, srl están definidos para std_logic_vector.

Por lo general, escribo turnos con concatenación, pero debes hacer un poco de cuidado con las cantidades firmadas al hacer esto si quieres que la extensión del signo sea correcta, solo una preferencia personal.

    
respondido por el Dan Mills

Lea otras preguntas en las etiquetas