我正在尝试使用通用参数为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;
当我模拟它时,我发现随身携带和输入输出有问题,我的答案中有未定义的位:
如果你已经阅读了我的帖子,非常感谢你的关注。如果有人能找到时间帮助我解决我的问题,我将非常感激!
此致
困惑的VHDL初学者
答案 0 :(得分:0)
因此,对于算术运算,您只需要一个算术库:numeric_std
。不要使用std_logic_arith
,因为它不是标准化的,因此实现之间的行为可能不同。
然后std_logic_unsigned
可能存在风险。吉姆刘易斯解释here使用它可能是一个好主意,但我认为你不应该这样做。最好使用integer
,unsigned
和signed
数据类型进行所有比较。
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
。如果同时分配了1
和0
,则会解析为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;