1922 lines
49 KiB
VHDL
1922 lines
49 KiB
VHDL
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use ieee.numeric_std.all;
|
|
use ieee.math_real.all;
|
|
use std.textio.all;
|
|
|
|
package body fixed_ja is
|
|
|
|
-------------------------------------------------------------
|
|
-- Local Procedures
|
|
-------------------------------------------------------------
|
|
-- adds 1 to the LSB of the number
|
|
procedure round_up
|
|
(
|
|
src : in ufixed_t;
|
|
result : out ufixed_t;
|
|
overflowx : out BOOLEAN ) is
|
|
|
|
variable srcuns, resuns : UNSIGNED (src'high-src'low+1 downto 0) := (others => '0');
|
|
begin -- round_up
|
|
srcuns (srcuns'high-1 downto 0) := to_unsigned (src);
|
|
resuns := srcuns + 1;
|
|
|
|
result := to_ufixed(resuns(src'high-src'low downto 0), src);
|
|
overflowx := (resuns(resuns'high) = '1');
|
|
|
|
end procedure round_up;
|
|
|
|
-------------------------------------------------------------
|
|
-- adds 1 to the LSB of the number
|
|
procedure round_up
|
|
(
|
|
src : in sfixed_t;
|
|
result : out sfixed_t;
|
|
overflowx : out BOOLEAN ) is
|
|
|
|
variable srcs, ress : SIGNED (src'high-src'low+1 downto 0);
|
|
begin -- round_up
|
|
srcs (srcs'high-1 downto 0) := to_signed (src);
|
|
srcs(srcs'high) := src(src'high); -- sign extend
|
|
ress := srcs + 1;
|
|
|
|
result := to_sfixed(ress (ress'high-1 downto 0), src);
|
|
overflowx := ((src(src'high) /= ress(ress'high-1)) and (or_red (sfixed_t(ress)) /= '0'));
|
|
|
|
end procedure round_up;
|
|
|
|
-------------------------------------------------------------
|
|
-- Local functions
|
|
-------------------------------------------------------------
|
|
-- round_fixed()
|
|
-- function round_fixed
|
|
-- (
|
|
-- src : ufixed_t;
|
|
-- remainder : ufixed_t;
|
|
-- rnd_mode : round_mode_t := default_round_mode
|
|
-- ) return ufixed_t is
|
|
-- variable res : ufixed_t(src'range);
|
|
-- begin
|
|
-- return res;
|
|
--
|
|
-- end round_fixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- function round_fixed
|
|
-- (
|
|
-- src : sfixed_t;
|
|
-- remainder : sfixed_t;
|
|
-- rnd_mode : round_mode_t := default_round_mode
|
|
-- ) return sfixed_t is
|
|
-- variable res : signed(src'length-1 downto 0);
|
|
-- begin
|
|
-- return src;
|
|
--
|
|
-- end round_fixed;
|
|
|
|
-------------------------------------------------------------
|
|
function reshape
|
|
(
|
|
src : ufixed_t;
|
|
proto : ufixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
|
|
variable RemainLow : ufixed_t (proto'low-1 downto src'low) := (others => '0');
|
|
variable RemainHigh : ufixed_t (src'high downto proto'high+1) := (others => '0');
|
|
variable dst, tmp : ufixed_t (proto'high downto proto'low) := (others => '0');
|
|
variable ovf, isTruncLo, isTruncHi : boolean := false;
|
|
begin
|
|
|
|
if proto'high < -1 then
|
|
assert false report "U: reshape: Bad dual point (Upper bound < (-1))" severity error;
|
|
end if;
|
|
|
|
-- Check for high and low truncation
|
|
isTruncLo := (src'low < dst'low);
|
|
isTruncHi := (src'high > dst'high);
|
|
|
|
-- Reshape
|
|
dst := (others => '0');
|
|
dst(min(src'high, dst'high) downto max(src'low, dst'low)) := src(min(src'high, dst'high) downto max(src'low, dst'low));
|
|
tmp := dst;
|
|
|
|
-- Get low remainder
|
|
if isTruncLo then
|
|
RemainLow := src(RemainLow'range);
|
|
end if;
|
|
|
|
-- Get high remainder
|
|
if isTruncHi then
|
|
RemainHigh := src(RemainHigh'range);
|
|
end if;
|
|
|
|
ovf := false;
|
|
|
|
-- Rounding
|
|
if isTruncLo then
|
|
|
|
case rnd_mode is
|
|
|
|
-- Round to positive infinity (round ceiling)
|
|
when round_pos_infinity =>
|
|
if or_red(RemainLow) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
|
|
-- Round Half-up
|
|
-- Round nearest
|
|
when round_half_up | round_nearest =>
|
|
if (RemainLow(RemainLow'high) = '1') then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
|
|
-- Round convergent
|
|
when round_convergent =>
|
|
if RemainLow(RemainLow'high) = '1' then
|
|
if or_red(RemainLow(RemainLow'high-1 downto RemainLow'low)) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
elsif tmp(dst'low) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
end if;
|
|
|
|
-- Round to zero
|
|
when round_to_zero | none => null;
|
|
|
|
when others =>
|
|
assert false report "Reshape(U): Rounding mode (" & round_mode_t'image(rnd_mode) & ") not implemented!" severity error;
|
|
|
|
end case;
|
|
end if;
|
|
|
|
-- Saturating
|
|
if sat_mode = saturate then
|
|
|
|
-- Check overflow
|
|
if isTruncHi then
|
|
ovf := ovf or or_red(RemainHigh) = '1';
|
|
end if;
|
|
|
|
-- Saturate
|
|
if ovf then
|
|
dst := (others => '1');
|
|
end if;
|
|
|
|
end if;
|
|
|
|
return dst;
|
|
|
|
end reshape;
|
|
|
|
-------------------------------------------------------------
|
|
function reshape
|
|
(
|
|
src : ufixed_t;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
|
|
begin
|
|
return reshape(src, uproto(nbits, nbits_int), rnd_mode, sat_mode);
|
|
|
|
end reshape;
|
|
|
|
-------------------------------------------------------------
|
|
function reshape
|
|
(
|
|
src : sfixed_t;
|
|
proto : sfixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
|
|
variable RemainLow : sfixed_t (proto'low-1 downto src'low) := (others => '0');
|
|
variable RemainHigh : sfixed_t (src'high-1 downto proto'high) := (others => '0');
|
|
variable dst, tmp : sfixed_t (proto'high downto proto'low) := (others => '0');
|
|
variable ovf, isTruncLo, isTruncHi : boolean := false;
|
|
variable sign : std_logic;
|
|
begin
|
|
|
|
if proto'high < 0 then
|
|
assert false report "Reshape(S): Bad dual point (Upper bound < (0))" severity error;
|
|
end if;
|
|
|
|
-- Check for high and low truncation
|
|
isTruncLo := (src'low < dst'low);
|
|
isTruncHi := (src'high > dst'high);
|
|
|
|
-- Reshape
|
|
sign := src(src'high);
|
|
dst := (others => '0');
|
|
dst(dst'high downto max(src'low, dst'low)) := (dst'high downto min(src'high, dst'high) => sign) & src(min(src'high, dst'high)-1 downto max(src'low, dst'low));
|
|
tmp := dst;
|
|
|
|
-- Get low remainder
|
|
if isTruncLo then
|
|
RemainLow := src(RemainLow'range);
|
|
end if;
|
|
|
|
-- Get high remainder
|
|
if isTruncHi then
|
|
RemainHigh := src(RemainHigh'range);
|
|
end if;
|
|
|
|
ovf := false;
|
|
|
|
-- Rounding
|
|
if isTruncLo then
|
|
|
|
case rnd_mode is
|
|
|
|
-- Round to positive infinity (round ceiling)
|
|
when round_pos_infinity =>
|
|
round_up(tmp, dst, ovf);
|
|
if ovf then
|
|
dst(dst'high) := '0';
|
|
end if;
|
|
|
|
-- Round Half-up
|
|
when round_half_up =>
|
|
if RemainLow(RemainLow'high) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
|
|
-- Round nearest
|
|
when round_nearest =>
|
|
if RemainLow(RemainLow'high) = '1' then
|
|
if RemainLow'length = 1 then
|
|
if sign = '0' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
elsif sign = '0' or (sign and or_red(RemainLow(RemainLow'high-1 downto RemainLow'low))) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
end if;
|
|
|
|
-- Round convergent
|
|
when round_convergent =>
|
|
if RemainLow(RemainLow'high) = '1' then
|
|
if or_red(RemainLow(RemainLow'high-1 downto RemainLow'low)) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
elsif tmp(dst'low) = '1' then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
end if;
|
|
|
|
-- Round to zero
|
|
when round_to_zero =>
|
|
if (or_red(RemainLow) = '1' and sign = '1') then
|
|
round_up(tmp, dst, ovf);
|
|
end if;
|
|
|
|
-- No Round
|
|
when none =>
|
|
-- Same as RoundToZero but overflow detection is omitted
|
|
dst := tmp + (or_red(RemainLow) and sign);
|
|
|
|
when others =>
|
|
assert false report "Reshape(S): Rounding mode (" & round_mode_t'image(rnd_mode) & ") not implemented!" severity error;
|
|
|
|
end case;
|
|
|
|
-- Check negative zero
|
|
if dst(dst'high) = '1' then
|
|
if or_red(dst(dst'high-1 downto dst'low)) = '0' then
|
|
dst(dst'high) := '0';
|
|
-- assert false report "Reshape(S): -0 detected" severity note;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
-- Saturating
|
|
if sat_mode = saturate then
|
|
|
|
-- Check overflow
|
|
if isTruncHi then
|
|
ovf := ovf or
|
|
(sign = '1' and src(dst'high) = '0' and or_red(tmp(dst'high-1 downto dst'low)) = '1') or
|
|
(sign = '1' and src(dst'high) = '1' and or_red(tmp(dst'high-1 downto dst'low)) = '0') or
|
|
(sign = '0' and or_red(RemainHigh) = '1');
|
|
end if;
|
|
|
|
-- Saturate
|
|
if ovf then
|
|
if (sign = '1') then
|
|
dst := '1' & (dst'high-1 downto dst'low+1 => '0') & '1';
|
|
else
|
|
dst := '0' & (dst'high-1 downto dst'low => '1');
|
|
end if;
|
|
end if;
|
|
|
|
end if;
|
|
|
|
return dst;
|
|
|
|
end reshape;
|
|
|
|
-------------------------------------------------------------
|
|
function reshape
|
|
(
|
|
src : sfixed_t;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
|
|
begin
|
|
return reshape(src, sproto(nbits, nbits_int), rnd_mode, sat_mode);
|
|
|
|
end reshape;
|
|
|
|
-------------------------------------------------------------
|
|
-- Constuctor helpers
|
|
-------------------------------------------------------------
|
|
function uproto (nbits : integer; nbits_int : integer) return ufixed_t is
|
|
constant result : ufixed_t (nbits_int-1 downto nbits_int-nbits) := (others => '0');
|
|
begin
|
|
return result(nbits_int-1 downto nbits_int-nbits);
|
|
end uproto;
|
|
|
|
-------------------------------------------------------------
|
|
function sproto (nbits : integer; nbits_int : integer) return sfixed_t is
|
|
constant result : sfixed_t (nbits_int downto nbits_int-nbits+1) := (others => '0');
|
|
begin
|
|
return result(nbits_int downto nbits_int-nbits+1);
|
|
end sproto;
|
|
|
|
-------------------------------------------------------------
|
|
function uproto (a : ufixed_t; op : character; b : ufixed_t) return ufixed_t is
|
|
constant result : ufixed_t(a'high + b'high + 4 downto a'low + b'low - 4) := (others => '0');
|
|
variable hi, lo : integer := 0;
|
|
|
|
begin
|
|
|
|
case op is
|
|
when '+' =>
|
|
hi := max(a'high, b'high);
|
|
if a'high = b'high then
|
|
hi := hi + 1;
|
|
end if;
|
|
lo := min(a'low, b'low);
|
|
|
|
when '-' =>
|
|
hi := max(a'high, b'high);
|
|
lo := min(a'low, b'low);
|
|
|
|
when '*' =>
|
|
hi := a'high + b'high + 1;
|
|
if (a'high < 0 or b'high < 0) then
|
|
if (hi > -1) then
|
|
hi := hi-1;
|
|
end if;
|
|
end if;
|
|
lo := hi - a'length - b'length + 1;
|
|
|
|
when others => null;
|
|
|
|
end case;
|
|
|
|
return result(hi downto lo);
|
|
end uproto;
|
|
|
|
-------------------------------------------------------------
|
|
function sproto (a : sfixed_t; op : character; b : sfixed_t) return sfixed_t is
|
|
constant result : sfixed_t(a'high + b'high + 4 downto a'low + b'low - 4) := (others => '0');
|
|
variable hi, lo : integer := 0;
|
|
|
|
begin
|
|
|
|
case op is
|
|
when '+' =>
|
|
hi := max(a'high, b'high);
|
|
if a'high = b'high then
|
|
hi := hi + 1;
|
|
end if;
|
|
lo := min(a'low, b'low);
|
|
|
|
when '-' =>
|
|
hi := max(a'high, b'high);
|
|
lo := min(a'low, b'low);
|
|
|
|
when '*' =>
|
|
hi := a'high + b'high;
|
|
if (a'high = 0 or b'high = 0) then
|
|
if (hi > 0) then
|
|
hi := hi-1;
|
|
end if;
|
|
end if;
|
|
lo := hi - a'length - b'length + 1;
|
|
|
|
when others => null;
|
|
|
|
end case;
|
|
|
|
return result(hi downto lo);
|
|
end sproto;
|
|
|
|
-------------------------------------------------------------
|
|
-- Type conversions
|
|
-------------------------------------------------------------
|
|
-- ufixed <= ufixed
|
|
function to_ufixed(src : ufixed_t) return ufixed_t is
|
|
begin
|
|
return to_ufixed(src, src);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= sfixed
|
|
function to_ufixed(src : sfixed_t) return ufixed_t is
|
|
variable dst : ufixed_t(src'range) := (others => '0');
|
|
begin
|
|
dst := ufixed_t(abs(src));
|
|
return dst(src'high-1 downto src'low);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= sfixed
|
|
function to_sfixed(src : sfixed_t) return sfixed_t is
|
|
begin
|
|
return src;
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= ufixed
|
|
function to_sfixed(src : ufixed_t) return sfixed_t is
|
|
variable dst : sfixed_t(src'high+1 downto src'low) := (others => '0');
|
|
begin
|
|
dst(src'range) := sfixed_t(src);
|
|
return dst;
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= ufixed
|
|
function to_ufixed
|
|
(
|
|
src : ufixed_t;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
begin
|
|
return reshape(src, nbits, nbits_int, rnd_mode, sat_mode);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= ufixed
|
|
function to_ufixed
|
|
(
|
|
src : ufixed_t;
|
|
proto : ufixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
begin
|
|
return reshape(src, proto, rnd_mode, sat_mode);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= sfixed
|
|
function to_sfixed
|
|
(
|
|
src : sfixed_t;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
begin
|
|
return reshape(src, nbits, nbits_int, rnd_mode, sat_mode);
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= sfixed
|
|
function to_sfixed
|
|
(
|
|
src : sfixed_t;
|
|
proto : sfixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
begin
|
|
return reshape(src, proto, rnd_mode, sat_mode);
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= integer
|
|
function to_ufixed (src : integer; nbits : integer; nbits_int : integer) return ufixed_t is
|
|
begin
|
|
return to_ufixed(src, uproto(nbits, nbits_int));
|
|
|
|
end to_ufixed;
|
|
|
|
function to_ufixed (src : integer; proto : ufixed_t) return ufixed_t is
|
|
begin
|
|
return to_ufixed(to_unsigned(src, proto'length), proto);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= unsigned
|
|
function to_ufixed (src : unsigned; nbits : integer; nbits_int : integer) return ufixed_t is
|
|
begin
|
|
return to_ufixed(src, uproto(nbits, nbits_int));
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= unsigned
|
|
function to_ufixed(src : unsigned; proto : ufixed_t) return ufixed_t is
|
|
variable dst : ufixed_t(proto'high downto proto'low) := (others => '0');
|
|
begin
|
|
|
|
dst(dst'low + min(dst'length, src'length)-1 downto dst'low) := ufixed_t(src(min(dst'length, src'length)-1 downto 0));
|
|
|
|
return dst;
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= integer
|
|
function to_sfixed (src : integer; nbits : integer; nbits_int : integer) return sfixed_t is
|
|
begin
|
|
return to_sfixed(src, sproto(nbits, nbits_int));
|
|
|
|
end to_sfixed;
|
|
|
|
function to_sfixed (src : integer; proto : sfixed_t) return sfixed_t is
|
|
begin
|
|
|
|
return to_sfixed(to_signed(src, proto'length), proto);
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= signed
|
|
function to_sfixed (src : signed; nbits : integer; nbits_int : integer) return sfixed_t is
|
|
begin
|
|
return to_sfixed(src, sproto(nbits, nbits_int));
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= signed
|
|
function to_sfixed(src : signed; proto : sfixed_t) return sfixed_t is
|
|
variable dst : sfixed_t(proto'high downto proto'low) := (others => '0');
|
|
begin
|
|
|
|
dst(dst'low + min(dst'length, src'length)-2 downto dst'low) := sfixed_t(src(min(dst'length, src'length)-2 downto 0));
|
|
dst(dst'high) := src(src'high);
|
|
|
|
return dst;
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
function to_ufixed (src : STD_LOGIC_VECTOR; proto : ufixed_t) return ufixed_t is
|
|
variable result : ufixed_t (proto'left downto proto'right);
|
|
begin
|
|
if (result'length < 1) then
|
|
return result;
|
|
else
|
|
result := to_ufixed (unsigned(src), proto);
|
|
return result;
|
|
end if;
|
|
|
|
end function to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
function to_ufixed (src : STD_LOGIC_VECTOR; nbits : integer; nbits_int : integer) return ufixed_t is
|
|
begin
|
|
return to_ufixed(src, uproto(nbits, nbits_int));
|
|
|
|
end function to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
function to_sfixed (src : STD_LOGIC_VECTOR; proto : sfixed_t) return sfixed_t is
|
|
variable result : sfixed_t (proto'left downto proto'right);
|
|
begin
|
|
if (result'length < 1) then
|
|
return result;
|
|
else
|
|
result := to_sfixed (signed(src), proto);
|
|
return result;
|
|
end if;
|
|
|
|
end function to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
function to_sfixed (src : STD_LOGIC_VECTOR; nbits : integer; nbits_int : integer) return sfixed_t is
|
|
begin
|
|
return to_sfixed(src, sproto(nbits, nbits_int));
|
|
|
|
end to_sfixed;
|
|
-------------------------------------------------------------
|
|
|
|
-- ufixed <= real
|
|
function to_ufixed
|
|
(
|
|
src : real;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
|
|
constant nbits_ext : integer := nbits + 1;
|
|
constant fix_hi : integer := nbits_int - 1;
|
|
constant fix_lo : integer := nbits_int - nbits_ext;
|
|
|
|
variable dst : ufixed_t (fix_hi downto fix_lo) := (others => '0');
|
|
variable i : integer := 0;
|
|
variable remain : real := 0.0;
|
|
|
|
begin
|
|
|
|
if (nbits_int < 0) then
|
|
assert false report "to_ufixed: Bad dual point (N integer bits < 0)" severity error;
|
|
end if;
|
|
|
|
if ((2.0**nbits_int - 1.0) < ipart(abs(src))) then
|
|
-- assert ASSERT_NO_WARN report "to_ufixed: Overflow (" & REAL'image(src) & ") " severity warning;
|
|
-- print_info(dst, "dst: ");
|
|
end if;
|
|
|
|
remain := abs(src);
|
|
for i in dst'range loop
|
|
if remain >= 2.0**i then
|
|
dst(i) := '1';
|
|
remain := remain - 2.0**i;
|
|
else
|
|
dst(i) := '0';
|
|
end if;
|
|
end loop;
|
|
|
|
return to_ufixed(dst, nbits, nbits_int, rnd_mode, sat_mode);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= real
|
|
function to_sfixed
|
|
(
|
|
src : real;
|
|
proto : sfixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
|
|
variable utmp : ufixed_t(proto'high-1 downto proto'low) := (others => '0');
|
|
variable dst : sfixed_t(proto'high downto proto'low) := (others => '0');
|
|
|
|
begin
|
|
utmp := to_ufixed(src, utmp, rnd_mode, sat_mode);
|
|
if (src < 0.0) then
|
|
dst := -to_sfixed(utmp);
|
|
else
|
|
dst := to_sfixed(utmp);
|
|
end if;
|
|
|
|
return dst;
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= real
|
|
function to_ufixed
|
|
(
|
|
src : real;
|
|
proto : ufixed_t;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return ufixed_t is
|
|
begin
|
|
return to_ufixed(src, proto'length, proto'high+1, rnd_mode, sat_mode);
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= real
|
|
function to_sfixed
|
|
(
|
|
src : real;
|
|
nbits : integer;
|
|
nbits_int : integer;
|
|
rnd_mode : round_mode_t := default_round_mode;
|
|
sat_mode : saturate_mode_t := default_saturate_mode
|
|
) return sfixed_t is
|
|
begin
|
|
return to_sfixed(src, sproto(nbits, nbits_int), rnd_mode, sat_mode);
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- ufixed <= ufixed_array(i)
|
|
function to_ufixed(src : ufixed_array_t; index : integer) return ufixed_t is
|
|
variable dst : ufixed_t(src'range(2));
|
|
begin
|
|
for j in src'range(2) loop
|
|
dst(j) := src(index, j);
|
|
end loop;
|
|
|
|
return dst;
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- sfixed <= sfixed_array(i)
|
|
function to_sfixed(src : sfixed_array_t; index : integer) return sfixed_t is
|
|
variable dst : sfixed_t(src'range(2));
|
|
begin
|
|
for j in src'range(2) loop
|
|
dst(j) := src(index, j);
|
|
end loop;
|
|
|
|
return dst;
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- ufixed <= string
|
|
function to_ufixed (src : string) return ufixed_t is
|
|
|
|
variable i, j, nbits, nbits_int, nbits_frac : integer := 0;
|
|
variable dst : unsigned(src'length downto 0) := (others => '0');
|
|
variable dp_found : boolean := false;
|
|
begin
|
|
|
|
for i in src'reverse_range loop
|
|
case src(i) is
|
|
when '.' =>
|
|
if dp_found then
|
|
assert false report "More than one DP not found." severity error;
|
|
else
|
|
dp_found := true;
|
|
nbits_frac := j;
|
|
end if;
|
|
|
|
when '0' => dst(nbits) := '0'; nbits := nbits + 1; j := j + 1;
|
|
when '1' => dst(nbits) := '1'; nbits := nbits + 1; j := j + 1;
|
|
when others =>
|
|
assert false report "Illegal character in binary string." severity error;
|
|
|
|
end case;
|
|
|
|
end loop ;
|
|
if not dp_found then
|
|
assert ASSERT_NO_WARN report "DP not found. Using left alignment." severity warning;
|
|
end if;
|
|
|
|
nbits_int := nbits - nbits_frac;
|
|
|
|
return to_ufixed(dst(nbits-1 downto 0), nbits, nbits_int);
|
|
|
|
end to_ufixed;
|
|
|
|
-------------------------------------------------------------
|
|
-- sfixed <= string
|
|
function to_sfixed (src : string) return sfixed_t is
|
|
|
|
variable i, j, nbits, nbits_int, nbits_frac : integer := 0;
|
|
variable dst : signed(src'length downto 0) := (others => '0');
|
|
variable dp_found : boolean := false;
|
|
variable is_neg : boolean := false;
|
|
begin
|
|
|
|
is_neg := src(src'left) = '-';
|
|
|
|
for i in src'reverse_range loop
|
|
case src(i) is
|
|
when '-' => null;
|
|
when '+' => null;
|
|
|
|
when '.' =>
|
|
if dp_found then
|
|
assert false report "More than one DP not found." severity error;
|
|
else
|
|
dp_found := true;
|
|
nbits_frac := j;
|
|
end if;
|
|
|
|
when '0' => dst(nbits) := '0'; nbits := nbits + 1; j := j + 1;
|
|
when '1' => dst(nbits) := '1'; nbits := nbits + 1; j := j + 1;
|
|
when others =>
|
|
assert false report "Illegal character in binary string." severity error;
|
|
end case;
|
|
end loop ;
|
|
nbits := nbits + 1;
|
|
|
|
if not dp_found then
|
|
assert ASSERT_NO_WARN report "DP not found. Using left alignment." severity warning;
|
|
end if;
|
|
|
|
nbits_int := nbits - nbits_frac-1;
|
|
|
|
if is_neg then
|
|
dst(nbits-1 downto 0) := -dst(nbits-1 downto 0);
|
|
end if;
|
|
|
|
return to_sfixed(dst(nbits-1 downto 0), nbits, nbits_int);
|
|
|
|
end to_sfixed;
|
|
|
|
-------------------------------------------------------------
|
|
function to_unsigned (src : ufixed_t) return UNSIGNED is
|
|
subtype t is UNSIGNED(src'high - src'low downto 0);
|
|
variable slv : t;
|
|
begin
|
|
slv := t(src);
|
|
return UNSIGNED(to_X01(std_logic_vector(slv)));
|
|
|
|
end function to_unsigned;
|
|
|
|
-------------------------------------------------------------
|
|
function to_signed (src : sfixed_t) return SIGNED is
|
|
subtype t is SIGNED(src'high - src'low downto 0);
|
|
variable slv : t;
|
|
begin
|
|
slv := t(src);
|
|
return SIGNED(to_X01(std_logic_vector(slv)));
|
|
|
|
end function to_signed;
|
|
|
|
-------------------------------------------------------------
|
|
-- integer <= ufixed
|
|
function to_integer (src : ufixed_t) return integer is
|
|
begin
|
|
return to_integer(to_unsigned(src));
|
|
end to_integer;
|
|
|
|
-------------------------------------------------------------
|
|
-- integer <= sfixed
|
|
function to_integer (src : sfixed_t) return integer is
|
|
begin
|
|
return to_integer(to_signed(src));
|
|
end to_integer;
|
|
|
|
-------------------------------------------------------------
|
|
-- to_real
|
|
function to_real(src : ufixed_t) return real is
|
|
variable dst : real := 0.0;
|
|
begin
|
|
for i in src'range loop
|
|
if (src(i) = '1') then
|
|
dst := dst + real(2.0**i);
|
|
end if;
|
|
end loop;
|
|
return dst;
|
|
|
|
end to_real;
|
|
|
|
-------------------------------------------------------------
|
|
function to_real(src : sfixed_t) return real is
|
|
variable dst : real := 0.0;
|
|
begin
|
|
dst := to_real(to_ufixed(src));
|
|
|
|
if (src(src'high) = '1') then
|
|
dst := -dst;
|
|
end if;
|
|
|
|
return dst;
|
|
|
|
end to_real;
|
|
|
|
-------------------------------------------------------------
|
|
-- to_slv
|
|
function to_slv (src : ufixed_t) return STD_LOGIC_VECTOR is
|
|
subtype t is STD_LOGIC_VECTOR (src'high - src'low downto 0);
|
|
variable slv : t;
|
|
begin
|
|
if src'length < 1 then
|
|
return NSLV;
|
|
end if;
|
|
slv := t (src);
|
|
return slv;
|
|
|
|
end function to_slv;
|
|
|
|
-------------------------------------------------------------
|
|
-- to_slv
|
|
function to_slv (src : sfixed_t) return STD_LOGIC_VECTOR is
|
|
subtype t is STD_LOGIC_VECTOR (src'high - src'low downto 0);
|
|
variable slv : t;
|
|
begin
|
|
if src'length < 1 then
|
|
return NSLV;
|
|
end if;
|
|
slv := t (src);
|
|
return slv;
|
|
|
|
end function to_slv;
|
|
|
|
-------------------------------------------------------------
|
|
function to_string(src : ufixed_t) return string is
|
|
variable str : string(src'length+1 downto 1) := (others => '0');
|
|
variable i, j : integer := 0;
|
|
|
|
begin
|
|
j := src'length+1;
|
|
for i in src'high downto 0 loop
|
|
if (src(i) = '1') then
|
|
str(j) := '1';
|
|
end if;
|
|
j := j - 1;
|
|
end loop;
|
|
|
|
str(j) := '.';
|
|
j := j - 1;
|
|
|
|
for i in -1 downto src'low loop
|
|
if (src(i) = '1') then
|
|
str(j) := '1';
|
|
end if;
|
|
j := j - 1;
|
|
end loop;
|
|
|
|
return str;
|
|
|
|
end to_string;
|
|
|
|
-------------------------------------------------------------
|
|
function to_string(src : sfixed_t) return string is
|
|
variable str : string(src'length+1 downto 1) := (others => '0');
|
|
variable i, j, start : integer := 0;
|
|
variable strlen : integer := 0;
|
|
variable src_abs : sfixed_t(src'range) := (others => '0');
|
|
|
|
begin
|
|
if (src'high < 0) then
|
|
assert false report "Illegal signed fix point number" severity error;
|
|
end if;
|
|
|
|
start := src'high;
|
|
strlen := src'length;
|
|
|
|
j := src'length+1;
|
|
if (src(start) = '1') then
|
|
str(j) := '-';
|
|
j := j - 1;
|
|
start := start - 1;
|
|
strlen := strlen + 1;
|
|
end if;
|
|
|
|
src_abs := abs(src);
|
|
|
|
for i in start downto 0 loop
|
|
if (src_abs(i) = '1') then
|
|
str(j) := '1';
|
|
end if;
|
|
j := j - 1;
|
|
end loop;
|
|
|
|
str(j) := '.';
|
|
j := j - 1;
|
|
|
|
for i in -1 downto src'low loop
|
|
if (src_abs(i) = '1') then
|
|
str(j) := '1';
|
|
end if;
|
|
j := j - 1;
|
|
end loop;
|
|
|
|
return str(strlen downto 1);
|
|
|
|
end to_string;
|
|
|
|
-------------------------------------------------------------
|
|
function to_string(src : std_logic_vector) return string is
|
|
variable str : string(src'length downto 1) := (others => '0');
|
|
variable i : integer := 0;
|
|
|
|
begin
|
|
for i in src'range loop
|
|
if (src(i) = '1') then
|
|
str(i+1) := '1';
|
|
end if;
|
|
end loop;
|
|
|
|
return str;
|
|
|
|
end to_string;
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary Operators
|
|
-------------------------------------------------------------
|
|
function "sla" (src : ufixed_t; count : integer) return ufixed_t is
|
|
variable result : ufixed_t (src'high downto src'low) := (others => '0');
|
|
|
|
begin
|
|
if (count = 0) then
|
|
result := src;
|
|
elsif (count < 0) then
|
|
result := src sra -count;
|
|
elsif (count < src'length) then
|
|
result(src'high downto src'low) := src(src'high-count downto src'low) & (count-1 downto 0 => '0');
|
|
end if;
|
|
return result;
|
|
|
|
end "sla";
|
|
|
|
-------------------------------------------------------------
|
|
function "sla" (src : sfixed_t; count : integer) return sfixed_t is
|
|
variable result : sfixed_t (src'high downto src'low) := (others => '0');
|
|
variable sign : std_logic := '0';
|
|
|
|
begin
|
|
sign := src(src'high);
|
|
if (count = 0) then
|
|
result := src;
|
|
elsif (count < 0) then
|
|
result := src sra -count;
|
|
elsif (count < src'length-1) then
|
|
result(src'high downto src'low) := sign & src(src'high-count-1 downto src'low) & (count-1 downto 0 => '0');
|
|
end if;
|
|
return result;
|
|
|
|
end "sla";
|
|
|
|
-------------------------------------------------------------
|
|
function "sra" (src : ufixed_t; count : integer) return ufixed_t is
|
|
variable result : ufixed_t (src'high downto src'low) := (others => '0');
|
|
|
|
begin
|
|
if (count = 0) then
|
|
result := src;
|
|
elsif (count < 0) then
|
|
result := src sla -count;
|
|
elsif (count < src'length) then
|
|
result(src'high downto src'low) := (count-1 downto 0 => '0') & src(src'high downto src'low + count);
|
|
end if;
|
|
return result;
|
|
|
|
end "sra";
|
|
|
|
-------------------------------------------------------------
|
|
function "sra" (src : sfixed_t; count : integer) return sfixed_t is
|
|
variable result : sfixed_t (src'high downto src'low) := (others => '0');
|
|
variable res_slv, src_slv : signed (src'length-1 downto 0) := (others => '0');
|
|
variable sign, do_sub : std_logic := '0';
|
|
|
|
begin
|
|
src_slv := to_signed(src);
|
|
sign := src(src'high);
|
|
do_sub := src(src'high) and src(src'low);
|
|
if (count = 0) then
|
|
result := src;
|
|
elsif (count < 0) then
|
|
result := src sla -count;
|
|
elsif (count < src'length-1) then
|
|
res_slv := (count downto 0 => sign) & src_slv(src'length-2 downto count);
|
|
if (do_sub = '1') then
|
|
result(src'high downto src'low) := to_sfixed(res_slv+1, result);
|
|
else
|
|
result(src'high downto src'low) := to_sfixed(res_slv, result);
|
|
end if;
|
|
end if;
|
|
return result;
|
|
|
|
end "sra";
|
|
|
|
-------------------------------------------------------------
|
|
function "*" (a : ufixed_t; b : ufixed_t) return ufixed_t is
|
|
variable result : ufixed_t (uproto(a,'*',b)'high downto uproto(a,'*',b)'low);
|
|
|
|
begin
|
|
if (a'high < 0 and b'high >= 0) or (a'high >= 0 and b'high < 0) then
|
|
result := to_ufixed(to_unsigned(a) * to_unsigned(b), result) sla 1;
|
|
else
|
|
result := to_ufixed(to_unsigned(a) * to_unsigned(b), result);
|
|
end if;
|
|
return result;
|
|
|
|
end "*";
|
|
|
|
-------------------------------------------------------------
|
|
function "*" (a : sfixed_t; b : sfixed_t) return sfixed_t is
|
|
variable result : sfixed_t (sproto(a,'*',b)'high downto sproto(a,'*',b)'low);
|
|
|
|
begin
|
|
if (a'high = 0 and b'high > 0) or (a'high > 0 and b'high = 0) then
|
|
result := to_sfixed(signed(a) * signed(b), result) sla 2;
|
|
else
|
|
result := to_sfixed(signed(a) * signed(b), result) sla 1;
|
|
end if;
|
|
return result;
|
|
|
|
end "*";
|
|
|
|
-------------------------------------------------------------
|
|
function "*" (a : ufixed_t; b : sfixed_t) return sfixed_t is
|
|
|
|
begin
|
|
return to_sfixed(a) * b;
|
|
|
|
end "*";
|
|
|
|
-------------------------------------------------------------
|
|
function "*" (a : sfixed_t; b : ufixed_t) return sfixed_t is
|
|
|
|
begin
|
|
return b * a;
|
|
|
|
end "*";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : ufixed_t; b : ufixed_t) return ufixed_t is
|
|
variable result : ufixed_t (uproto(a,'+',b)'high downto uproto(a,'+',b)'low);
|
|
|
|
begin
|
|
result := ufixed_t(unsigned(reshape(a, result)) + unsigned(reshape(b, result)));
|
|
return result;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : sfixed_t; b : sfixed_t) return sfixed_t is
|
|
variable result : sfixed_t (sproto(a,'+',b)'high downto sproto(a,'+',b)'low);
|
|
|
|
begin
|
|
result := to_sfixed(signed(reshape(a,result)) + signed(reshape(b,result)), result);
|
|
-- result := to_sfixed(signed(a) + signed(b), result);
|
|
return result;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : ufixed_t; b : sfixed_t) return sfixed_t is
|
|
|
|
begin
|
|
return to_sfixed(a) + b;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : sfixed_t; b : ufixed_t) return sfixed_t is
|
|
|
|
begin
|
|
return b + a;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : ufixed_t; b : unsigned) return ufixed_t is
|
|
|
|
begin
|
|
|
|
return ufixed_t(unsigned(a) + b);
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : sfixed_t; b : signed) return sfixed_t is
|
|
|
|
begin
|
|
|
|
return sfixed_t(signed(a) + b);
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : ufixed_t; b : integer) return ufixed_t is
|
|
|
|
begin
|
|
|
|
return ufixed_t(unsigned(a) + to_unsigned(b, a'length));
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : sfixed_t; b : integer) return sfixed_t is
|
|
|
|
begin
|
|
|
|
return sfixed_t(signed(a) + to_signed(b, a'length));
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : ufixed_t; b : std_logic) return ufixed_t is
|
|
variable result : ufixed_t (a'high downto a'low);
|
|
variable buns : unsigned(a'length-1 downto 0);
|
|
|
|
begin
|
|
buns := (a'length-1 downto 1 => '0') & b;
|
|
result := ufixed_t(to_unsigned(a) + buns);
|
|
return result;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "+" (a : sfixed_t; b : std_logic) return sfixed_t is
|
|
variable result : sfixed_t (a'high downto a'low);
|
|
variable bs : signed(a'length-1 downto 0);
|
|
|
|
begin
|
|
bs := (a'length-1 downto 1 => '0') & b;
|
|
result := sfixed_t(to_signed(a) + bs);
|
|
return result;
|
|
|
|
end "+";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : ufixed_t; b : ufixed_t) return ufixed_t is
|
|
variable result : ufixed_t (uproto(a,'-',b)'high downto uproto(a,'-',b)'low);
|
|
begin
|
|
result := to_ufixed(to_sfixed(a) - to_sfixed(b));
|
|
return result;
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : sfixed_t; b : sfixed_t) return sfixed_t is
|
|
variable result : sfixed_t (sproto(a,'-',b)'high downto sproto(a,'-',b)'low);
|
|
|
|
begin
|
|
result := to_sfixed(signed(reshape(a,result)) - signed(reshape(b,result)), result);
|
|
return result;
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : ufixed_t; b : sfixed_t) return sfixed_t is
|
|
begin
|
|
return to_sfixed(a) - b;
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : sfixed_t; b : ufixed_t) return sfixed_t is
|
|
|
|
begin
|
|
return a - to_sfixed(b);
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : ufixed_t; b : unsigned) return ufixed_t is
|
|
|
|
begin
|
|
return ufixed_t(unsigned(a) - b);
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : sfixed_t; b : signed) return sfixed_t is
|
|
|
|
begin
|
|
return sfixed_t(signed(a) - b);
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : ufixed_t; b : integer) return ufixed_t is
|
|
|
|
begin
|
|
|
|
return ufixed_t(unsigned(a) - to_unsigned(b, a'length));
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : sfixed_t; b : integer) return sfixed_t is
|
|
|
|
begin
|
|
|
|
return sfixed_t(signed(a) - to_signed(b, a'length));
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : ufixed_t; b : std_logic) return ufixed_t is
|
|
variable result : ufixed_t (a'high downto a'low);
|
|
variable buns : unsigned(a'length-1 downto 0);
|
|
|
|
begin
|
|
buns := (a'length-1 downto 1 => '0') & b;
|
|
result := ufixed_t(unsigned(a) - buns);
|
|
return result;
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (a : sfixed_t; b : std_logic) return sfixed_t is
|
|
variable result : sfixed_t (a'high downto a'low);
|
|
variable bs : signed(a'length-1 downto 0);
|
|
|
|
begin
|
|
bs := (a'length-1 downto 1 => '0') & b;
|
|
result := sfixed_t(signed(a) - bs);
|
|
return result;
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
-- Unary Operators
|
|
-------------------------------------------------------------
|
|
function "abs" (src : sfixed_t) return sfixed_t is
|
|
begin
|
|
return to_sfixed(abs(signed(src)), src);
|
|
|
|
end "abs";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (src : ufixed_t) return sfixed_t is
|
|
begin
|
|
return -to_sfixed(src);
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
function "-" (src : sfixed_t) return sfixed_t is
|
|
begin
|
|
return to_sfixed(-signed(src), src);
|
|
|
|
end "-";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary Equality
|
|
-------------------------------------------------------------
|
|
function "=" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
variable ta, tb: ufixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_ufixed(a, ta);
|
|
tb := to_ufixed(b, tb);
|
|
return to_unsigned(ta) = to_unsigned(tb);
|
|
|
|
end "=";
|
|
|
|
-------------------------------------------------------------
|
|
function "=" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
variable ta, tb: sfixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_sfixed(a, ta);
|
|
tb := to_sfixed(b, tb);
|
|
return to_signed(ta) = to_signed(tb);
|
|
|
|
end "=";
|
|
|
|
-------------------------------------------------------------
|
|
function "=" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return to_sfixed(a) = b;
|
|
end "=";
|
|
|
|
-------------------------------------------------------------
|
|
function "=" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return b = a;
|
|
end "=";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary Inequality
|
|
-------------------------------------------------------------
|
|
function "/=" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a = b);
|
|
|
|
end "/=";
|
|
|
|
-------------------------------------------------------------
|
|
function "/=" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a = b);
|
|
|
|
end "/=";
|
|
|
|
-------------------------------------------------------------
|
|
function "/=" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a = b);
|
|
end "/=";
|
|
|
|
-------------------------------------------------------------
|
|
function "/=" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a = b);
|
|
end "/=";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary less than
|
|
-------------------------------------------------------------
|
|
function "<" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
variable ta, tb: ufixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_ufixed(a, ta);
|
|
tb := to_ufixed(b, tb);
|
|
return to_unsigned(ta) < to_unsigned(tb);
|
|
|
|
end "<";
|
|
|
|
-------------------------------------------------------------
|
|
function "<" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
variable ta, tb: sfixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_sfixed(a, ta);
|
|
tb := to_sfixed(b, tb);
|
|
return to_signed(ta) < to_signed(tb);
|
|
|
|
end "<";
|
|
|
|
-------------------------------------------------------------
|
|
function "<" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return to_sfixed(a) < b;
|
|
|
|
end "<";
|
|
|
|
-------------------------------------------------------------
|
|
function "<" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return a < to_sfixed(b);
|
|
|
|
end "<";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary greater than
|
|
-------------------------------------------------------------
|
|
function ">" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
variable ta, tb: ufixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_ufixed(a, ta);
|
|
tb := to_ufixed(b, tb);
|
|
return to_unsigned(ta) > to_unsigned(tb);
|
|
|
|
end ">";
|
|
|
|
-------------------------------------------------------------
|
|
function ">" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
variable ta, tb: sfixed_t(max(a'high, b'high) downto min(a'low, b'low));
|
|
begin
|
|
ta := (others => '0');
|
|
tb := (others => '0');
|
|
ta := to_sfixed(a, ta);
|
|
tb := to_sfixed(b, tb);
|
|
return to_signed(ta) > to_signed(tb);
|
|
|
|
end ">";
|
|
|
|
-------------------------------------------------------------
|
|
function ">" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return to_sfixed(a) > b;
|
|
end ">";
|
|
|
|
-------------------------------------------------------------
|
|
function ">" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return a > to_sfixed(b);
|
|
end ">";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary less equal than
|
|
-------------------------------------------------------------
|
|
function "<=" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a > b);
|
|
end "<=";
|
|
|
|
function "<=" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a > b);
|
|
end "<=";
|
|
|
|
function "<=" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a > b);
|
|
end "<=";
|
|
|
|
function "<=" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a > b);
|
|
end "<=";
|
|
|
|
-------------------------------------------------------------
|
|
-- Binary greater or equal than
|
|
-------------------------------------------------------------
|
|
function ">=" (a : ufixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a < b);
|
|
end ">=";
|
|
|
|
function ">=" (a : sfixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a < b);
|
|
end ">=";
|
|
|
|
function ">=" (a : ufixed_t; b : sfixed_t) return boolean is
|
|
begin
|
|
return not (a < b);
|
|
end ">=";
|
|
|
|
function ">=" (a : sfixed_t; b : ufixed_t) return boolean is
|
|
begin
|
|
return not (a < b);
|
|
end ">=";
|
|
|
|
-------------------------------------------------------------
|
|
-- Misc. Operators
|
|
-------------------------------------------------------------
|
|
function ipart (src : ufixed_t) return ufixed_t is
|
|
begin
|
|
return src(src'high downto 0);
|
|
end ipart;
|
|
|
|
function fpart (src : ufixed_t) return ufixed_t is
|
|
begin
|
|
return src(-1 downto src'low);
|
|
end fpart;
|
|
|
|
function ipart (src : sfixed_t) return sfixed_t is
|
|
begin
|
|
return src(src'high-1 downto 0);
|
|
end ipart;
|
|
|
|
function fpart (src : sfixed_t) return sfixed_t is
|
|
begin
|
|
return src(-1 downto src'low);
|
|
end fpart;
|
|
|
|
-------------------------------------------------------------
|
|
-- Print functions
|
|
-------------------------------------------------------------
|
|
procedure print_info(src : in ufixed_t; prefix : in string) is
|
|
variable L : line;
|
|
|
|
begin
|
|
write (L, prefix & "'length = ");write (L, src'length);
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'high(left) = ");
|
|
write (L, src'high);
|
|
write (L, '(');
|
|
write (L, src'left);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'low(right) = ");
|
|
write (L, src'low);
|
|
write (L, '(');
|
|
write (L, src'right);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'value = B");write (L, to_string(src));
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'value = ");write (L, to_real(src));
|
|
writeline (output, L);
|
|
|
|
-- write (L, prefix & "'cmsb = ");write (L, cmsb(src));
|
|
-- writeline (output, L);
|
|
|
|
-- write (L, prefix & "'clsb = ");write (L, clsb(src));
|
|
-- writeline (output, L);
|
|
|
|
writeline (output, L);
|
|
|
|
end print_info;
|
|
|
|
-------------------------------------------------------------
|
|
procedure print_info(src : in sfixed_t; prefix : in string) is
|
|
variable L : line;
|
|
|
|
begin
|
|
write (L, prefix & "'length = ");write (L, src'length);
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'high(left) = ");
|
|
write (L, src'high);
|
|
write (L, '(');
|
|
write (L, src'left);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'low(right) = ");
|
|
write (L, src'low);
|
|
write (L, '(');
|
|
write (L, src'right);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'value = B");write (L, to_string(src));
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'value = ");write (L, to_real(src));
|
|
writeline (output, L);
|
|
|
|
-- write (L, prefix & "'cmsb = ");write (L, cmsb(src));
|
|
-- writeline (output, L);
|
|
|
|
-- write (L, prefix & "'clsb = ");write (L, clsb(src));
|
|
-- writeline (output, L);
|
|
|
|
writeline (output, L);
|
|
|
|
end print_info;
|
|
|
|
-------------------------------------------------------------
|
|
procedure print_info(src : in string; prefix : in string) is
|
|
variable L : line;
|
|
|
|
begin
|
|
write (L, prefix & "'length = ");write (L, src'length);
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'high(left) = ");
|
|
write (L, src'high);
|
|
write (L, '(');
|
|
write (L, src'left);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
write (L, prefix & "'low(right) = ");
|
|
write (L, src'low);
|
|
write (L, '(');
|
|
write (L, src'right);
|
|
write (L, ')');
|
|
writeline (output, L);
|
|
|
|
writeline (output, L);
|
|
|
|
end print_info;
|
|
|
|
-------------------------------------------------------------
|
|
-- Helpers
|
|
-------------------------------------------------------------
|
|
-- Count significant bits for integer part
|
|
function cmsb(src : ufixed_t) return integer is
|
|
variable j, i : integer := src'high;
|
|
begin
|
|
for i in src'range loop
|
|
if src(i) = '1' then
|
|
exit;
|
|
end if;
|
|
j := j - 1;
|
|
end loop;
|
|
|
|
-- LRM nachlesen: hier is i=src'high re-initialisert
|
|
|
|
return j;
|
|
|
|
end cmsb;
|
|
|
|
-------------------------------------------------------------
|
|
-- Count significant bits for fractional part
|
|
function clsb(src : ufixed_t) return integer is
|
|
variable j, i : integer := src'low;
|
|
begin
|
|
for i in src'reverse_range loop
|
|
if src(i) = '1' then
|
|
exit;
|
|
end if;
|
|
j := j + 1;
|
|
end loop;
|
|
|
|
-- LRM nachlesen: hier is i=src'low re-initialisert
|
|
|
|
return j;
|
|
|
|
end clsb;
|
|
|
|
-------------------------------------------------------------
|
|
function MIN (X, Y: INTEGER) return INTEGER is
|
|
variable res : integer := X;
|
|
begin
|
|
if Y < X then
|
|
res := Y;
|
|
end if;
|
|
|
|
return res;
|
|
|
|
end MIN;
|
|
|
|
-------------------------------------------------------------
|
|
function MAX (X, Y: INTEGER) return INTEGER is
|
|
variable res : integer := X;
|
|
begin
|
|
if Y > X then
|
|
res := Y;
|
|
end if;
|
|
|
|
return res;
|
|
|
|
end MAX;
|
|
|
|
-------------------------------------------------------------
|
|
function "MOD" (X, Y: in REAL ) return REAL is
|
|
-- Description:
|
|
-- See function declaration in IEEE Std 1076.2-1996
|
|
-- Notes:
|
|
-- a) Returns 0.0 on error
|
|
|
|
variable XNEGATIVE : BOOLEAN := X < 0.0;
|
|
variable YNEGATIVE : BOOLEAN := Y < 0.0;
|
|
variable VALUE : REAL;
|
|
begin
|
|
-- Check validity of input arguments
|
|
if (Y = 0.0) then
|
|
assert FALSE
|
|
report "MOD(X, 0.0) is undefined"
|
|
severity ERROR;
|
|
return 0.0;
|
|
end if;
|
|
|
|
-- Compute value
|
|
if ( XNEGATIVE ) then
|
|
if ( YNEGATIVE ) then
|
|
VALUE := X + (FLOOR(ABS(X)/ABS(Y)))*ABS(Y);
|
|
else
|
|
VALUE := X + (CEIL(ABS(X)/ABS(Y)))*ABS(Y);
|
|
end if;
|
|
else
|
|
if ( YNEGATIVE ) then
|
|
VALUE := X - (CEIL(ABS(X)/ABS(Y)))*ABS(Y);
|
|
else
|
|
VALUE := X - (FLOOR(ABS(X)/ABS(Y)))*ABS(Y);
|
|
end if;
|
|
end if;
|
|
|
|
return VALUE;
|
|
|
|
end "MOD";
|
|
|
|
-------------------------------------------------------------
|
|
-- misc. conversion
|
|
function ipart(src : real) return real is
|
|
begin
|
|
return floor(src);
|
|
|
|
end ipart;
|
|
|
|
-------------------------------------------------------------
|
|
function fpart(src : real) return real is
|
|
begin
|
|
return src - floor(src);
|
|
|
|
end fpart;
|
|
|
|
-------------------------------------------------------------
|
|
function or_red (arg : STD_LOGIC_VECTOR)
|
|
return STD_LOGIC is
|
|
variable Upper, Lower : STD_LOGIC;
|
|
variable Half : INTEGER;
|
|
variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0);
|
|
variable Result : STD_LOGIC;
|
|
begin
|
|
if (arg'length < 1) then -- In the case of a NULL range
|
|
Result := '0';
|
|
else
|
|
BUS_int := to_ux01 (arg);
|
|
if (BUS_int'length = 1) then
|
|
Result := BUS_int (BUS_int'left);
|
|
elsif (BUS_int'length = 2) then
|
|
Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left);
|
|
else
|
|
Half := (BUS_int'length + 1) / 2 + BUS_int'right;
|
|
Upper := or_red (BUS_int (BUS_int'left downto Half));
|
|
Lower := or_red (BUS_int (Half - 1 downto BUS_int'right));
|
|
Result := Upper or Lower;
|
|
end if;
|
|
end if;
|
|
return Result;
|
|
|
|
end function or_red;
|
|
|
|
-------------------------------------------------------------
|
|
function and_red (arg : STD_LOGIC_VECTOR)
|
|
return STD_LOGIC is
|
|
variable Upper, Lower : STD_LOGIC;
|
|
variable Half : INTEGER;
|
|
variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0);
|
|
variable Result : STD_LOGIC;
|
|
begin
|
|
if (arg'length < 1) then -- In the case of a NULL range
|
|
Result := '1';
|
|
else
|
|
BUS_int := to_ux01 (arg);
|
|
if (BUS_int'length = 1) then
|
|
Result := BUS_int (BUS_int'left);
|
|
elsif (BUS_int'length = 2) then
|
|
Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left);
|
|
else
|
|
Half := (BUS_int'length + 1) / 2 + BUS_int'right;
|
|
Upper := and_red (BUS_int (BUS_int'left downto Half));
|
|
Lower := and_red (BUS_int (Half - 1 downto BUS_int'right));
|
|
Result := Upper and Lower;
|
|
end if;
|
|
end if;
|
|
return Result;
|
|
|
|
end function and_red;
|
|
|
|
-------------------------------------------------------------
|
|
function xor_red (arg : STD_LOGIC_VECTOR) return STD_ULOGIC is
|
|
variable Upper, Lower : STD_ULOGIC;
|
|
variable Half : INTEGER;
|
|
variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0);
|
|
variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range
|
|
begin
|
|
if (arg'length >= 1) then
|
|
BUS_int := to_ux01 (arg);
|
|
if (BUS_int'length = 1) then
|
|
Result := BUS_int (BUS_int'left);
|
|
elsif (BUS_int'length = 2) then
|
|
Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left);
|
|
else
|
|
Half := (BUS_int'length + 1) / 2 + BUS_int'right;
|
|
Upper := xor_red (BUS_int (BUS_int'left downto Half));
|
|
Lower := xor_red (BUS_int (Half - 1 downto BUS_int'right));
|
|
Result := Upper xor Lower;
|
|
end if;
|
|
end if;
|
|
return Result;
|
|
|
|
end function xor_red;
|
|
|
|
-------------------------------------------------------------
|
|
-- Reduction operators, same as numeric_std functions
|
|
function and_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return and_red (to_slv(arg));
|
|
end function and_red;
|
|
|
|
function nand_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not and_red (to_slv(arg));
|
|
end function nand_red;
|
|
|
|
function or_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return or_red (to_slv(arg));
|
|
end function or_red;
|
|
|
|
function nor_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not or_red (to_slv(arg));
|
|
end function nor_red;
|
|
|
|
function xor_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return xor_red (to_slv(arg));
|
|
end function xor_red;
|
|
|
|
function xnor_red(arg : ufixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not xor_red (to_slv(arg));
|
|
end function xnor_red;
|
|
|
|
function and_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return and_red (to_slv(arg));
|
|
end function and_red;
|
|
|
|
function nand_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not and_red (to_slv(arg));
|
|
end function nand_red;
|
|
|
|
function or_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return or_red (to_slv(arg));
|
|
end function or_red;
|
|
|
|
function nor_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not or_red (to_slv(arg));
|
|
end function nor_red;
|
|
|
|
function xor_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return xor_red (to_slv(arg));
|
|
end function xor_red;
|
|
|
|
function xnor_red(arg : sfixed_t) return STD_ULOGIC is
|
|
begin
|
|
return not xor_red (to_slv(arg));
|
|
end function xnor_red;
|
|
|
|
-------------------------------------------------------------
|
|
|
|
end; -- package body fixed_ja;
|