bzrk89
bzrk89

Reputation: 55

How to concatenate 3 operation select bits in a 4-bit ALU design - VHDL

So I have been working on this assignment and it requires me to design a 4-bit ALU being controlled by a couple of bits(namely S1, S0, Cin/C0(carry in) and M) Depending on the value of M the ALU will perform either logical or Arithmetic operations. I have temporarily designed an ALU which works with an input named 'Sel' while I figure out how to take the values of the 3 diff inputs(S0, S1, Cin/C0). I cannot figure out how to concatenate the 3 bits. I have also used '-' for dont care bits while performing logical operations. Also since I haven't used the 3 control selects, Mode (m) feels redundant. So ignore some parts of the code since they aren't useful.

I have attached an image at the end which explains what is expected.

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

Upvotes: 0

Views: 2830

Answers (1)

fru1tbat
fru1tbat

Reputation: 1625

What you tried to do with X and Y (and which you commented out) is a perfectly reasonable way of concatenating your selects. The problem is the don't-cares. The ordinary case statement does not handle don't-cares the way you're expecting (i.e. it doesn't match against them as if they can be anything - it handles them as a unique std_logic value same as everything else). If you have tools that support VHDL-2008, you can use case?, which does match against don't-care values the way you want. You could even concatenate M into your select as well and shorten your code a bit. Like:

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" =>

    ...

(Note that I'm using sel here as an internal variable instead of a port.)

If you can't use VHDL-2008, you will have to nest your if/case statements appropriately. Hint: you can use a slice of sel in a case statement, so if Cin is always a don't-care for M = '0', you can do something like:

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" =>

      ...

As Paebbels pointed out, a better solution for you perhaps would be just to explicitly give multiple choices where there's a don't-care, though that may get tedious for designs with more control bits.

Upvotes: 1

Related Questions