简体   繁体   English

在 VHDL 中将无符号组件实现到 ALU 的条件时出现问题

[英]Trouble implementing unsigned component to conditions of ALU in VHDL

I have to create an ALU that has conditions for add, add unsigned, sub, sub unsigned, and, or, xor, nor, slt, and slt unsigned.我必须创建一个 ALU,它具有 add、add unsigned、sub、sub unsigned 和、or、xor、nor、slt 和 slt unsigned 的条件。 I am having difficulty implementing the design to include the unsigned conditions.我在实施设计以包含未签名条件时遇到困难。 I have noted in the code where the errors are occurring.我已经在发生错误的代码中注明。 Also, every other aspect of the ALU works correct, it is ONLY the unsigned portion I need help with.此外,ALU 的所有其他方面都可以正常工作,这只是我需要帮助的未签名部分。 I was researching about unsigned and std_logic but I was unable to find the problems similar to mine.我正在研究 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, sltu : std_logic_vector (31 downto 0);
signal add_result,sub_result,a32,b32: std_logic_vector(32 downto 0);
-- create separate a and b for unsigned 
signal add_u,sub_u,a32u,b32u: unsigned(32 downto 0);
signal c32: std_logic_vector(32 downto 0):=(others=>'0');
signal add_ov,sub_ov:std_logic;

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
            std_logic_vector(add_u(31 downto 0)) when "0100", -- add unsigned 
            std_logic_vector(sub_u(31 downto 0)) when "0101", -- sub unsigned
            sltu    when "1000", -- set less than 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;
process(a32u,b32u)
begin
if (a32u < b32u) then 
    sltu <= x"00000001";
else
    sltu <= 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));
sub_result<=std_logic_vector(signed(a32) - signed(b32));

