2 votes

Problème d'implémentation du composant non signé aux conditions de l'ALU en VHDL

Je dois créer une ALU qui a des conditions pour add, add unsigned, sub, sub unsigned, and, or, xor, nor, slt, et slt unsigned. J'ai des difficultés à mettre en œuvre la conception pour inclure les conditions non signées. J'ai noté dans le code où les erreurs se produisent. De plus, tous les autres aspects de l'UAL fonctionnent correctement, c'est SEULEMENT la partie non signée qui me pose problème. J'ai fait des recherches au sujet de unsigned et de std_logic mais je n'ai pas réussi à trouver les problèmes similaires au mien.

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;

1voto

GLJ Points 627

Donc sans regarder les détails, je peux vous dire pourquoi vous avez des problèmes de compilation pour la première erreur. Tout d'abord, regardons vos signaux. Ils sont tous déclarés comme le type unsigned.

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

Cependant, votre ALUOut Le port de sortie est du type STD_LOGIC_VECTOR type. Vous aurez des problèmes parce que signed n'est pas la même chose que STD_LOGIC_VECTOR . Heureusement pour vous, il est très facile de faire des lancers vers et depuis ces types d'objets. En fait, je garde cette fiche technique de conversion des nandlands à portée de main à tout moment.

Essayez ce qui suit. Elle devrait transformer votre type signé en un 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

Je vais donc vous expliquer comment je conçois les vecteurs std_logic_vector, signed et unsigned. Encore une fois, nandland propose une bonne revue de ces types de produits. . Voici comment je l'imagine :

  1. std_logic_vector ne sait pas si le vecteur de STD_LOGIC est censé être une représentation signée ou non signée. Par conséquent, toutes les opérations d'addition, de soustraction et de multiplication ne fonctionneront pas.
  2. signed interprète un vecteur de std_logic comme utilisant la forme complémentaire de deux. Cela permet l'addition, la soustraction et la multiplication des types signés ensemble.
  3. unsigned est similaire à signed, mais suppose que les entiers sont des représentations non signées.

Si vous essayez de ne pas utiliser signed o unsigned pour une affectation, vous devrez alors mettre en œuvre la logique. Cependant, vous pouvez laisser les types signés et non signés implémenter la logique pour vous.

Ajoutons donc deux types de std_logic_vector . Comme vous le voyez ci-dessous, je convertis les vecteurs A et B en signés/non signés, puis je les convertis à nouveau en 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));

J'espère que cela vous aidera !

1voto

tim Points 446

Je l'ai parcouru en profondeur. Le principal problème concerne les conversions de type, j'ai donc commenté les endroits où je les ai ajoutées. J'ai également modifié une partie du code pour le rendre plus lisible en ajoutant des constantes pour les noms des commandes, ce qui est généralement une bonne pratique, et une déclaration de cas pour la sélection des commandes. Et std_logic_unsigned est une bibliothèque non standard dépréciée.

Je l'ai mis à jour en fonction des mises à jour apportées à votre question initiale concernant le traitement de la logique non signée. J'ai également ajouté quelques constantes supplémentaires et trois sous-types, conformément au principe de conception consistant à n'avoir qu'une seule version de la vérité.

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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X