VHDL NxM -bit multiplicador de bloque paralelo

0

Estoy tratando de crear esquemas para un multiplicador de bloque paralelo de NxM-bit usando parámetros genéricos para definir el tamaño del multiplicador y generar sentencias para describir la estructura interna. Tengo algunos problemas con mis sumas y gastos de transporte y no puedo implementar lo que quiero hacer en el código VHDL.

Esto es lo que obtuve hasta ahora:

Multiplicador de 1 bit:

library IEEE;  
use IEEE.std_logic_1164.all;  
use IEEE.std_logic_arith.all;  
use ieee.numeric_std.all;  
use ieee.std_logic_unsigned.all;

entity mult is  
 port (  
  a     :  in std_logic;  
  b     :  in std_logic;  
  Sin   :  in std_logic;        --sum-in  
  Cin   :  in std_logic;        --carry-in  
  Sout  :  out std_logic;       --sum-out  
  Cout  :  out std_logic        --carry-out  
);  
end mult;  

architecture mult of mult is  
  begin  

Sout <= '1' when a = '0' and b = '0' and Sin = '0' and Cin = '1' else
        '1' when a = '0' and b = '0' and Sin = '1' and Cin = '0' else
        '1' when a = '0' and b = '1' and Sin = '1' and Cin = '0' else
        '1' when a = '0' and b = '1' and Sin = '0' and Cin = '1' else
        '1' when a = '1' and b = '0' and Sin = '0' and Cin = '1' else
        '1' when a = '1' and b = '0' and Sin = '1' and Cin = '0' else
        '1' when a = '1' and b = '1' and Sin = '0' and Cin = '0' else
        '1' when a = '1' and b = '1' and Sin = '1' and Cin = '1' else
        '0';
Cout <= '1' when a = '0' and b = '0' and Sin = '1' and Cin = '1' else
        '1' when a = '0' and b = '1' and Sin = '1' and Cin = '1' else
        '1' when a = '1' and b = '0' and Sin = '1' and Cin = '1' else
        '1' when a = '1' and b = '1' and Sin = '0' and Cin = '1' else
        '1' when a = '1' and b = '1' and Sin = '1' and Cin = '0' else
        '1' when a = '1' and b = '1' and Sin = '1' and Cin = '1' else
        '0';

end mult;

Lo usé como un componente en un multiplicador NxM:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

entity generic_mult is
        generic (bits: integer);
 port (
  a     :  in std_logic_vector(bits-1 downto 0);
  b     :  in std_logic_vector(bits-1 downto 0);
  answer:  out std_logic_vector(bits*2-1 downto 0)      --sum-out
  );
end entity generic_mult;

