难以在VHDL中实现ALU条件的未签名组件

问题描述 投票:1回答:2

我必须创建一个ALU,该ALU具有添加,无符号,子,子无符号和,或xor,或slt和slt无符号的条件。我很难实现包含未签名条件的设计。我已经在代码中指出了发生错误的位置。而且,ALU的其他所有方面都可以正常工作,只有我需要帮助的未签名部分。我正在研究unsigned和std_logic,但找不到类似于我的问题。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;

entity ALU is
Port (A, B     : in  STD_LOGIC_VECTOR (31 downto 0);
      ALUCntl  : in  STD_LOGIC_VECTOR (3 downto 0);
      Carryin  : in  STD_LOGIC;
      ALUOut   : out STD_LOGIC_VECTOR (31 downto 0);
      Zero     : out STD_LOGIC;
      Carryout : out STD_LOGIC;
      Overflow : out STD_LOGIC);
end ALU; 

architecture Behavioral of ALU is
signal ALU_Result, slt : std_logic_vector (31 downto 0);
signal add_result,sub_result,a32,b32: std_logic_vector(32 downto 0);
signal c32: std_logic_vector(32 downto 0):=(others=>'0');
signal add_ov,sub_ov:std_logic;

-- create separate signal for unsigned 
signal add_u,sub_u,a32u,b32u: unsigned(32 downto 0);

begin
with ALUCntl select
ALU_Result <=add_result(31 downto 0) when "0010", -- add
            sub_result(31 downto 0) when "0110", -- sub
            slt     when "0111", -- set less than

            ----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
            add_u(31 downto 0) when "0100", -- add unsigned 
            sub_u(31 downto 0) when "0101", -- sub unsigned
            -------------------------------------------------------------------

            A AND B when "0000",
            A OR  B when "0001",
            A XOR B when "0011",
            A NOR B when "1100",
            A when others;---condition for all other alu control signals
ALUOut  <= ALU_Result; 
----Set less than-----------------------------------
process(a32,b32)
begin
if (a32 < b32) then 
    slt <= x"00000001";
else
    slt <= x"00000000";
end if;
end process;
----Addition Operation and carry out generation-----    
a32   <='0'& A;
b32   <='0'& B;
c32(0)<=Carryin;
add_result<=a32 + b32 + c32;
sub_result<=a32 - b32;
-- Getting "'0' definitions found" errors here --
a32u   <='0'& A;
b32u   <='0'& B;
add_u<=a32u + b32u + c32;
sub_u<=a32u - b32u;
-------------------------------------------------
---Zero flag-----------------------------   
Zero <= '1' when ALU_Result =x"00000000" else '0';
---Overflow flag---------------------------------------
add_ov<= (A(31)and B(31)       and (not alu_result(31))) or ((not A(31))and (not B(31)) and alu_result(31));
sub_ov<= (A(31)and (not B(31)) and (not alu_result(31))) or ((not A(31))and B(31)       and alu_result(31)); 
with ALUCntl select
  Overflow<= add_ov when "0010",
             sub_ov when "0110",
             'Z' when others;
---Carryout-------------------------------------------------
With ALUCntl select 
 Carryout<= add_result(32) when "0010",
            sub_result(32) when "0110",
            'Z' when others;
 end Behavioral;
vhdl unsigned alu
2个回答
0
投票

我已经仔细阅读了。主要问题是类型转换,因此我评论了添加它们的位置。我还通过添加命令名称常量和用于命令选择的case语句,对一些代码进行了调整,以使其更具可读性。 std_logic_unsigned是已弃用的非标准库。

library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_unsigned.all;  -- Not advisable to use this non standard library.
use ieee.numeric_std.all;

entity ALU is
    generic
    (
        ALU_BITS: natural := 32  -- Added a generic parameter to specify the number of bits in the ALU.
    );
    port
    (
        A, B     : in  std_logic_vector (ALU_BITS - 1 downto 0);
        ALUCntl  : in  std_logic_vector (3 downto 0);
        Carryin  : in  std_logic;
        ALUOut   : out std_logic_vector (ALU_BITS - 1 downto 0);
        Zero     : out std_logic;
        Carryout : out std_logic;
        Overflow : out std_logic
    );
end ALU;

