diff --git a/libraries/base/common/src/vhdl/common_pkg.vhd b/libraries/base/common/src/vhdl/common_pkg.vhd index bb74671548ee892e30be6b39f504f8de69a312b8..9d4be12f077a5624612486010b5bbfd3e1ee47ff 100644 --- a/libraries/base/common/src/vhdl/common_pkg.vhd +++ b/libraries/base/common/src/vhdl/common_pkg.vhd @@ -366,6 +366,7 @@ PACKAGE common_pkg IS FUNCTION TO_UREAL(uvec : STD_LOGIC_VECTOR) RETURN REAL; -- convert unsigned slv of any length to REAL FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR) RETURN REAL; -- convert signed slv of any length to REAL + FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL; -- convert signed fixed point slv of any length, and with fixed point resolution of 2**resolution_w, to REAL -- The RESIZE for SIGNED in IEEE.NUMERIC_STD extends the sign bit or it keeps the sign bit and LS part. This -- behaviour of preserving the sign bit is less suitable for DSP and not necessary in general. A more @@ -1758,12 +1759,12 @@ PACKAGE BODY common_pkg IS END; FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR) RETURN REAL IS - CONSTANT c_len : NATURAL := svec'LENGTH; + CONSTANT c_len : NATURAL := svec'LENGTH + 1; -- use +1 so the v_uvec can also fit abs() of most negative is -1 * -2**(c_len-1) VARIABLE v_pos : BOOLEAN := TRUE; - VARIABLE v_uvec : STD_LOGIC_VECTOR(c_len-1 DOWNTO 0) := svec; + VARIABLE v_uvec : STD_LOGIC_VECTOR(c_len-1 DOWNTO 0) := RESIZE_SVEC(svec, c_len); VARIABLE v_real : REAL := 0.0; BEGIN - -- Negate svec to have positive v_uvec. The v_uvec can also fit -1 * -2**(c_len-1) + -- Negate svec to have positive v_uvec. IF SIGNED(svec) < 0 THEN v_pos := FALSE; v_uvec := INCR_UVEC(NOT svec, 1); -- negate the svec to make it positive @@ -1777,6 +1778,17 @@ PACKAGE BODY common_pkg IS RETURN -v_real; END IF; END; + + FUNCTION TO_SREAL(svec : STD_LOGIC_VECTOR; resolution_w : INTEGER) RETURN REAL IS + VARIABLE v_real : REAL := TO_SREAL(svec); -- first convert as signed integer + BEGIN + -- The resolution_w is the number of bits that LSbit 0 in svec is after or before the fixed point. + -- The real value is then scaled by scaling the integer value by 2**resolution_w: + -- . resolution_w = 0 : scale by 2**0 = 1, so no scaling and the value is treated as an integer + -- . resolution_w < 0 : scale up + -- . resolution_w > 0 : scale down + RETURN v_real * 2.0**REAL(resolution_w); + END; FUNCTION RESIZE_NUM(u : UNSIGNED; w : NATURAL) RETURN UNSIGNED IS BEGIN