![]() |
|
![]() |
|
Answers Database
FPGA Express: Implementing efficient multipliers in VHDL or Verilog
Record #4949
Product Family: Software --save this file as multiply.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; use work.my_arith.all; -- refers to the package listed in Solution 2 entity multiply is
port(a : in std_logic_vector(20 downto 0); --<- Change these bounds
b : in std_logic_vector(13 downto 0); --<- to change the size
prod : out std_logic_vector(34 downto 0)); --<- of the multiplier
end multiply;
architecture nice of multiply is
begin
prod <= my_mult(a, b); -- multiply "a" and "b" to produce "prod"
end nice;
For VHDL designs, the my_mult function can be used in any file as shown above. For Verilog designs, instantiate "multiply" to call the function as follows: multiply U1 (.a(x), .b(y), .prod(z)); NOTE: In a sequential block (VHDL `process' or Verilog `always'), perform an assignment from a temporary signal, then instantiate the multiplier outside the sequential block in such a way that the temporary signal is the output of the multiplier instantiation. Example: always@(posedge clk) QOUT <= TEMP; multiply U1 (.a(X), .b(Y), .prod(TEMP)); Solution 2: -- save this file as mult_package.vhd ---------------------------------------------------------------------------- -- -- Copyright (c) 1998 by Synopsys, Inc. All rights reserved. -- -- This source file may be used and distributed without restriction -- provided that this copyright statement is not removed from the file -- and that any derivative work contains this copyright notice. -- -- Package name: my_arith -- -- Purpose: This package defines a more efficient implementation -- for the multiplication operator-- ---- Algorithm: -- loop: Pi = (Yi==1) ? Xi : 0 -- loop: Qi = P(2i) + P(2i+1)<<1 -- loop: Ri = Q(2i) + Q(2i+1)<<2 -- If T'length > 7 -- loop: Ti = R(2i) + R(2i+1)<<4 -- loop: Q += Ti<<(8i) -- else -- loop: Q += Ri<<(4i) -- end if -- -- Notes: Partial products Qi's ccomputed in parallel -- Partial products Ri's ccomputed in parallel-- Partial products Ti's (if apply) ccomputed in parallel -- ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; package my_arith is function my_mult(S, L: std_logic_vector) return std_logic_vector; end my_arith; package body my_arith is function largest(X, Y: INTEGER) return INTEGER is begin if X > Y then return X; else return Y; end if; end; function smallest(X, Y: INTEGER) return INTEGER is begin if X < Y then return X; else return Y; end if; end; function my_mult(S, L: std_logic_vector) return std_logic_vector is constant lS : integer := smallest(S'length, L'length); constant lL : integer := largest(S'length, L'length); -- Number of intermediate products P, Q, R constant nP : integer := lS; constant nQ : integer := (nP+1)/2; constant nR : integer := (nQ+1)/2; constant nT : integer := (nR+1)/2; -- Length of P, Q, R, and final result constant lP : integer := Ll; constant lQ : integer := lP+2; constant lR : integer := lQ+3; constant lT : integer := lR+5; constant n : integer := lS+lP; type Pi_type is array(nP-1 downto 0) of std_logic_vector(lP-1 downto 0); type Qi_type is array(nQ-1 downto 0) of std_logic_vector(lQ-1 downto 0); type Ri_type is array(nR-1 downto 0) of std_logic_vector(lR-1 downto 0); type Ti_type is array(nT-1 downto 0) of std_logic_vector(lT-1 downto 0); variable P : Pi_type; variable Q : Qi_type; variable R : Ri_type; variable T : Ti_type; variable result: std_logic_vector(n-1 downto 0); variable Small : std_logic_vector(ls-1 downto 0); variable Large : std_logic_vector(Ll-1 downto 0); begin if (S'length < L'length) then Small := S; Large := L; else Small := L; Large := S; end if; -- Compute Pi's for i in 0 to nP-1 loop if (Small(i) = '0') then P(i) := (others => '0'); else P(i) := Large; end if; end loop; -- Compute Qi's for i in 0 to nP/2-1 loop Q(i) := (EXT(P(2*i)(lP-1 downto 1),lQ-1) + EXT(P(2*i+1),lQ-1)) & P(2*i)(0); end loop; if (nP mod 2) = 1 then Q(nQ-1) := EXT(P(nP-1), lQ); end if; -- Compute Ri's for i in 0 to nQ/2-1 loop R(i):=(EXT(Q(2*i)(lQ-1 downto 2),lR-2) + EXT(Q(2*i+1),lR-2)) & Q(2*i) (1 downto 0); end loop; if (nQ mod 2) = 1 then R(nR-1) := EXT(Q(nQ-1), lR); end if; if (lS >= 8) then -- Compute Ti's for i in 0 to nR/2-1 loop T(i) := (EXT(R(2*i)(lR-1 downto 4),lT-4) + EXT(R(2*i+1),lT-4)) & R(2*i)(3 downto 0); end loop; if (nR mod 2) = 1 then T(nT-1) := EXT(R(nR-1), lT); end if; -- Compute final product result := EXT(T(0), n); for i in 1 to nT-1 loop -- skip i=0 result := result + (EXT(T(i) & EXT("0", 8*i), n)); end loop; else -- Compute final product result := EXT(R(0), n); for i in 1 to nR-1 loop -- skip i=0 result := result + (EXT(R(i) & EXT("0", 4*i), n)); end loop; end if; return result; end; end my_arith; End of Record #4949 - Last Modified: 05/10/99 15:39 |
| For the latest news, design tips, and patch information on the Xilinx design environment, check out the Technical Tips! |