VHDL NxM位并行块乘法器

时间:2017-11-01 07:34:46

标签: vhdl multiplication

我正在尝试使用通用参数为NxM位并行块乘法器创建原理图,以定义乘法器的大小,并生成描述内部结构的语句。我的总和和携带有些麻烦,我无法在VHDL代码中实现我想做的事。

这是我到目前为止所得到的:

1位乘数:

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;

将其用作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;

还有一个测试平台:

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;

当我模拟它时,我发现随身携带和输入输出有问题,我的答案中有未定义的位:

https://i.stack.imgur.com/y4ED9.png

如果你已经阅读了我的帖子,非常感谢你的关注。如果有人能找到时间帮助我解决我的问题,我将非常感激!

此致
困惑的VHDL初学者

1 个答案:

答案 0 :(得分:0)

因此,对于算术运算,您只需要一个算术库:numeric_std。不要使用std_logic_arith,因为它不是标准化的,因此实现之间的行为可能不同。

然后std_logic_unsigned可能存在风险。吉姆刘易斯解释here使用它可能是一个好主意,但我认为你不应该这样做。最好使用integerunsignedsigned数据类型进行所有比较。

实体mult

您正在实施的是查找表。组合逻辑语句。这不是算术运算,因此不需要算术库。

但是,您可以简化代码。 我们来看this description参考。

可以使用逻辑运算符(基于描述为here的完整加法器)定义1x1乘数:

architecture rtl of mult is
    signal FA_a, FA_b : std_logic;
begin
    FA_a <= Sin;
    FA_b <= a AND b;
    Sout <= FA_a XOR FA_b XOR Cin;
    Cout <= (FA_a AND FA_b) OR (Cin AND (FA_a XOR FA_b));
end architecture;

或者只是跳过这一切并使用加法运算符,它为您提供逻辑。

architecture rtl of mult is
    use ieee.numeric_std.all;
    signal FA_a, FA_b, FA_Cin : unsigned(1 downto 0) := (others => '0');
    signal FA_out : unsigned(1 downto 0);
begin
    FA_a(0) <= Sin;
    FA_b(0) <= a AND b;
    FA_Cin(0) <= Cin;
    FA_out <= FA_a + FA_b + FA_Cin;
    Sout <= FA_out(0);
    Cout <= FA_out(1);
end architecture;

实体generic_mult

首先,您的乘数是MxM,而不是MxN。 接下来,您在评论中抱怨您的标签......需要付出同样的努力来改变它们;)。

关于您的实施,您将在labellll生成块中多次分配信号。它应该是:

labellll: for N in 0 to bits-1 generate
    sum_internal(N+1)(N) <= carry_internal(N)(N);
end generate;

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

但这不是最大的问题,因为它可以解决。 你遇到的问题与多个驱动程序有关。在this_is_label2中,您有以下行:

Sout => sum_internal(M+1)(N-1)

labellll中你有这条线:

sum_internal(N+1)(N) <= carry_internal(N)(N);

两个语句,都将值赋给sum_internal。如果同时分配了10,则会解析为X

但这不是必要的,因为它是您设计中出错的结果。请再次查看my link,了解如何实施乘数。我不打算为你做这件事(这不是那么困难,也可能是你的作业。如果其他人为你做功课,你就什么也学不到。;)

测试平台

您正在将unsigned算术(to_integer(unsigned(a))*to_integer(unsigned(b)))与std_logic_vector算术(a <= a + 1;)合并。不要那样做。最好只使用unsigned

使用乘法运算符

如pev.hall所述,您可以简化所有内容并使用numeric_std包中的乘法运算符。

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

architecture rtl of generic_mult is
    use ieee.numeric_std.all;
begin
    answer <= std_logic_vector(unsigned(a)*unsigned(b));
end architecture;