====== Example of a Multiplier ====== ===== Introduction ===== {{:courses:system_design:synthesis:combinational_logic:folie274_multiplierblockdiagram.svg?nolink&300|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. ===== Mutliplier: Function Table ===== ^ 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. ===== Multiplier Minterms - Karnaugh Diagram ===== {{:courses:system_design:synthesis:combinational_logic:folie276_karnaughdiagram.svg?nolink&500|Karnaugh Diagram}} {{:courses:system_design:synthesis:combinational_logic:folie276_multiplierminiterms.svg?nolink&400|Multiplier Miniterms}} === Notes === The function table of this 2x2 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. ===== Multiplier: VHDL Code using the Function Tables ===== 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”; ... when “1100” => (C3,C2,C1,C0) <= “0000”; when “1101” => (C3,C2,C1,C0) <= “0011”; when “1110” => (C3,C2,C1,C0) <= “0110”; when “1111” => (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. ===== Multiplier: VHDL Code using Minterm Functions ===== 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. ===== Multiplier: Integer Realization ===== 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.