a32u   <=unsigned('0'& A);
b32u   <=unsigned('0'& B);
add_u<=a32u + b32u + unsigned(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" | "0100",
             sub_ov when "0110" | "0101",
             'Z' when others;

---Carryout-------------------------------------------------
With ALUCntl select 
Carryout<= add_result(32) when "0010",
            sub_result(32) when "0110",
            add_u(32)      when "0100",
            sub_u(32)      when "0101",
            'Z' when others;
end Behavioral;

So without looking at the details, I can tell you why you're having compilation issues for the first error.因此,无需查看详细信息,我就可以告诉您为什么第一个错误会出现编译问题。 First, lets look at your signals.首先,让我们看看你的信号。 They are all declared as the unsigned type.它们都被声明为无符号类型。

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

However, your ALUOut output port is of the STD_LOGIC_VECTOR type.但是,您的ALUOut output 端口属于STD_LOGIC_VECTOR类型。 You will have issues because signed is not the same as STD_LOGIC_VECTOR .您会遇到问题,因为signedSTD_LOGIC_VECTOR不同。 Luckily for you, it's very easy to cast to and from these types.幸运的是,在这些类型之间进行转换非常容易。 I actually keep this nandland conversion cheatsheet handy at all times.实际上,我始终将这个 NAND 转换备忘单放在手边。

Try the following.试试下面的。 It should cast your signed type to an STD_LOGIC_VECTOR.它应该将您的签名类型转换为 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

So as a crash course review I'll describe how I think about std_logic_vector, signed, and unsigned.因此,作为速成课程回顾,我将描述我对 std_logic_vector、已签名和未签名的看法。 Yet again, nandland has a good review of these types .再一次, nandland 对这些类型有很好的评价 Here is how I imagine it:这是我的想象:

  1. std_logic_vector does not know whether the vector of STD_LOGIC is supposed to be signed or unsigned representation. std_logic_vector不知道 STD_LOGIC 的向量应该是有符号还是无符号表示。 Therefore, any addition, subtraction, and multiplication operations won't work.因此,任何加法、减法和乘法运算都不起作用。
  2. signed is interpreting a vector of std_logic as using two's compliments form. signed将 std_logic 的向量解释为使用二进制补码形式。 This allows for the addition, subtraction, and multiplication of the signed types together这允许对有符号类型进行加法、减法和乘法运算
  3. unsigned is similar to signed, but assumes that the integers are unsigned representation. unsigned类似于signed,但假定整数是无符号表示。

If you are trying to not used signed or unsigned for an assignment, then you will need to implement the logic.如果您尝试不使用有signedunsigned进行分配,那么您将需要实现逻辑。 However, you can let the signed and unsigned types implement the logic for you.但是,您可以让有符号和无符号类型为您实现逻辑。

So let's add two types of std_logic_vector .所以让我们添加两种类型的std_logic_vector As you see below, I cast the A and B vectors to signed/unsigned, then cast back to 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));

I hope this helps!我希望这有帮助!

I've gone through it thoroughly.我已经彻底完成了。 The main issue is type conversions, so I've commented where I've added them.主要问题是类型转换,所以我已经评论了我添加它们的位置。 I've also tweaked some of the code to make it more readable by adding constants for the command names which is generally good practice, and a case statement for command selection.我还调整了一些代码,使其更具可读性,为命令名称添加常量,这通常是一种很好的做法,并为命令选择添加了一个 case 语句。 And std_logic_unsigned is a deprecated non standard library.std_logic_unsigned是一个已弃用的非标准库。

I've updated it in keeping with your updates to your original question regarding the processing of unsigned logic.我已根据您对处理未签名逻辑的原始问题的更新对其进行了更新。 I've also added a couple more constants and three subtypes in keeping with the design principle of only having one version of the truth.我还添加了几个常量和三个子类型,以符合只有一个版本的真相的设计原则。

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 and subtypes to make the code more readable and maintainable.

    constant ALU_MSB: natural := ALU_BITS - 1;

    subtype TALURegister is std_logic_vector(ALU_MSB downto 0);
    subtype TALURegisterX is std_logic_vector(ALU_BITS downto 0);
    subtype TALURegisterXU is unsigned(ALU_BITS downto 0);

    constant ALU_REGISTER_ZERO: TALURegister := (others => '0');
    constant ALU_REGISTER_ONE : TALURegister := (ALU_MSB downto 1 => '0') & '1';

    constant CMD_ADD   : std_logic_vector := "0010";
    constant CMD_SUB   : std_logic_vector := "0110";
    constant CMD_SLT   : std_logic_vector := "0111";
    constant CMD_SLT_U : std_logic_vector := "1000";
    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, sltu : TALURegister;
    signal add_result, sub_result, a32, b32: TALURegisterX;

    -- create separate a and b for unsigned
    signal add_u, sub_u, a32u, b32u: TALURegisterXU;
    signal c32: TALURegisterX := (others => '0');
    signal add_ov, sub_ov: std_logic;

    begin
        -- Alternative command selection using a case statement.
        process(ALUCntl, add_result, sub_result, slt, sltu, add_u, sub_u, A, B)
        begin
            case ALUCntl is
                when CMD_ADD    =>  ALU_Result <= add_result(ALU_MSB downto 0);
                when CMD_SUB    =>  ALU_Result <= sub_result(ALU_MSB downto 0);
                when CMD_SLT    =>  ALU_Result <= slt;
                when CMD_SLT_U  =>  ALU_Result <= sltu;
                when CMD_ADD_U  =>  ALU_Result <= TALURegister(add_u(ALU_MSB downto 0));  -- Added type conversion.
                when CMD_SUB_U  =>  ALU_Result <= TALURegister(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(ALU_MSB downto 0) when CMD_ADD, -- add
                -- sub_result(ALU_MSB downto 0) when CMD_SUB, -- sub
                -- slt     when CMD_SLT, -- set less than

                -- - Getting an error that indexed name is not STD_LOGIC_VECTOR --
                -- TALURegister(add_u(ALU_MSB downto 0)) when CMD_ADD_U, -- add unsigned  -- Added type conversion.
                -- TALURegister(sub_u(ALU_MSB downto 0)) when CMD_SUB_U, -- sub unsigned  -- Added type conversion.
                ---------------------------------------------------------

                -- sltu    when CMD_SLT_U, -- set less than unsigned
                -- A AND B when CMD_AND,
                -- A OR  B when CMD_OR,
                -- A XOR B when CMD_XOR,
                -- A NOR B when CMD_NOR,
                -- 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 <= ALU_REGISTER_ONE;
            else
                slt <= ALU_REGISTER_ZERO;
            end if;
        end process;

        ----Set less than unsigned--------------------------
        process(a32u, b32u)
        begin
        if (a32u < b32u) then
            sltu <= ALU_REGISTER_ONE;
        else
            sltu <= ALU_REGISTER_ZERO;
        end if;
        end process;

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

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

        -------------------------------------------------
        ---Zero flag-----------------------------
        Zero <= '1' when ALU_Result = ALU_REGISTER_ZERO else '0';

        ---Overflow flag---------------------------------------
        add_ov <= (A(ALU_MSB) and B(ALU_MSB)       and (not alu_result(ALU_MSB))) or ((not A(ALU_MSB)) and (not B(ALU_MSB)) and alu_result(ALU_MSB));
        sub_ov <= (A(ALU_MSB) and (not B(ALU_MSB)) and (not alu_result(ALU_MSB))) or ((not A(ALU_MSB)) and B(ALU_MSB)       and alu_result(ALU_MSB));
        with ALUCntl select
            Overflow <=
                add_ov when CMD_ADD | CMD_ADD_U,
                sub_ov when CMD_SUB | CMD_SUB_U,
                'Z' when others;

        ---Carryout-------------------------------------------------
        with ALUCntl select
            Carryout <=
                add_result(ALU_BITS) when CMD_ADD,
                sub_result(ALU_BITS) when CMD_SUB,
                add_u(ALU_BITS)      when CMD_ADD_U,
                sub_u(ALU_BITS)      when CMD_SUB_U,
                'Z' when others;
end Behavioral;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM