Logic 带加法器的ALU实现

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

您好,我正在尝试创建一个带有一些操作码的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);
    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设计测试了相同的设计,它工作得完美无缺。我想我必须调试加法器:)