# Multiplicador 8 bits signo complemento a 2 VHDL



## soundstream32 (Mar 28, 2013)

saludos vengo a pedir su ayuda ya que tengo que realizar en vhdl un multiplicador 8 x 8 pero de números con signo en complemento a2 mediante el algoritmo de sumas y desplazamientos, ya tengo realizado el código para multiplicar números sin signo.La cuestión es que se que solo tengo que modificarle algo al código pero no se que es, ya estuve leyendo sobre este asunto de la multiplicación en complemento a2 y estuve viendo los distintos algoritmos que existen pero no entiendo que cambiar en mi código o no e encontrado el algoritmo que me de a entender que cambiar al código. si me pudieran ayudar un poco se los agradecería, al menos si me pudieran dar información del algoritmo que tengo que utilizar, les adjunto el código para que vean que es lo que estoy haciendo, como comentario no puedo utilizar estandard logic, lo que utilizo en el código solo es para hacer el barrido a los displays de la tarjeta solo en eso  lo puedo utilizar. 


```
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
entity Mult4x4 is
    port(
            clk : in bit;
            rst : in bit;
            enter : in bit;
            sw : in bit_vector(7 downto 0);
            rdy : out bit;
            prod : out bit_vector(15 downto 0);
            seg : out std_logic_vector(6 downto 0);
            an : out std_logic_vector (3 downto 0);
            dp: out std_logic
            );
end Mult4x4;

architecture arq_Mult4x4 of Mult4x4 is
    -- Señales para el control
    type estados is(IDLE, S1, MULT);
    signal ep : estados := IDLE;
    -- Señales para el procesamiento (data path)
    signal mndo, mdor : bit_vector(7 downto 0) := "00000000"; -- Multiplicando y multiplicador
    signal ac : bit_vector(16 downto 0) := (others =>'0'); -- Acumulador
    signal cnt : bit_vector(2 downto 0) := "000"; -- Contador
    signal suma : bit_vector(8 downto 0);
    signal mux : bit_vector(7 downto 0);
        ---señales utiles para el circuito Y/Decodificador/Multiplexor
    signal LED1,LED2,LED3,LED4: std_logic_vector(6 downto 0);
    constant t_1ms: integer := 50000;
    signal delay_1ms: integer range 0 to t_1ms;
    
    -----------------------------------------------
    -- Funciones
    function add( X, Y : bit_vector) return bit_vector is
        variable q : bit_vector(X'range);
        variable c : bit_vector((X'HIGH+1) downto 0);    
    begin
        c(0) := '0';
        for i in X'reverse_range loop -- Voy de 0 al top de X con "reverse_range"
              q(i) := X(i) xor Y(i) xor c(i);
            c(i+1) := (X(i) and Y(i)) or
                         (Y(i) and c(i)) or
                         (c(i) and X(i));
        end loop;
        return q;
    end function add;
    -- Señales para la salida
    signal x, y : bit_vector(8 downto 0);
begin
    
    -- Unidad de control
    Uctrl:
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                ep <= IDLE;
            else
                case ep is
                    when IDLE =>    if(enter = '1') then
                                            ep <= S1;
                                        else
                                            ep <= IDLE;
                                        end if;
                    when S1     =>    if(enter = '0') then
                                            ep <= MULT;
                                        else
                                            ep <= S1;
                                        end if;
                    when MULT =>    if(cnt = "111") then
                                            ep <= IDLE;
                                        else
                                            ep <= MULT;
                                        end if;
                end case;
            end if;
        end if;
    end process Uctrl;
    
    -- Unidad de procesamiento (data path)
    Regmndo: -- Registro multiplicando
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                mndo <= "00000000";
            elsif(enter = '1' and ep = IDLE) then
                mndo <= sw;
            end if;
        end if;
    end process Regmndo;
    
    Regmdor: -- Registro mutliplicador
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                mdor <= "00000000";
            elsif(enter = '0' and ep = S1) then
                mdor <= sw;
            elsif(ep = MULT) then
                mdor <= '0' & mdor(7 downto 1); -- Corrimiento a la derecha
            end if;
        end if;
    end process Regmdor;
    
    Regcnt: -- Registro del contador
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                cnt <= "000";
            elsif(enter = '1' and ep = IDLE) then
                cnt <= "000";
            elsif(ep = MULT) then
                cnt(0) <= not(cnt(0));     -- Hacemos un pequeño contador. Primera cifra se niega cada pulso
                if (cnt(0) = '1') then    --    Segunda cifra se niega cada que la primera es '1'.
                    cnt(1) <= not(cnt(1));
                else
                    cnt(1) <= cnt(1);
                    end if;
                if(cnt(0)='1' and cnt(1)='1') then
                cnt(2)<= not(cnt(2));
                else
                cnt(2)<= cnt(2);
                end if;
                                        -- Termina contador de 0 a 7.
            end if;
        end if;
    end process Regcnt;
    
    Regacum: -- Registro del acumulador
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                ac <= (others => '0');
            elsif(ep = IDLE and enter = '1') then
                ac <= (others => '0');
            elsif(ep = MULT) then
                ac(7 downto 0) <= ac(8 downto 1); -- Corrimiento del RHS del acumulador
                ac(16 downto 8) <= suma; -- Suma de producto parcial
            end if;
        end if;
    end process Regacum;
    
    RegRdy: -- Registro de bandera de ready
    process(clk)
    begin
        if(clk'event and clk = '1') then
            if(rst = '1') then
                Rdy <= '0';
            elsif(ep = IDLE and enter = '1') then
                Rdy <= '0';
            elsif(ep = MULT and cnt = "111") then
                Rdy <= '1';
            end if;
        end if;
    end process RegRdy;
    
    x <= '0' & ac(16 downto 9);
    y <= '0' & mux;
    
    suma <= add(x,y);
    mux <= mndo when mdor(0) = '1' else "00000000";
    
    prod <= ac(16 downto 1); -- Salida.
    -------------------------------
--circuito y (codificador)
--HEX-to-seven-segment decoder
-- segment encoinputg
--      0
--     ---  
--  5 |   | 1
--     ---   <- 6
--  4 |   | 2
--     ---
--      3
    with ac(4 downto 1) SELect
   LED1<= "1111001" when "0001",   --1
         "0100100" when "0010",   --2
         "0110000" when "0011",   --3
         "0011001" when "0100",   --4
         "0010010" when "0101",   --5
         "0000010" when "0110",   --6
         "1111000" when "0111",   --7
         "0000000" when "1000",   --8
         "0010000" when "1001",   --9
         "0001000" when "1010",   --A
         "0000011" when "1011",   --b
         "1000110" when "1100",   --C
         "0100001" when "1101",   --d
         "0000110" when "1110",   --E
         "0001110" when "1111",   --F
         "1000000" when others;   --0
 
    with ac(8 downto 5) SELect
   LED2<= "1111001" when "0001",   --1
         "0100100" when "0010",   --2
         "0110000" when "0011",   --3
         "0011001" when "0100",   --4
         "0010010" when "0101",   --5
         "0000010" when "0110",   --6
         "1111000" when "0111",   --7
         "0000000" when "1000",   --8
         "0010000" when "1001",   --9
         "0001000" when "1010",   --A
         "0000011" when "1011",   --b
         "1000110" when "1100",   --C
         "0100001" when "1101",   --d
         "0000110" when "1110",   --E
         "0001110" when "1111",   --F
         "1000000" when others;   --0

    with ac(12 downto 9) SELect
   LED3<= "1111001" when "0001",   --1
         "0100100" when "0010",   --2
         "0110000" when "0011",   --3
         "0011001" when "0100",   --4
         "0010010" when "0101",   --5
         "0000010" when "0110",   --6
         "1111000" when "0111",   --7
         "0000000" when "1000",   --8
         "0010000" when "1001",   --9
         "0001000" when "1010",   --A
         "0000011" when "1011",   --b
         "1000110" when "1100",   --C
         "0100001" when "1101",   --d
         "0000110" when "1110",   --E
         "0001110" when "1111",   --F
         "1000000" when others;   --0

   with ac(16 downto 13) SELect
   LED4<= "1111001" when "0001",   --1
         "0100100" when "0010",   --2
         "0110000" when "0011",   --3
         "0011001" when "0100",   --4
         "0010010" when "0101",   --5
         "0000010" when "0110",   --6
         "1111000" when "0111",   --7
         "0000000" when "1000",   --8
         "0010000" when "1001",   --9
         "0001000" when "1010",   --A
         "0000011" when "1011",   --b
         "1000110" when "1100",   --C
         "0100001" when "1101",   --d
         "0000110" when "1110",   --E
         "0001110" when "1111",   --F
         "1000000" when others;   --0
----------------------------------------
--circuito multiplexor/contador
    process(clk)
    begin
        if(clk'event and clk='1') then
            delay_1ms<= delay_1ms +1;
            if(delay_1ms <t_1ms/4) then
                seg <= LED1;
                an<= "1110";
            elsif(t_1ms/4<=delay_1ms and delay_1ms<t_1ms/2) then
                seg <= LED2;
                an <= "1101";
            elsif(t_1ms/2<=delay_1ms and delay_1ms<t_1ms*3/4) then
                seg <= LED3;
                an <= "1011";
            elsif(t_1ms*3/4<=delay_1ms and delay_1ms<t_1ms) then
                seg <= LED4;
                an <= "0111";            
            end if;
        end if;
    end process;
-------------------
dp <='1';    
-----    
end arq_Mult4x4;
```


saludos y de antemano muchas gracias.


----------



## chclau (Mar 30, 2013)

Aca la wiki te lo explica

http://en.wikipedia.org/wiki/Booth's_multiplication_algorithm


----------



## MrCarlos (Mar 30, 2013)

Hola soundstream32

Ha pasado algo de tiempo y creo que ya estás avanzado en tu proyecto. Sin embargo indaga en Google.com por esta frase: Algoritmo Multiplicador con signo VHDL

Espero esto también te sirva:
Según sabemos se requiere un BIT extra en cada operando el cual determinará si el número es positivo o negativo.
Si los signos, del multiplicando y el multiplicador, son diferentes el resultado será negativo.
Si los signos, del multiplicando y el multiplicador, son iguales el resultado será positivo.

saludos
a sus ordenes


----------



## soundstream32 (Mar 31, 2013)

ya lo termine gracias a todos por su ayuda


----------



## edpb (Abr 1, 2013)

Hola, tengo que entregar el mismo proyecto final y mi lap se quedo sin espacio para instalar Xilinx 13.3 para bajarlo a una Nexys 3, no hay posibilidad de que pases el codigo terminado, para que en mi escuela, lo sintetize y lo  pueda entregar??? 

Gracias por el apoyo...


----------

