Search code examples
vhdlfpga

RTL Hardware Design Using VHDL, Example 7.1


7.1 - Consider an Arithmetic Circuit that can perform four operations: a+b, a-b, a+1 and a-1, where a and b are 16-bit Unsigned Numbers and the desired operation is specified by a 2-bit Control Signal, ctrl.

Is it possible to design this circuit just with one adder without using sequential logic.

I designed this circuit with 2's complementary logic but i cannot add logic (a + (not b) + 1) just one adder without memory components

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;

    entity Ex_7_1_b is
         generic( BUS_WIDTH : integer := 16 );
        port ( a : in  STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
               b : in  STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
               ctrl : in  STD_LOGIC_VECTOR (1 downto 0);
               y : out  STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0)
                );
    end Ex_7_1_b;

    architecture Behavioral of Ex_7_1_b is
        signal adder : unsigned(BUS_WIDTH - 1 downto 0);
        signal mux_sign : unsigned(BUS_WIDTH - 1 downto 0);
        signal mux_inp_sel : unsigned(BUS_WIDTH - 1 downto 0);
        signal mux_val : unsigned(BUS_WIDTH - 1 downto 0);
        signal result : unsigned(BUS_WIDTH - 1 downto 0);
    begin
        mux_val <= to_unsigned(0, mux_val'length) when ctrl(1) = '1' else to_unsigned(1, mux_val'length);
        mux_inp_sel <= mux_val when ctrl(0) = '1' else unsigned(b);
        mux_sign <= not (mux_inp_sel) when ctrl(1) = '1' else mux_inp_sel;

        result <= unsigned(a) + mux_sign;
        y <= std_logic_vector(result);

    end Behavioral;

Solution

  • The solution you found yourself is fine but it uses a 17-bits adder instead of a 16-bits one. With smart enough synthesizers it should not make any difference. Just for completeness here is another, 16-bits (and slightly simpler), solution:

    architecture RTL of Ex_7_1_b is
        signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
    begin
        x   <= unsigned(i_a);
        y0  <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
        y1  <= not y0 when i_ctrl(0) = '1' else y0;
        o_y <= std_logic_vector(x + y1 + i_ctrl(0));
    end architecture RTL;
    

    Note: this works only in VHDL 2008 where the addition of an unsigned and a std_logic is defined. If you must use an older version of the VHDL standard use the following, instead:

    architecture RTL of Ex_7_1_b is
        signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
        signal c: natural range 0 to 1;
    begin
        x   <= unsigned(i_a);
        y0  <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
        y1  <= not y0 when i_ctrl(0) = '1' else y0;
        c   <= 1 when i_ctrl(0) = '1' else 0;
        o_y <= std_logic_vector(x + y1 + c);
    end architecture RTL;