architecture behavioral of generic_mult is

 component mult is
  port (
    a    :  in std_logic;
    b    :  in std_logic;
    Sin  :  in std_logic;       --sum-in
    Cin  :  in std_logic;       --carry-in
    Sout :  out std_logic;      --sum-out
    Cout :  out std_logic       --carry-out
  );
 end component;

        type mem_word  is array (0 to bits) of std_logic_vector(bits downto 0);

        signal  carry_internal : mem_word;
        signal  sum_internal : mem_word;

  begin
    this_is_label: for N in 1 to bits generate --Im sorry, my labels are horrible :(
        this_is_label3: for M in 0 to bits-1 generate

            this_is_label2: mult
          port map (
            a => a(N-1),
            b => b(M),
            Cin => carry_internal(M)(N),
            Cout => carry_internal(M+1)(N),
            Sin => sum_internal(M)(N),
            Sout => sum_internal(M+1)(N-1)
        );
    end generate;
end generate;
    labellll: for N in 0 to bits-1 generate
        sum_internal(N+1)(N) <= carry_internal(N)(N);
    carry_internal(0) <= (others => '0');
    sum_internal(0)   <= (others => '0');

    answer(bits*2-1) <= carry_internal(bits)(bits);
    answer(bits downto 0) <= sum_internal(bits);
    end generate;
end behavioral;

Y un banco de pruebas para ello:

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

entity NM_mult_tb is
end NM_mult_tb;

architecture behavioral of NM_mult_tb is
    component generic_mult

        generic (bits: integer := 4);
 port (
  a     :  in std_logic_vector(bits-1 downto 0);
  b     :  in std_logic_vector(bits-1 downto 0);
  answer:  out std_logic_vector(bits*2-1 downto 0)      --sum-out
  );
    end component;
   --declaring inputs and initializing them
        signal a  :  std_logic_vector(3 downto 0) :="0101";
        signal b  :  std_logic_vector(3 downto 0) :="1010";
        signal Sin:  std_logic_vector(3 downto 0) :="0000";
        signal Cin:  std_logic := '0';
   --declaring outputs and initializing them
        signal answer :  std_logic_vector(7 downto 0);  --sum-out
        signal correct:  std_logic;                     --carry-out

BEGIN
    -- Instantiating the Design Under Test (DUT)
   dut: generic_mult
        GENERIC MAP (4)
        PORT MAP (
          a => a,
          b => b,
         answer => answer
        );

   -- Stimulus process
    correct <= '1' when to_integer(unsigned(a))*to_integer(unsigned(b)) = 
to_integer(unsigned(answer)) else '0';
  stim_proc: process
   begin
        wait for 1 ns;
        a <= a + 1;
        if a = "0" then b <= b + 1; end if;
  end process;

END;

Cuando lo simulo, veo que hay algo mal con los acarreos y sumas y salidas y mi respuesta tiene bits indefinidos:

(No se me permiten imágenes incrustadas en esta publicación antes de tener 10 reputación, por lo que aquí hay un enlace a la imagen :) enlace

Si has leído mi publicación hasta aquí, muchas gracias por tu atención. ¡Si alguien pudiera encontrar el tiempo para ayudarme con mi problema, estaría muy agradecido!

Atentamente,
Un principiante confundido en VHDL

    
pregunta T.R.

1 respuesta

0

Así es como lo trabajaría yo. Código primero:

mult.vhd

library ieee;  
use ieee.std_logic_1164.all;  

entity mult is  
port ( a     :  in std_logic;  
       b     :  in std_logic;  
       pin   :  in std_logic;    -- product in  
       cin   :  in std_logic;    -- carry in  
       pout  :  out std_logic;   -- product out
       cout  :  out std_logic ); -- carry out  
end mult;  

architecture mult of mult is
begin  
    pout <= (a and b) xor cin xor pin;
    cout <= (a and b and cin) or (a and b and pin) or (cin and pin);
end mult;

generic_mult.vhd

library ieee;
use ieee.std_logic_1164.all;

entity generic_mult is
generic (N: integer; M: integer);
port ( a    :  in  std_logic_vector(N-1 downto 0);
       b    :  in  std_logic_vector(M-1 downto 0);
       prod :  out std_logic_vector(M+N-1 downto 0) );
end entity generic_mult;

architecture behavioral of generic_mult is

-- Components
component mult is
port (
    a    :  in std_logic;
    b    :  in std_logic;
    pin  :  in std_logic;
    cin  :  in std_logic;
    pout :  out std_logic;
    cout :  out std_logic );
end component;

-- Signals
type mem_word is array (0 to M-1) of std_logic_vector(N-1 downto 0);
signal cin  : mem_word;
signal cout : mem_word;
signal pin  : mem_word;
signal pout : mem_word;

begin

    m_loop: for i in 0 to M-1 generate
        n_loop: for j in 0 to N-1 generate
            mult_inst : mult
            port map (
                a    => a(j),
                b    => b(i),
                pin  => pin(i)(j),
                cin  => cin(i)(j),
                pout => pout(i)(j),
                cout => cout(i)(j) );
        end generate;
    end generate;

    cin_init: for j in 0 to N-1 generate 
        cin(0)(j) <= '0'; 
    end generate;

    cin_mloop: for i in 1 to M-1 generate
        cin_nloop: for j in 0 to N-2 generate 
            cin(i)(j) <= pout(i-1)(j+1); 
        end generate;
        cin(i)(N-1) <= cout(i-1)(N-1);
    end generate;

    pin_mloop: for i in 0 to M-1 generate 
        pin(i)(0) <= '0'; 
        pin_nloop: for j in 1 to N-1 generate 
            pin(i)(j) <= cout(i)(j-1); 
        end generate;
    end generate;

    prod_loop: for j in 0 to M-1 generate
        prod(j) <= pout(j)(0);
    end generate;

    prod(M+N-2 downto M) <= pout(M-1)(N-1 downto 1);
    prod(M+N-1) <= cout(M-1)(N-1);

end behavioral;

simulation

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity NM_mult_tb is
end NM_mult_tb;

architecture behavioral of NM_mult_tb is

component generic_mult
generic (M: integer := 4; N: integer := 4);
    port (
        a    :  in  std_logic_vector(M-1 downto 0);
        b    :  in  std_logic_vector(N-1 downto 0);
        prod :  out std_logic_vector(M+N-1 downto 0) );
end component;

-- signals
signal a       : std_logic_vector(3 downto 0) :="0101";
signal b       : std_logic_vector(3 downto 0) :="1010";
signal answer  : std_logic_vector(7 downto 0);
signal correct : std_logic;

begin
    -- Instantiating the Design Under Test (DUT)
    dut: generic_mult
    generic map (
        M => 4,
        N => 4 )
    port map (
        a    => a,
        b    => b,
        prod => answer );

    -- Stimulus process
    stim_proc: process
    begin
        wait for 1 ns;
        a <= a + 1;
        if a = "0" then
            b <= b + 1;
        end if;
    end process;

    -- Check results
    correct <= '1' when to_integer(unsigned(a))*to_integer(unsigned(b)) = 
    to_integer(unsigned(answer)) else '0';

end behavioral;

Lo primero que hice fue simplificar la entidad mult . Y como se implementó como un multiplicador de 1 bit, cambié los nombres de las señales.

Para generic_mult , me resultó mucho más fácil dividir los buses carry_internal y sum_internal en buses de entrada / salida separados. Se eliminó gran parte de la confusión. A partir de ahí, no es demasiado difícil, como creo que verá en el código.

Por último, he cambiado tu

  

genérico (bits: entero);

a

  

genérico (N: entero; M: entero);

para permitir anchos MxN.

    
respondido por el Blair Fonville

Lea otras preguntas en las etiquetas