VHDL 4位向量中的无符号乘法?
Unsigned multiplication in VHDL 4bit vector?
我正在制作一个 ALU,可以选择执行 A + 2B
但我无法理解乘以 2B 并在我的测试台上得到正确的答案。
例如:A = 0110 B = 0011
方程式是 A + 2B
我得到 0110
我的代码片段是
entity ALU is
port( A :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
B :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
S0 :IN STD_LOGIC ;
S1 :IN STD_LOGIC ;
M :IN STD_LOGIC ;
C0 :IN STD_LOGIC ;
Cout :OUT STD_LOGIC ;
Z :OUT STD_LOGIC ;
F :OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
SIGNAL VariableAlu : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP2 : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL ZTEMP : STD_LOGIC;
SIGNAL BTEMP1 : STD_LOGIC_VECTOR(4 DOWNTO 0);
END ALU ;
PROCESS(A,B,S0,S1,M,C0)
BEGIN
VariableAlu <= (S0 & S1 & C0 & M);
--M = 1 ARITHMETIC
(part that shifts it, lab teacher told us to do this)
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
when "1111" => FTEMP2 <= ((A) + BTEMP1);
如有任何帮助,我们将不胜感激。
关于您的代码,有几点需要注意。首先,对于任何算法,避免使用 SLV 并坚持使用 numeric_std
库中的 unsigned
或 signed
类型。
您对操作数 B 的显式移位(乘以 2):
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
a) 不需要,b) 冗长。您可以通过简单地执行 BTEMP <= B & '0';
来实现此目的,或者更好的是,甚至不使用中间信号并直接分配给 switch 语句中的 FTEMP2
。例如
when "1111" => FTEMP2 <= std_logic_vector(unsigned(A) + unsigned(B&'0'));
注意上一行中的转换。它们是必需的,因为默认情况下,SLV 不支持 +
运算符(除非您使用 std_logic_unsigned
或 std_logic_signed
库)。为此,您需要包含 numeric_std
库。
编辑:
我还忘了提到 FTEMP 可能会溢出给定的函数; F <= A + 2B
,其中A
和B
都是4位,F
是5位。
除了GSM说的,你也可以随便写。 IE。乘以 2。合成软件足够智能,可以识别您在做什么。
你要记住的是,结果会太大,所以必须调整大小。
library IEEE;
use IEEE.std_logic_1164.all;
entity input_output_adder is
port (
input_a : in std_logic_vector(4 downto 0);
input_b : in std_logic_vector(4 downto 0);
output : out std_logic_vector(4 downto 0)
);
end entity;
architecture rtl of input_output_adder is
use IEEE.numeric_std.all;
begin
output <= std_logic_vector(unsigned(input_a) + resize((unsigned(input_b) * 2), 5));
end architecture;
这将导致仅 LUT...nu 乘数。
来自 Vivado 的结果:
Quartus 的结果:
我正在制作一个 ALU,可以选择执行 A + 2B 但我无法理解乘以 2B 并在我的测试台上得到正确的答案。
例如:A = 0110 B = 0011 方程式是 A + 2B 我得到 0110
我的代码片段是
entity ALU is
port( A :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
B :IN STD_LOGIC_VECTOR(3 DOWNTO 0) ;
S0 :IN STD_LOGIC ;
S1 :IN STD_LOGIC ;
M :IN STD_LOGIC ;
C0 :IN STD_LOGIC ;
Cout :OUT STD_LOGIC ;
Z :OUT STD_LOGIC ;
F :OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
SIGNAL VariableAlu : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL FTEMP2 : STD_LOGIC_VECTOR(4 DOWNTO 0);
SIGNAL ZTEMP : STD_LOGIC;
SIGNAL BTEMP1 : STD_LOGIC_VECTOR(4 DOWNTO 0);
END ALU ;
PROCESS(A,B,S0,S1,M,C0)
BEGIN
VariableAlu <= (S0 & S1 & C0 & M);
--M = 1 ARITHMETIC
(part that shifts it, lab teacher told us to do this)
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
when "1111" => FTEMP2 <= ((A) + BTEMP1);
如有任何帮助,我们将不胜感激。
关于您的代码,有几点需要注意。首先,对于任何算法,避免使用 SLV 并坚持使用 numeric_std
库中的 unsigned
或 signed
类型。
您对操作数 B 的显式移位(乘以 2):
BTEMP1(4 DOWNTO 1)<= B;
BTEMP1(0)<= '0';
a) 不需要,b) 冗长。您可以通过简单地执行 BTEMP <= B & '0';
来实现此目的,或者更好的是,甚至不使用中间信号并直接分配给 switch 语句中的 FTEMP2
。例如
when "1111" => FTEMP2 <= std_logic_vector(unsigned(A) + unsigned(B&'0'));
注意上一行中的转换。它们是必需的,因为默认情况下,SLV 不支持 +
运算符(除非您使用 std_logic_unsigned
或 std_logic_signed
库)。为此,您需要包含 numeric_std
库。
编辑:
我还忘了提到 FTEMP 可能会溢出给定的函数; F <= A + 2B
,其中A
和B
都是4位,F
是5位。
除了GSM说的,你也可以随便写。 IE。乘以 2。合成软件足够智能,可以识别您在做什么。 你要记住的是,结果会太大,所以必须调整大小。
library IEEE;
use IEEE.std_logic_1164.all;
entity input_output_adder is
port (
input_a : in std_logic_vector(4 downto 0);
input_b : in std_logic_vector(4 downto 0);
output : out std_logic_vector(4 downto 0)
);
end entity;
architecture rtl of input_output_adder is
use IEEE.numeric_std.all;
begin
output <= std_logic_vector(unsigned(input_a) + resize((unsigned(input_b) * 2), 5));
end architecture;
这将导致仅 LUT...nu 乘数。
来自 Vivado 的结果:
Quartus 的结果: