UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 4949

FPGA Express: Implementing efficient multipliers in VHDL or Verilog

Description

Keywords: Express, mult, multiply, VHDL, Verilog, Foundation Express

Urgency: Hot

General Description:
FPGA Express uses specific Xilinx features for arithmetic functions when
implementing designs. However, multiplier implementations are not optimal for
performance (Virtex excepted). These results have been greatly improved
with v3.2 of FPGA Express, so this solution should be applied when using
Express v3.1 and earlier.

Use the following VHDL package containing a multiplier function to implement
much more efficient multipliers for XC4000 and Spartan architectures.

解决方案

1

Copy the VHDL code listed in Solution 2 to a VHDL file called mult_package.vhd.
Analyze this package file in your Express project first, before your design
files. Or, create a new library and add this package file to that library.

Then, refer to this package in the library declaration portion of your VHDL
code. The name of the package is "my_arith" and the library will be "work"
unless you have created your own. Then, call the "my_mult" function within
VHDL code using the following code. Copy the following code to a file called
multiply.vhd and add this to your Express project.


--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));

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
--
-- Author: Ramine Roane (rroane@synopsys.com)
--
-- 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;
AR# 4949
创建日期 10/30/1998
Last Updated 08/11/2003
状态 Archive
Type 综合文章