Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make change_size function safer (sizing_2008) #13

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 64 additions & 17 deletions rtl/extras_2008/sizing_2008.vhdl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
--# Additionally the package provides functions for vectors resizing with
--# interfaces which show clearly, how resizing should be performed (extending
--# or truncating, most significant bits or least significant bits).
--# The leftmost bit is treated as the most significant bit (like in
--# NUMERIC_STD).
--#
--# This implementation excludes the overload of change_size for resolved
--# std_logic_vector, because it breaks VHDL-2008 compiler (slv and sulv are
Expand Down Expand Up @@ -141,7 +143,8 @@ package sizing is

type resize_method is (truncate_LSBs, truncate_MSBs, extend_LSBs, extend_MSBs);
--## Resizizng function for std_ulogic_vector clearly stating how exactly the
--# resizing will be done.
--# resizing will be done. The leftmost bit is treated as the most significant
--# bit (like in NUMERIC_STD).
--#
--# Args:
--# s: Vector to resize
Expand All @@ -154,7 +157,8 @@ package sizing is
extension : std_ulogic := '0' ) return std_ulogic_vector;

--## Resizizng function for unsigned number clearly stating how exactly the
--# resizing will be done. Extends numbers with zeros.
--# resizing will be done. Extends numbers with zeros. The leftmost bit is
--# treated as the most significant bit (like in NUMERIC_STD).
--#
--# Args:
--# s: Vector to resize
Expand All @@ -167,7 +171,8 @@ package sizing is

--## Resizizng function for signed number clearly stating how exactly the
--# resizing will be done. Extends most significant bits with a sign bit,
--# and least significant bits with zeros.
--# and least significant bits with zeros. The leftmost bit is treated as the
--# most significant bit (like in NUMERIC_STD).
--#
--# Args:
--# s: Vector to resize
Expand Down Expand Up @@ -264,33 +269,74 @@ package body sizing is
end function;


--## Checks if resize is correct
function is_resize_ill_formed(new_size,
old_size : natural;
method : resize_method)
return boolean is
begin
case method is
when truncate_LSBs | truncate_MSBs =>
return (old_size < new_size);
when extend_LSBs | extend_MSBs =>
return (old_size > new_size);
end case;
end function;

--## Resizizng function for std_ulogic_vector clearly stating how exactly the
--# resizing will be done.
--# resizing will be done. The leftmost bit is treated as the most significant
--# bit (like in NUMERIC_STD).
function change_size (s : std_ulogic_vector; new_size : positive; method : resize_method;
extension : std_ulogic := '0' ) return std_ulogic_vector is

variable v : std_ulogic_vector(new_size-1 downto 0);
variable v : std_ulogic_vector(s'high downto s'low); -- var to resize
variable r : std_ulogic_vector(new_size-1 downto 0); -- result

alias sr : std_ulogic_vector(s'reverse_range) is s;
alias rr : std_ulogic_vector(r'reverse_range) is r;

-- Null range sulv to trigger elaboration failure
constant NASULV : std_ulogic_vector (0 downto 1) := (others => '0');
begin

-- Safeguards against ill-formed resize attempts
if is_resize_ill_formed(new_size, s'length, method) then
assert false report "Ill-formed resize." severity failure;
return NASULV;
end if;

-- No need to do anything
if s'length = new_size then
return s;
end if;

-- v'range is downto regardless of s'range
v := sr when s'ascending else s;

case method is
when truncate_LSBs =>
return s( s'high downto (s'length - new_size) );
r := v( v'left downto (v'left - (new_size - 1)) );
when truncate_MSBs =>
return s(new_size-1 downto 0);
r := v( (v'right + (new_size - 1)) downto v'right);
when extend_LSBs =>
v(v'high downto new_size - s'length) := s;
v(new_size - s'length - 1 downto 0) := (others => extension);
return v;
r(r'left downto (new_size - v'length)) := v;
r(r'left - v'length downto 0) := (others => extension);
when extend_MSBs =>
v(new_size-1 downto s'high+1) := (others => extension);
v(s'high downto 0) := s;
return v;
r(r'left downto v'length) := (others => extension);
r(v'length-1 downto 0) := v;
end case;


-- Choose the same range as input
if s'ascending then
return rr;
else
return r;
end if;
end function;

--## Resizizng function for unsigned number clearly stating how exactly the
--# resizing will be done. Extends numbers with zeros.
--# resizing will be done. Extends numbers with zeros. The leftmost bit is
--# treated as the most significant bit (like in NUMERIC_STD).
function change_size (s : u_unsigned; new_size : positive; method : resize_method)
return u_unsigned is
begin
Expand All @@ -300,15 +346,16 @@ package body sizing is

--## Resizizng function for signed number clearly stating how exactly the
--# resizing will be done. Extends most significant bits with a sign bit,
--# and least significant bits with zeros.
--# and least significant bits with zeros. The leftmost bit is treated as the
--# most significant bit (like in NUMERIC_STD).
function change_size (s : u_signed; new_size : positive; method : resize_method)
return u_signed is
begin

case method is
when extend_MSBs =>
return u_signed(
change_size(std_ulogic_vector(s), new_size, method, s(s'high)));
change_size(std_ulogic_vector(s), new_size, method, s(s'left)));
when others =>
return u_signed(
change_size(std_ulogic_vector(s), new_size, method, '0'));
Expand Down