Electronic – Working of resize function in VHDL

fpgastd-logic-vectorvhdl

I am using resize function as below to convert 32bit vector(temp2_32) to 16 bit vector(temp2).

temp2<=std_logic_vector(resize(to_sfixed(temp2_32,3,-28),1,-14));

When temp2_32 value is x"0002ad50", temp2 value is getting updated as x"000b".
In my understanding, while resizing first 16bits will be assigned to temp2 which is x"0002". But here the value updated for temp2 is x"000b". How is this value obtained? how does resize work?

Best Answer

Your assignment statement:

temp2<=std_logic_vector(resize(to_sfixed(temp2_32,3,-28),1,-14));

should cause a simulation error:

ghdl -r resize_function
./resize_function:error: bound check failure at resize_function.vhdl:12
in process .resize_function(foo).P0
./resize_function:error: simulation failed

This should be caused by the semantics of the type conversion to std_logic_vector (IEEE Std 1076-2008):

9.3.6 Type conversions (paragraphs 4 & 5)

If the type mark denotes a subtype, conversion consists of conversion to the target type followed by a check that the result of the conversion belongs to the subtype.

In certain cases, an implicit subtype conversion is performed. A subtype conversion involves a type conversion in which the target subtype is the subtype to which the operand is converted and the target type is the base type of the target subtype.

An explicit type conversion, an expression, is not the recipient of an implicit aubtype conversion. The check that the result of the conversion belongs to the subtype (std_logic_vector) should fail. The index type for std_logic_vector is natural which should fail for the right bounds of the resized sfixed value.

(That it doesn't in Vivado Simulator is somewhere between mildly disturbing and worrisome.)

The -2008 fixed_pkg package has a conversion routine to fix that:

library ieee;
use ieee.std_logic_1164.all;
use ieee.fixed_pkg.all;

entity resize_function is
end entity;

architecture foo of resize_function is
    constant temp2_32:  std_logic_vector := x"0002ad50";
    signal temp2:       std_logic_vector (15 downto 0);
begin
    -- temp2<=std_logic_vector(resize(to_sfixed(temp2_32,3,-28),1,-14));
    temp2 <= to_slv(resize(to_sfixed(temp2_32, 3, -28), 1, -14));
    
    process
    begin
        wait for 0 ns;
        report 
            LF & HT & "temp2_32 " & to_string (temp2_32) &
            LF & HT & "SFIXED " & to_string (to_sfixed(temp2_32, 3, -28)) &
            LF & HT & "RESIZE " &
                to_string(resize (to_sfixed(temp2_32, 3, -28), 1, -14)) &
            LF & HT & "temp2 "& to_string(temp2);
        wait;
    end process;
end architecture;
ghdl -r resize_function
resize_function.vhdl:18:9:@0ms:(report note):
    temp2_32 00000000000000101010110101010000
    SFIXED 0000.0000000000101010110101010000
    RESIZE 00.00000000001011
    temp2 0000000000001011

The resize function has parameters with default values:

unction resize (
    arg                     : UNRESOLVED_ufixed;  -- input
    constant left_index     : INTEGER;  -- integer portion
    constant right_index    : INTEGER;  -- size of fraction
    constant overflow_style : fixed_overflow_style_type := fixed_overflow_style;
    constant round_style    : fixed_round_style_type    := fixed_round_style)
    return UNRESOLVED_ufixed;

Where fixed_round_style is a generic in the fixed_pkg package declaration as part of instantiating fixed_pkg from package fixed_generic_pkg.

The resize is rounded by default (the last if statement before return result;).

You can examine other values of fixed_round_style_type (fixed_truncate defined in fixed_float_types package which can be made directly visible with a use clause) and see if that will provide an answer you find more palatable.

temp2 <= to_slv(resize(to_sfixed(temp2_32, 3, -28), 1, -14, fixed_overflow_style, fixed_truncate));

It gives the result:

ghdl -r resize_function
resize_function.vhdl:19:9:@0ms:(report note):
    temp2_32 00000000000000101010110101010000
    SFIXED 0000.0000000000101010110101010000
    RESIZE 00.00000000001011
    temp2 0000000000001010

Where the report statement with text RESIZE shows the rounded value and the truncated value is assigned to temp2.

The source for these packages is part of the standard (-2008 onward) and can be downloaded from the IEEE-SA.

https://standards.ieee.org/downloads.html

https://standards.ieee.org/content/dam/ieee-standards/standards/web/download/1076-2008_downloads.zip (-2008).

The source for the libraries can be found for the -2019 revision elsewhere.

The -2008 link is provided here because the link found in the standard text is no longer accurate.