Logic 带加法器的ALU实现
您好,我正在尝试创建一个带有一些操作码的32位加法器,除了两种情况外,它工作得很好,我似乎找不到导致它们的原因。。也许你能帮我 由于某种原因,减法运算总是失败,而当ADDC运算应该使用由ADDS运算创建的c_reg中的进位时,它无法计算正确的输出Logic 带加法器的ALU实现,logic,vhdl,hdl,Logic,Vhdl,Hdl,您好,我正在尝试创建一个带有一些操作码的32位加法器,除了两种情况外,它工作得很好,我似乎找不到导致它们的原因。。也许你能帮我 由于某种原因,减法运算总是失败,而当ADDC运算应该使用由ADDS运算创建的c_reg中的进位时,它无法计算正确的输出 LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL; ENTITY ALU IS GENERIC(WIDTH : NATURAL := 32);
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY ALU IS
GENERIC(WIDTH : NATURAL := 32);
PORT(Clk : IN STD_LOGIC := '0';
Reset : IN STD_LOGIC := '0';
A : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
B : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
Op : IN STD_LOGIC_VECTOR(3 DOWNTO 0) := (OTHERS => '0');
Outs : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END ALU;
ARCHITECTURE arch_ALU OF ALU IS
COMPONENT adder
PORT(OpA : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
OpB : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
Cin : IN STD_LOGIC;
Cout : OUT STD_LOGIC;
Result : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0));
END COMPONENT;
SIGNAL adder_output : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL B_neg : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL c_flag : STD_LOGIC := '0';
SIGNAL c_reg : STD_LOGIC := '0';
SIGNAL cin : STD_LOGIC := '0';
BEGIN
adder_comp : adder
PORT MAP(OpA => A,
OpB => B_neg,
Cin => cin,
Result => adder_output,
Cout => c_flag);
WITH Op SELECT
B_neg <= NOT(B) WHEN "1000",
B WHEN OTHERS;
WITH Op SELECT
cin <= '1' WHEN "1000", -- SUB
c_reg WHEN "0111", -- ADDC
'0' WHEN OTHERS; -- ADD/ADDS
ALU_Process:
PROCESS(Clk)
BEGIN
IF Reset = '0' THEN
Outs <= (OTHERS => '0');
ELSIF rising_edge(Clk) THEN
CASE Op IS
WHEN "0001" => Outs <= A AND B;
WHEN "0010" => Outs <= A OR B;
WHEN "0011" => Outs <= A NOR B;
WHEN "0100" => Outs <= A XOR B;
WHEN "0101" => Outs <= adder_output; -- ADD
WHEN "0110" => Outs <= adder_output; -- ADDS
c_reg <= c_flag;
WHEN "0111" => Outs <= adder_output; -- ADDC
WHEN "1000" => Outs <= adder_output; -- SUB
WHEN "1001" => Outs <= STD_LOGIC_VECTOR(UNSIGNED(A) SLL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1010" => Outs <= STD_LOGIC_VECTOR(unsigned(A) SRL to_integer(UNSIGNED(B(4 DOWNTO 0))));
WHEN "1011" => Outs <= STD_LOGIC_VECTOR(shift_right(SIGNED(A),to_integer(UNSIGNED(B(4 DOWNTO 0)))));
WHEN OTHERS => Outs <= (OTHERS => '0');
END CASE;
END IF;
END PROCESS;
END arch_ALU;
ieee库;
使用ieee.std_logic_1164.ALL;
使用ieee.numeric_std.ALL;
实体ALU是
通用(宽度:自然:=32);
端口(时钟:在标准逻辑中:='0';
重置:在标准逻辑中:='0';
答:在标准逻辑向量中(宽度-1到0):=(其他=>“0”);
B:在标准逻辑向量中(宽度-1到0):=(其他=>'0');
Op:STD_逻辑_向量(3到0):=(其他=>'0');
Outs:OUT标准_逻辑_向量(宽度-1到0));
末端ALU;
ALU的建筑arch_ALU是
分量加法器
端口(OpA:STD_逻辑_向量(宽度-1至0);
OpB:标准逻辑向量(宽度-1到0);
Cin:标准逻辑;
Cout:输出标准逻辑;
结果:输出标准_逻辑_向量(宽度-1到0));
端部元件;
信号加法器输出:标准逻辑向量(宽度-1到0):=(其他=>'0');
信号B_neg:STD_逻辑_向量(宽度-1到0):=(其他=>'0');
信号c_标志:标准_逻辑:='0';
信号c_reg:STD_逻辑:='0';
信号cin:STD_逻辑:='0';
开始
加法器组件:加法器
端口图(OpA=>A,
OpB=>B_neg,
Cin=>Cin,
结果=>加法器输出,
Cout=>c_标志);
使用Op SELECT
B_neg虽然您没有提供一个测试,但读者至少可以测试您的设计中存在的减法部分:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alu is
generic (width: natural := 32);
port (
clk: in std_logic := '0';
reset: in std_logic := '0';
a: in std_logic_vector(width - 1 downto 0) := (others => '0');
b: in std_logic_vector(width - 1 downto 0) := (others => '0');
op: in std_logic_vector(3 downto 0) := (others => '0');
outs: out std_logic_vector(width - 1 downto 0)
);
end alu;
architecture arch_alu of alu is
-- component adder
-- port (
-- opa: in std_logic_vector(width - 1 downto 0);
-- opb: in std_logic_vector(width - 1 downto 0);
-- cin: in std_logic;
-- cout: out std_logic;
-- result: out std_logic_vector(width - 1 downto 0)
-- );
-- end component;
procedure adder (
signal opa: in std_logic_vector(width - 1 downto 0);
signal opb: in std_logic_vector(width - 1 downto 0);
signal cin: in std_logic;
signal cout: out std_logic;
signal result: out std_logic_vector(width - 1 downto 0)
) is
variable sum: unsigned (width downto 0);
begin
sum := unsigned('0' & opa) + unsigned(opb) + unsigned'(""& cin);
result <= std_logic_vector(sum (width - 1 downto 0));
cout <= sum(width);
end procedure;
signal adder_output: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b_neg: std_logic_vector(width - 1 downto 0) := (others => '0');
signal c_flag: std_logic := '0';
signal c_reg: std_logic := '0';
signal cin: std_logic := '0';
begin
adder_comp:
adder
-- port map (
(
opa => a,
opb => b_neg,
cin => cin,
result => adder_output,
cout => c_flag
);
with op select
b_neg <= not b when "1000",
b when others;
with op select
cin <= '1' when "1000", -- sub
c_reg when "0111", -- addc
'0' when others; -- add/adds
alu_process:
process(clk)
begin
if reset = '0' then
outs <= (others => '0');
elsif rising_edge(clk) then
case op is
when "0001" => outs <= a and b;
when "0010" => outs <= a or b;
when "0011" => outs <= a nor b;
when "0100" => outs <= a xor b;
when "0101" => outs <= adder_output; -- add
when "0110" => outs <= adder_output; -- adds
c_reg <= c_flag;
when "0111" => outs <= adder_output; -- addc
when "1000" => outs <= adder_output; -- sub
when "1001" => outs <= std_logic_vector (
unsigned(a) sll to_integer(unsigned(b(4 downto 0)))
);
when "1010" => outs <= std_logic_vector (
unsigned(a) srl to_integer(unsigned(b(4 downto 0)))
);
when "1011" => outs <= std_logic_vector (
shift_right(signed(a),to_integer(unsigned(b(4 downto 0))))
);
when others => outs <= (others => '0');
end case;
end if;
end process;
end arch_alu;
library ieee;
use ieee.std_logic_1164.all;
entity alu_tb is
end entity;
architecture foo of alu_tb is
constant width: integer := 32;
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal a: std_logic_vector(width - 1 downto 0) := (others => '0');
signal b: std_logic_vector(width - 1 downto 0) := (others => '0');
signal op: std_logic_vector(3 downto 0) := (others => '0');
signal outs: std_logic_vector(width - 1 downto 0);
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 90 ns then
wait;
end if;
end process;
DUT:
entity work.alu
port map (
clk => clk,
reset => reset,
a => a,
b => b,
op => op,
outs => outs
);
STIMULUS:
process
begin
wait for 20 ns;
reset <= '1';
a <= x"E6A4960F";
b <= x"7B494E34";
op <= "1000";
wait for 20 ns;
a <= x"EFDE31A3";
b <= x"0BCAB8FA";
wait for 20 ns;
wait;
end process;
end architecture;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体alu是
通用(宽度:自然:=32);
港口(
时钟:在标准逻辑中:='0';
重置:在标准逻辑中:='0';
答:在标准逻辑向量中(宽度-1到0):=(其他=>'0');
b:在标准逻辑向量中(宽度-1到0):=(其他=>'0');
op:std_逻辑_向量(3到0):=(其他=>'0');
输出:输出标准逻辑向量(宽度-1到0)
);
末端alu;
alu的建筑arch_alu是
--分量加法器
--港口(
--opa:标准逻辑向量(宽度-1到0);
--opb:标准逻辑向量(宽度-1到0);
--cin:标准逻辑;
--cout:输出标准逻辑;
--结果:输出标准逻辑向量(宽度-1到0)
-- );
--端部元件;
程序加法器(
信号opa:标准逻辑向量(宽度-1至0);
信号opb:标准逻辑向量(宽度-1至0);
信号cin:标准逻辑中;
信号输出:输出标准逻辑;
信号结果:输出标准逻辑向量(宽度-1至0)
)是
变量和:无符号(宽度减至0);
开始
总和:=无符号('0'&opa)+无符号(opb)+无符号(“”&cin);
结果“0”);
信号c_标志:标准_逻辑:='0';
信号c_reg:std_逻辑:='0';
信号cin:std_逻辑:='0';
开始
加法器组件:
加法器
--港口地图(
(
opa=>a,
opb=>b_neg,
cin=>cin,
结果=>加法器输出,
cout=>c_标志
);
使用op select
b_neg“0”);
信号op:std_逻辑_向量(3到0):=(其他=>'0');
信号输出:标准逻辑向量(宽度-1至0);
开始
时钟:
过程
开始
等待10纳秒;
时钟90纳秒
等待
如果结束;
结束过程;
DUT:
实体工作.alu
港口地图(
时钟=>clk,
重置=>重置,
a=>a,
b=>b,
op=>op,
出局=>出局
);
刺激:
过程
开始
等待20纳秒;
重置是的,谢谢你的回复,我已经收到了加法器,据说它是经过测试和验证的。我刚刚用我的ripple carry设计测试了相同的设计,它工作得完美无缺。我想我必须调试加法器:)