如何在4位ALU设计中连接3个操作选择位 - VHDL

时间:2015-01-28 14:13:08

标签: vhdl alu

所以我一直在研究这个任务,它要求我设计一个由几位控制的4位ALU(即S1,S0,Cin / C0(进位)和M)取决于值M ALU将执行逻辑或算术运算。我暂时设计了一个ALU,它使用名为'Sel'的输入,同时我弄清楚如何取3个diff输入(S0,S1,Cin / C0)的值。我无法弄清楚如何连接3位。在执行逻辑操作时,我还使用' - '作为不关心位。此外,由于我没有使用3个控制选择,Mode(m)感觉多余。因此忽略代码的某些部分,因为它们没用。

我在最后附上了一张图片,说明了预期的内容。

CODE

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity codeALU is
    Port (  A : in  STD_LOGIC_VECTOR (3 downto 0);
           B : in  STD_LOGIC_VECTOR (3 downto 0);
           Cin : in  STD_LOGIC;
          --S0 : in  STD_LOGIC;
           --S1 : in  STD_LOGIC;
              Sel : in STD_LOGIC_VECTOR (2 downto 0);
           M : in  STD_LOGIC;
           Cout : out  STD_LOGIC;
              Z : out STD_LOGIC;
           F : out  STD_LOGIC_VECTOR (3 downto 0));
end codeALU;

architecture Behavioral of codeALU is
begin

process(A, B, M, Cin, Sel)

    --variable X : STD_LOGIC_VECTOR (1 downto 0);
    --variable Y : STD_LOGIC_VECTOR (2 downto 0);
    variable temp : STD_LOGIC_VECTOR (4 downto 0);
    variable Fx : STD_LOGIC_VECTOR (3 downto 0);
    variable Cx, Zx : STD_LOGIC;

begin
    --X := S1 & S0;
    --Y := S1 & S0 & Cin;
        Cx := '0';
        Zx := '0';
    if M = '0' then
        Z <= '0';
        case Sel is
            when "00-" => 
                Fx :=  A AND B;
                Zx := '0';
            when "01-" =>
                Fx :=  A XOR B;
            when "10-" =>
                Fx :=  A OR B;
            when "11-" => 
                Fx :=  A XNOR B;
            when others =>
                null;
        end case;
    elsif M = '1' then 
        case Sel is
            when "000" =>
                temp := (B(3)&B(3 downto 1) + ('0'&A));
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "001" =>
                temp := (A(3)&A(3 downto 1) + ('0'&B));
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "010" =>
                temp := ('0'&A) + ('0'&B);
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "011" =>
                temp := ('0'&A) + ('0'&B) + ('0'&Cin);
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "100" =>
                temp := ('0'&A) + (not B);
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "101" =>
                temp := (not B) + ('0'&A) + 1;
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "110" =>
                temp := ('0'&A) + ('0'&B(3 downto 1));
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when "111" =>
                temp := ('0'&B) + ('0'&A(3 downto 1));
                Fx := temp(3 downto 0);
                Cx := temp(4);
            when others => 
                null;
        end case;

        for i in 0 to 3 loop
            Zx := Zx or Fx(i);
        end loop;
            Z <= not Zx;
    else null;

    end if;
        F <= Fx;
        Cout <= Cx;
end process;

end Behavioral;

TEST BENCH

![LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY test2ALU IS
END test2ALU;

ARCHITECTURE behavior OF test2ALU IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT codeALU
    PORT(
         A : IN  std_logic_vector(3 downto 0);
         B : IN  std_logic_vector(3 downto 0);
         Cin : IN  std_logic;
         Sel : IN  std_logic_vector(2 downto 0);
         M : IN  std_logic;
         Cout : OUT  std_logic;
         Z : OUT  std_logic;
         F : OUT  std_logic_vector(3 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal A : std_logic_vector(3 downto 0) := (others => '0');
   signal B : std_logic_vector(3 downto 0) := (others => '0');
   signal Cin : std_logic := '0';
   signal Sel : std_logic_vector(2 downto 0) := (others => '0');
   signal M : std_logic := '0';

    --Outputs
   signal Cout : std_logic;
   signal Z : std_logic;
   signal F : std_logic_vector(3 downto 0);


BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: codeALU PORT MAP (
          A => A,
          B => B,
          Cin => Cin,
          Sel => Sel,
          M => M,
          Cout => Cout,
          Z => Z,
          F => F
        );


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for 100 ns;  
        A <= "1001";
        B <= "1111";

        M <= '0';
        wait for 50 ns;
        Sel <= "00-";
        wait for 50 ns;
        Sel <= "01-";
        wait for 50 ns;
        Sel <= "10-";
        wait for 50 ns;
        Sel <= "11-";
        wait for 50 ns;

        M <= '1';
        Sel <= "000";
        wait for 50 ns;
        Sel <= "001";
        wait for 50 ns;
        Sel <= "010";
        wait for 50 ns;
        Sel <= "011";
        wait for 50 ns;
        Sel <= "100";
        wait for 50 ns;
        Sel <= "101";
        wait for 50 ns;
        Sel <= "110";
        wait for 50 ns;
        Sel <= "111";

      -- insert stimulus here 

      wait;
   end process;

END;][1]

enter image description here

Assignment statement

1 个答案:

答案 0 :(得分:1)

您尝试使用XY(以及您注释掉的)是一种非常合理的方式来连接您的选择。问题是不关心。普通的case声明不会像你期望的那样处理不关心的事情(即它不会像对待它们那样匹配它们 - 它将它们作为一种独特的方式处理它们std_logic值与其他所有值相同)。如果您有支持VHDL-2008的工具,则可以使用case? 按照您想要的方式匹配不在乎的值。您甚至可以将M连接到您的选择中并稍微缩短您的代码。像:

process (all)
  variable sel : std_logic_vector(3 downto 0);
begin
  sel := M & S1 & S0 & Cin;
  case? sel is
    when "000-" =>
      Fx :=  A and B;
    when "001-" =>
      Fx :=  A or B;

    ...

    when "1000" =>

    ...

(请注意,我在这里使用sel作为内部变量而不是端口。)

如果无法使用VHDL-2008,则必须适当地嵌套if / case语句。提示:您可以在案例陈述中使用sel切片,因此如果Cin始终是M = '0'的关注点,您可以执行以下操作:

process (M, S0, S1, Cin, A, B)
  variable sel : std_logic_vector(2 downto 0);
begin
  sel := S1 & S0 & Cin;
  if M = '0' then
    case sel(2 downto 1) is   -- Cin is don't-care
      when "00" =>
        Fx := A and B;
      when "01" =>
        Fx := A or B;

      ...
  else
    case sel is   -- all control bits are significant
      when "000" =>

      ...

正如Paebbels指出的那样,为您提供更好的解决方案或许只是明确地给出了多个选择,尽管这对于拥有更多控制位的设计来说可能会变得乏味。