|
-- Copyright (c) 2013 Malte Graeper (mgraep@t-online.de) All rights reserved.
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Title : Carry lookahead adder library
|
-- Carry lookahead adder library
|
-- Project :
|
-- provides all functions for making carry lookahead adder of
|
-------------------------------------------------------------------------------
|
|
-- File : cla.vhd
|
|
-- Author : Malte Graeper <malte@T430u>
|
|
-- Company :
|
|
-- Created : 2013-11-10
|
|
-- Last update: 2014-06-29
|
|
-- Platform :
|
|
-- Standard : VHDL'93/02
|
|
-------------------------------------------------------------------------------
|
|
-- Description: provides all functions for making carry lookahead adder of
|
|
-- arbitary deepth and width
|
-- arbitary deepth and width
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
-- Copyright (c) 2013
|
|
-------------------------------------------------------------------------------
|
|
-- Revisions :
|
|
-- Date Version Author Description
|
|
-- 2013-11-10 1.0 Malte Graeper Created
|
|
-------------------------------------------------------------------------------
|
|
|
|
library IEEE;
|
library IEEE;
|
use IEEE.std_logic_1164.all;
|
use IEEE.std_logic_1164.all;
|
use IEEE.numeric_std.all;
|
use IEEE.numeric_std.all;
|
|
|
package cla_p is
|
package cla_p is
|
|
|
type cla_group_t is record
|
type cla_group_t is record
|
pro : std_ulogic;
|
pro : std_ulogic;
|
gen : std_ulogic;
|
gen : std_ulogic;
|
end record;
|
end record;
|
|
|
type cla_level_t is array (natural range <>) of cla_group_t;
|
type cla_level_t is array (natural range <>) of cla_group_t;
|
|
|
function CLAGroupMk (
|
function CLAGroupMk (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned)
|
b : unsigned)
|
return cla_group_t;
|
return cla_group_t;
|
|
|
function CLAGroupMk (
|
function CLAGroupMk (
|
level : cla_level_t)
|
level : cla_level_t)
|
return cla_group_t;
|
return cla_group_t;
|
|
|
function CLALevelMk (
|
function CLALevelMk (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned;
|
b : unsigned;
|
group_size : natural)
|
group_size : natural)
|
return cla_level_t;
|
return cla_level_t;
|
|
|
function CLALevelMk (
|
function CLALevelMk (
|
level : cla_level_t;
|
level : cla_level_t;
|
group_size : natural)
|
group_size : natural)
|
return cla_level_t;
|
return cla_level_t;
|
|
|
-- purpose: propagates carry through groups and returns expanded carry vector
|
-- purpose: propagates carry through groups and returns expanded carry vector
|
function CLAExpandCy (
|
function CLAExpandCy (
|
level : cla_level_t;
|
level : cla_level_t;
|
cy_in : std_ulogic)
|
cy_in : std_ulogic)
|
return std_ulogic_vector;
|
return std_ulogic_vector;
|
|
|
function CLAExpandCy (
|
function CLAExpandCy (
|
level : cla_level_t;
|
level : cla_level_t;
|
cy_in : std_ulogic_vector)
|
cy_in : std_ulogic_vector)
|
return std_ulogic_vector;
|
return std_ulogic_vector;
|
|
|
-- purpose: adds vector a and b with using carry information from groups
|
-- purpose: adds vector a and b with using carry information from groups
|
function CLAParallelAdd (
|
function CLAParallelAdd (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned;
|
b : unsigned;
|
cy_in : std_ulogic_vector)
|
cy_in : std_ulogic_vector)
|
return unsigned;
|
return unsigned;
|
|
|
end cla_p;
|
end cla_p;
|
|
|
package body cla_p is
|
package body cla_p is
|
|
|
function min(
|
function min(
|
a : natural;
|
a : natural;
|
b : natural)
|
b : natural)
|
return natural is
|
return natural is
|
begin
|
begin
|
if a > b then
|
if a > b then
|
return b;
|
return b;
|
else
|
else
|
return a;
|
return a;
|
end if;
|
end if;
|
end min;
|
end min;
|
|
|
function CLAGroupMk (
|
function CLAGroupMk (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned)
|
b : unsigned)
|
return cla_group_t is
|
return cla_group_t is
|
|
|
variable gen : std_ulogic;
|
variable gen : std_ulogic;
|
variable pro : std_ulogic;
|
variable pro : std_ulogic;
|
begin
|
begin
|
gen := '0';
|
gen := '0';
|
pro := '1';
|
pro := '1';
|
for i in a'length-1 downto 0 loop
|
for i in a'length-1 downto 0 loop
|
gen := (a(i) and b(i) and pro) or gen;
|
gen := (a(i) and b(i) and pro) or gen;
|
pro := (a(i) or b(i)) and pro;
|
pro := (a(i) or b(i)) and pro;
|
end loop;
|
end loop;
|
return (pro,gen);
|
return (pro,gen);
|
end CLAGroupMk;
|
end CLAGroupMk;
|
|
|
function CLAGroupMk (
|
function CLAGroupMk (
|
level : cla_level_t)
|
level : cla_level_t)
|
return cla_group_t is
|
return cla_group_t is
|
|
|
variable gen : std_ulogic;
|
variable gen : std_ulogic;
|
variable pro : std_ulogic;
|
variable pro : std_ulogic;
|
begin
|
begin
|
gen := '0';
|
gen := '0';
|
pro := '1';
|
pro := '1';
|
for i in level'length-1 downto 0 loop
|
for i in level'length-1 downto 0 loop
|
-- calc propagate/generate
|
-- calc propagate/generate
|
gen := (level(i).gen and pro) or gen;
|
gen := (level(i).gen and pro) or gen;
|
pro := level(i).pro and pro;
|
pro := level(i).pro and pro;
|
end loop;
|
end loop;
|
return (pro,gen);
|
return (pro,gen);
|
end CLAGroupMk;
|
end CLAGroupMk;
|
|
|
function CLALevelMk (
|
function CLALevelMk (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned;
|
b : unsigned;
|
group_size : natural)
|
group_size : natural)
|
return cla_level_t is
|
return cla_level_t is
|
|
|
variable lb,ub : natural;
|
variable lb,ub : natural;
|
variable slice_a,slice_b : unsigned(group_size-1 downto 0);
|
variable slice_a,slice_b : unsigned(group_size-1 downto 0);
|
variable level : cla_level_t((a'length-1)/group_size downto 0);
|
variable level : cla_level_t((a'length-1)/group_size downto 0);
|
begin
|
begin
|
for i in 0 to (a'length-1)/group_size loop
|
for i in 0 to (a'length-1)/group_size loop
|
lb := i*group_size;
|
lb := i*group_size;
|
ub := min(lb+group_size,a'length)-1;
|
ub := min(lb+group_size,a'length)-1;
|
slice_a(ub-lb downto 0) := a(ub downto lb);
|
slice_a(ub-lb downto 0) := a(ub downto lb);
|
slice_b(ub-lb downto 0) := b(ub downto lb);
|
slice_b(ub-lb downto 0) := b(ub downto lb);
|
level(i) := CLAGroupMk(slice_a(ub-lb downto 0),slice_b(ub-lb downto 0));
|
level(i) := CLAGroupMk(slice_a(ub-lb downto 0),slice_b(ub-lb downto 0));
|
end loop;
|
end loop;
|
|
|
--level(0) := CLAGroupMk(a(min(gsize,a'length-gsize)-1 downto 0),b(gsize-1 downto 0));
|
--level(0) := CLAGroupMk(a(min(gsize,a'length-gsize)-1 downto 0),b(gsize-1 downto 0));
|
|
|
-- recursive call
|
-- recursive call
|
--if level'length > 0 then
|
--if level'length > 0 then
|
-- level(level'length-1 downto 1) := CLALevelMk(a(a'length-1 downto gsize),b(b'length-1 downto gsize),gsize);
|
-- level(level'length-1 downto 1) := CLALevelMk(a(a'length-1 downto gsize),b(b'length-1 downto gsize),gsize);
|
--end if;
|
--end if;
|
|
|
return level;
|
return level;
|
end CLALevelMk;
|
end CLALevelMk;
|
|
|
function CLALevelMk (
|
function CLALevelMk (
|
level : cla_level_t;
|
level : cla_level_t;
|
group_size : natural)
|
group_size : natural)
|
return cla_level_t is
|
return cla_level_t is
|
|
|
variable lb,ub : natural;
|
variable lb,ub : natural;
|
variable slice : cla_level_t(group_size-1 downto 0);
|
variable slice : cla_level_t(group_size-1 downto 0);
|
variable level_out : cla_level_t((level'length-1)/group_size downto 0);
|
variable level_out : cla_level_t((level'length-1)/group_size downto 0);
|
begin
|
begin
|
for i in 0 to (level'length-1)/group_size loop
|
for i in 0 to (level'length-1)/group_size loop
|
lb := i*group_size;
|
lb := i*group_size;
|
ub := min(lb+group_size,level'length)-1;
|
ub := min(lb+group_size,level'length)-1;
|
slice(ub-lb downto 0) := level(ub downto lb);
|
slice(ub-lb downto 0) := level(ub downto lb);
|
level_out(i) := CLAGroupMk(slice(ub-lb downto 0));
|
level_out(i) := CLAGroupMk(slice(ub-lb downto 0));
|
end loop;
|
end loop;
|
return level_out;
|
return level_out;
|
end CLALevelMk;
|
end CLALevelMk;
|
|
|
-- purpose: propagates carry through group and returns expanded carry vector
|
-- purpose: propagates carry through group and returns expanded carry vector
|
function CLAExpandCy (
|
function CLAExpandCy (
|
level : cla_level_t;
|
level : cla_level_t;
|
cy_in : std_ulogic)
|
cy_in : std_ulogic)
|
return std_ulogic_vector is
|
return std_ulogic_vector is
|
|
|
variable cy : std_ulogic;
|
variable cy : std_ulogic;
|
variable cy_out : std_ulogic_vector(level'length downto 0);
|
variable cy_out : std_ulogic_vector(level'length downto 0);
|
begin -- CLAExpandCy
|
begin -- CLAExpandCy
|
cy := cy_in;
|
cy := cy_in;
|
cy_out(0) := cy;
|
cy_out(0) := cy;
|
for i in 0 to level'length-1 loop
|
for i in 0 to level'length-1 loop
|
cy := level(i).gen or (level(i).pro and cy);
|
cy := level(i).gen or (level(i).pro and cy);
|
cy_out(i+1) := cy;
|
cy_out(i+1) := cy;
|
end loop; -- i
|
end loop; -- i
|
return cy_out;
|
return cy_out;
|
end CLAExpandCy;
|
end CLAExpandCy;
|
|
|
-- purpose: propagates carry through each group (maybe more than one) and returns expanded carry vector
|
-- purpose: propagates carry through each group (maybe more than one) and returns expanded carry vector
|
function CLAExpandCy (
|
function CLAExpandCy (
|
level : cla_level_t;
|
level : cla_level_t;
|
cy_in : std_ulogic_vector)
|
cy_in : std_ulogic_vector)
|
return std_ulogic_vector is
|
return std_ulogic_vector is
|
|
|
constant group_size : natural := 1+(level'length-1)/(cy_in'length-1); -- length cy_in = number of groups+1
|
constant group_size : natural := 1+(level'length-1)/(cy_in'length-1); -- length cy_in = number of groups+1
|
variable ub,lb : natural;
|
variable ub,lb : natural;
|
variable slice : cla_level_t(group_size-1 downto 0);
|
variable slice : cla_level_t(group_size-1 downto 0);
|
variable cy_out : std_ulogic_vector(level'length downto 0);
|
variable cy_out : std_ulogic_vector(level'length downto 0);
|
begin -- CLAExpandCy
|
begin -- CLAExpandCy
|
cy_out(cy_out'length-1) := cy_in(cy_in'length-1);
|
cy_out(cy_out'length-1) := cy_in(cy_in'length-1);
|
for i in 0 to (level'length-1)/group_size loop
|
for i in 0 to (level'length-1)/group_size loop
|
lb := i*group_size;
|
lb := i*group_size;
|
ub := min(lb+group_size,level'length)-1;
|
ub := min(lb+group_size,level'length)-1;
|
slice(ub-lb downto 0) := level(ub downto lb);
|
slice(ub-lb downto 0) := level(ub downto lb);
|
cy_out(ub downto lb) := CLAExpandCy(slice(ub-lb downto 0),cy_in(i))(ub-lb downto 0);
|
cy_out(ub downto lb) := CLAExpandCy(slice(ub-lb downto 0),cy_in(i))(ub-lb downto 0);
|
end loop;
|
end loop;
|
return cy_out;
|
return cy_out;
|
end CLAExpandCy;
|
end CLAExpandCy;
|
|
|
-- purpose: adds vector a and b with using carry information from groups
|
-- purpose: adds vector a and b with using carry information from groups
|
function CLAParallelAdd (
|
function CLAParallelAdd (
|
a : unsigned;
|
a : unsigned;
|
b : unsigned;
|
b : unsigned;
|
cy_in : std_ulogic_vector)
|
cy_in : std_ulogic_vector)
|
return unsigned is
|
return unsigned is
|
|
|
constant adder_size : integer := 1+(a'length-1)/(cy_in'length-1);
|
constant adder_size : integer := 1+(a'length-1)/(cy_in'length-1);
|
variable lb,ub : natural;
|
variable lb,ub : natural;
|
variable result : unsigned(a'length-1 downto 0);
|
variable result : unsigned(a'length-1 downto 0);
|
variable cy_vec : std_ulogic_vector(adder_size-1 downto 0) := (others => '0');
|
variable cy_vec : std_ulogic_vector(adder_size-1 downto 0) := (others => '0');
|
begin -- CLAParallelAdd
|
begin -- CLAParallelAdd
|
result := to_unsigned(0,result'length);
|
result := to_unsigned(0,result'length);
|
|
|
for i in 0 to (a'length-1)/adder_size loop
|
for i in 0 to (a'length-1)/adder_size loop
|
lb := i*adder_size;
|
lb := i*adder_size;
|
ub := min(lb+adder_size,a'length)-1;
|
ub := min(lb+adder_size,a'length)-1;
|
cy_vec(0) := cy_in(i);
|
cy_vec(0) := cy_in(i);
|
result(ub downto lb) := a(ub downto lb)+b(ub downto lb)+unsigned(cy_vec(ub-lb downto 0));
|
result(ub downto lb) := a(ub downto lb)+b(ub downto lb)+unsigned(cy_vec(ub-lb downto 0));
|
end loop; -- i
|
end loop; -- i
|
return result;
|
return result;
|
end CLAParallelAdd;
|
end CLAParallelAdd;
|
|
|
end package body cla_p;
|
end package body cla_p;
|
|
|