Проблема с внедрением неподписанного компонента в условия ALU в VHDL - PullRequest
0 голосов
/ 17 апреля 2020

Мне нужно создать ALU, в котором есть условия для добавления, добавления без знака, саб, суб без знака и, или, или xor, ни, slt и slt без знака. У меня возникают трудности при реализации дизайна, чтобы включить неподписанные условия. Я отметил в коде, где происходят ошибки. Кроме того, все остальные аспекты ALU работают правильно, это ТОЛЬКО неподписанная часть, с которой мне нужна помощь. Я изучал unsigned и std_logi c, но не смог найти проблем, похожих на мою.

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;

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Я прошел через это тщательно. Основная проблема заключается в преобразовании типов, поэтому я прокомментировал, где я их добавил. Я также внес некоторые изменения в код, чтобы сделать его более читабельным, добавив константы для имен команд, что, как правило, является хорошей практикой, и оператор case для выбора команд. И std_logic_unsigned является устаревшей нестандартной библиотекой.

Я обновил ее в соответствии с вашими обновлениями к вашему первоначальному вопросу, касающемуся обработки неподписанных логи c. Я также добавил еще пару констант и три подтипа в соответствии с принципом дизайна, согласно которому только одна версия истины.

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;
1 голос
/ 17 апреля 2020

Так что, не глядя на детали, я могу рассказать вам, почему у вас возникают проблемы с компиляцией для первой ошибки. Во-первых, давайте посмотрим на ваши сигналы. Все они объявлены как тип без знака.

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

Однако ваш выходной порт ALUOut относится к типу STD_LOGIC_VECTOR. У вас будут проблемы, потому что signed отличается от STD_LOGIC_VECTOR. К счастью для вас, эти типы очень легко переносить в и из этих типов. На самом деле, я всегда держу под рукой этот конверт nandland .

Попробуйте следующее. Он должен привести ваш подписанный тип к 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

Так что в качестве обзора курса cra sh я опишу, как я думаю о std_logic_vector, подписанном и неподписанном. Еще раз, nandland имеет хороший обзор этих типов . Вот как я это себе представляю:

  1. std_logic_vector не знает, должен ли вектор STD_LOGI C быть представлением со знаком или без знака. Поэтому любые операции сложения, вычитания и умножения не будут работать.
  2. signed интерпретирует вектор std_logi c как использование формы комплиментов двух. Это позволяет для сложения, вычитания и умножения подписанных типов вместе
  3. unsigned аналогично знаку, но предполагает, что целые числа являются беззнаковым представлением.

Если вы пытаетесь не использовать signed или unsigned для назначения, вам нужно будет реализовать логи c. Однако вы можете позволить подписанному и неподписанному типам реализовывать для вас логи c.

Итак, давайте добавим два типа 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));

Надеюсь, это поможет!

...