courses:system_design:synthesis:combinational_logic:example_of_a_multiplier

Example of a Multiplier

Multiplier Block Diagram

  • 2 x 2 bit multiplier
    • Inputs: A1, A0, B1, B0 : 2 bit
    • Outputs: C3, C2, C1, C0 : 4 bit
entity MULTIPLIER is 
 port (A0  : in  bit;
       A1  : in  bit;
       B0  : in  bit;
       B1  : in  bit;
       C0  : out bit;
       C1  : out bit;
       C2  : out bit;
       C3  : out bit);
end MULTIPLIER;
  • 3 different VHDL implementations
    • Function table
    • Synthesis “by hand” (boolean functions for the outputs)
    • Use of VHDL integer types and operators

Notes

Different VHDL coding styles shall be demonstrated with a simple module that has to calculate the result of the multiplication of two 2-bit numbers. The maximum value of each input is 3, i.e. the maximum output value is 9 which needs 4 bits in a binary code.

Therefore, four input ports and four output ports of data type ’bit’ are required.

The same entity shall be used for all different implementations.

a1 a0 b1 b0 c3 c2 c1 c0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0
0 0 1 1 0 0 0 0
0 1 0 0 0 0 0 0
0 1 0 1 0 0 0 1
0 1 1 0 0 0 1 0
0 1 1 1 0 0 1 1
1 0 0 0 0 0 0 0
1 0 0 1 0 0 1 0
1 0 1 0 0 1 0 0
1 0 1 1 0 1 1 0
1 1 0 0 0 0 0 0
1 1 0 1 0 0 1 1
1 1 1 0 0 1 1 0
1 1 1 1 1 0 0 1

Notes

The most direct approach is via the function table of the multiplications. The behavior of a combinational logic block is completely defined by listing the result for all possible input values. Of course, the function table is usually no the most compact representation.

Karnaugh Diagram

Multiplier Miniterms

Notes

The function table of this 2×2 bit multiplier leads directly to the four Karnaugh diagrams of the output signals.

The bars on the side of the squares indicate those regions where the corresponding input bit is ’1’.

All ’1’s of the output signals are marked in the corresponding diagrams. By combining adjacent ’1’s, the minimal output function can be derived.

architecture RTL_TABLE of MULTIPLIER is 
  signal A_B : bit_vector ( 3 downto 0);
begin
  A_B <= A1 & A0 & B1 & B0;
  MULTIPLY : process (A_B)
  begin
   case A_B is 
    when “0000” => (C3,C2,C1,C0) <= “0000”;
    when “0001” => (C3,C2,C1,C0) <= “0000”;
    when “0010” => (C3,C2,C1,C0) <= “0000”;
    when “0011” => (C3,C2,C1,C0) <= “0000”;
    when “0100” => (C3,C2,C1,C0) <= “0000”;
    when “0101” => (C3,C2,C1,C0) <= “0001”;
    when “0110” => (C3,C2,C1,C0) <= “0010”;
    when “0111” => (C3,C2,C1,C0) <= “0011”;
   ...
    when1100=> (C3,C2,C1,C0) <= “0000”;
    when1101=> (C3,C2,C1,C0) <= “0011”;
    when1110=> (C3,C2,C1,C0) <= “0110”;
    when1111=> (C3,C2,C1,C0) <=1001;
  end case;
 end process MULTIPLY;
end RTL_TABLE;
  • An internal signal is used that combines all input signals
  • The internal signal is generated concurrently, i.e. it is updated whenever the input changes
  • The function table is realized as case statement and thus has to placed within a process. The internal signal is the only signal that controls the behavior.

Notes

The conversion of the function table into VHDL is straight forward. An intermediate signal is used to combine the four input signals which facilitates the coding. Every row is represented by a different signal value, now. As all possibilities are covered in the table, a case structure can be used for the implementation.

architecture RTL_MINTERM of MULTIPLIER is
begin
 
  C0 <= A0 and B0;
 
  C1 <= (A0 and not A1 and B1) or 
        (A0 and not B0 and B1) or
        (not A0 and A1 and B0) or
        (A0 and B0 and not B1);
 
  C2 <= (A1 and B1 and not B0) or 
        (A1 and not A0 and B1);
 
  C3 <= A1 and A0 and B1 and B0;
 
end  RTL_MINTERM;
  • The minterm functions are realized directly as concurrent statements

Notes

Because the minterms are rather simple logical functions, they are realized with concurrent statements. This way, it is just a matter of replacing the mathematical symbols with their corresponding VHDL operators.

The minterm realization is very tedious and is performed by the synthesis tool automatically when the function table is parsed.

It is more or less a structural implementation of the algorithm - no synthesis is required.

library IEEE;
use IEEE.NUMERIC_BIT.all;
 
architecture RTL_INTEGER
of MULTIPLIER is 
  signal A_VEC : unsigned (1 downto 0 );
  signal B_VEC : unsigned (1 downto 0 );  
  signal A_INT : integer range 0 to 3;
  signal B_INT : integer range 0 to 3;
  signal C_VEC : unsigned (3 downto 0 );
  signal C_INT : integer range 0 to 9;
begin
 
  A_VEC <= A1 & A0;
  A_INT <= TO_INTEGER(A_VEC);
  B_VEC <= B1 & B0;
  B_INT <= TO_INTEGER(B_VEC);
 
  C_INT <= A_INT * B_INT;
 
  C_VEC <= TO_UNSIGNED(C_INT, 4);
 
  (C3, C2, C1, C0) <= C_VEC;
end RTL_INTEGER;
  • The NUMERIC_BIT package provides all necessary functions to convert bit vector to integer values and vice versa
  • Internal signals are used to generate bit vectors and integer representations of the port signals. The bit vectors shall be treated as unsigned binary values.
  • The signal bit input signals are concatenated to vectors and converted to integer data types
  • the multiplication s realized via the standard VHDL operator
  • The size of the target vector must be specified when converting integers back to bit vectors
  • Finally, the bit vector elements are assigned to the output ports

Notes

The most obvious solution via the multiplication operator ’*’ is not directly applicable because only single bits are provided by the entity.

Thus, bits belonging together are combined in bit vectors which are converted to integer values afterwards. The inverse procedure is necessary to assign the integer result to the output ports.

The most elegant solution is the integer implementation as the function of the code is clearly visible and not hidden in boolean functions or in hardcoded values like in the other examples. The use of ’bit’ type ports, however, is very awkward.

It is better style to use ’unsigned’ bit vectors or ’integer’. Please note that the conversion of the bit vectors to ’integer’ is not necessary as the arithmetic operators, including ’*’ are overloaded in the NUMERIC_BIT package. Vector arithmetic is provided for signed and unsigned binary representations

The synthesis result should be identical in all three cases.


Chapters of System Design > Synthesis > Combinational Logic