architecture Behavioral of ALU is

    -- Added some constants to make the code more readable.

    constant ALU_MSB: natural := ALU_BITS - 1;

    constant CMD_ADD   : std_logic_vector := "0010";
    constant CMD_SUB   : std_logic_vector := "0110";
    constant CMD_SLT   : std_logic_vector := "0111";
    constant CMD_ADD_U : std_logic_vector := "0100";
    constant CMD_SUB_U : std_logic_vector := "0101";
    constant CMD_AND   : std_logic_vector := "0000";
    constant CMD_OR    : std_logic_vector := "0001";
    constant CMD_XOR   : std_logic_vector := "0011";
    constant CMD_NOR   : std_logic_vector := "1100";

    signal ALU_Result, slt: std_logic_vector (ALU_MSB downto 0);
    signal add_result, sub_result, a32, b32: std_logic_vector(ALU_BITS downto 0);
    signal c32: std_logic_vector(ALU_BITS downto 0) := (others => '0');
    signal add_ov, sub_ov: std_logic;

    -- create separate signal for unsigned
    signal add_u, sub_u, a32u, b32u: unsigned(ALU_BITS downto 0);

    begin
        -- Alternative command selection using a case statement.
        process(ALUCntl, add_result, add_ov, sub_result, sub_ov, slt, add_u, sub_u, A, B)
        begin
            case ALUCntl is
                when CMD_ADD    =>  ALU_Result <= add_result(ALU_MSB downto 0);
                                    Carryout   <= add_result(ALU_BITS);
                                    Overflow   <= add_ov;
                when CMD_SUB    =>  ALU_Result <= sub_result(ALU_MSB downto 0);
                                    Carryout   <= sub_result(ALU_BITS);
                                    Overflow   <= sub_ov;
                when CMD_SLT    =>  ALU_Result <= slt;
                when CMD_ADD_U  =>  ALU_Result <= std_logic_vector(add_u(ALU_MSB downto 0));  -- Added type conversion.
                when CMD_SUB_U  =>  ALU_Result <= std_logic_vector(sub_u(ALU_MSB downto 0));  -- Added type conversion.
                when CMD_AND    =>  ALU_Result <= A and B;
                when CMD_OR     =>  ALU_Result <= A or B;
                when CMD_XOR    =>  ALU_Result <= A xor B;
                when CMD_NOR    =>  ALU_Result <= A nor B;
                when others     =>  ALU_Result <= A;
            end case;
        end process;

        -- with ALUCntl select
        -- ALU_Result <= add_result(31 downto 0) when "0010", -- add
                    -- sub_result(31 downto 0) when "0110", -- sub
                    -- slt     when "0111", -- set less than

                    -- ----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
                    -- std_logic_vector(add_u(31 downto 0)) when "0100", -- add unsigned  -- Added type conversion.
                    -- std_logic_vector(sub_u(31 downto 0)) when "0101", -- sub unsigned  -- Added type conversion.
                    -- -------------------------------------------------------------------

                    -- A AND B when "0000",
                    -- A OR  B when "0001",
                    -- A XOR B when "0011",
                    -- A NOR B when "1100",
                    -- A when others;---condition for all other alu control signals

        ALUOut  <= ALU_Result;

        ----Set less than-----------------------------------
        process(a32, b32)
        begin
            if (a32 < b32) then
                slt <= x"00000001";
            else
                slt <= x"00000000";
            end if;
        end process;

        ----Addition Operation and carry out generation-----
        a32     <= '0' & A;
        b32     <= '0' & B;
        c32(0)  <= Carryin;
        add_result <= std_logic_vector(signed(a32) + signed(b32) + signed(c32));  -- Added type conversion.
        sub_result <= std_logic_vector(signed(a32) - signed(b32));                -- Added type conversion.

        -- Getting "'0' definitions found" errors here --
        a32u  <= unsigned('0' & A);            -- Added type conversion.
        b32u  <= unsigned('0' & B);            -- Added type conversion.
        add_u <= a32u + b32u + unsigned(c32);  -- Added type conversion.
        sub_u <= a32u - b32u;

        -------------------------------------------------
        ---Zero flag-----------------------------
        Zero <= '1' when ALU_Result = x"00000000" else '0';

        ---Overflow flag---------------------------------------
        add_ov <= (A(31)and B(31)       and (not alu_result(31))) or ((not A(31))and (not B(31)) and alu_result(31));
        sub_ov <= (A(31)and (not B(31)) and (not alu_result(31))) or ((not A(31))and B(31)       and alu_result(31));

        -- Moved to the case statement above.
        -- with ALUCntl select
          -- Overflow <= add_ov when "0010",
                     -- sub_ov when "0110",
                     -- 'Z' when others;

        ---Carryout-------------------------------------------------

        -- Moved to the case statement above.
        -- With ALUCntl select
         -- Carryout <= add_result(32) when "0010",
                    -- sub_result(32) when "0110",
                    -- 'Z' when others;
end Behavioral;

0
投票

因此,无需查看细节,我可以告诉您为什么您遇到第一个错误的编译问题。首先,让我们看看您的信号。它们都被声明为无符号类型。

signal add_u,sub_u,a32u,b32u: unsigned(32 downto 0);

但是,您的ALUOut输出端口是STD_LOGIC_VECTOR类型。您会遇到问题,因为signedSTD_LOGIC_VECTOR不同。幸运的是,在这些类型之间进行转换非常容易。实际上,我一直都方便this nandland conversion cheatsheet

尝试以下操作。它应该将您的签名类型转换为STD_LOGIC_VECTOR。

ALU_Result <=add_result(31 downto 0) when "0010", -- add
            sub_result(31 downto 0) when "0110", -- sub
            slt     when "0111", -- set less than

            ----- Getting an error that indexed name is not STD_LOGIC_VECTOR --
            STD_LOGIC_VECTOR(add_u(31 downto 0)) when "0100", -- add unsigned 
            STD_LOGIC_VECTOR(sub_u(31 downto 0)) when "0101", -- sub unsigned

因此,作为速成课程的回顾,我将描述我对std_logic_vector,有符号和无符号的看法。再一次,nandland has a good review of these types。这是我的想象:

  1. std_logic_vector不知道STD_LOGIC的矢量应该是带符号的表示还是无符号的表示。因此,任何加法,减法和乘法运算均不起作用。
  2. signed将std_logic的向量解释为使用二进制补码形式。这允许将带符号的类型加,减和乘在一起]
  3. unsigned与有符号相似,但假定整数是无符号表示。

如果您尝试不使用signedunsigned进行分配,那么您将需要实现逻辑。但是,您可以让有符号和无符号类型为您实现逻辑。

因此,我们添加两种类型的std_logic_vector。如下所示,我将A和B向量转换为有符号/无符号,然后转换回std_logic_vector

signal A, B: std_logic_vector(31 downto 0);
signal result: std_logic_vector(31 + 1 downto 0);
-- Lets add them together as though they were unsigned
-- We pad a 0 to the end of the value to extend its length
result <= std_logic_vector(unsigned('0' & A) + unsigned(B));
-- Lets add them together as though they were signed
-- We copy the last bit of A for signed values
result <= std_logic_vector(signed((A(31) & & A) + signed(B));

我希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.