Select Git revision
run_altera_simlib_comp
-
Eric Kooistra authoredEric Kooistra authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tb_common_to_sreal.vhd 8.42 KiB
-- --------------------------------------------------------------------------
-- Copyright 2021
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
--
-- Author: E. Kooistra, 13 okt 2021
-- Purpose: Verify to_sreal() and to_svec() from common_pkg.vhd
-- Description:
-- The tb shows how a REAL value is represented by a fixed point SLV. The
-- signed REAL value is denoted as s(w, p) as defined and explained in []:
--
-- s = sign bit, value +1 or -1
-- w = width in number of bits of the SLV
-- p = position of the fixed point in the SLV, p = 0 for integers, p > 0
-- for p bit fraction, p < 0 for scale factor 2**p
--
-- The resolution of the REAL value is r = 1/2**p.
--
-- . to_svec() converts a fixed point INTEGER or SLV into a REAL value
-- . to_sreal() converts a REAL value into a fixed point SLV or INTEGER
--
-- The tb verifies that a_slv(w-1:0) = to_svec(to_sreal(a_slv(w-1:0))).
--
-- References:
-- [1] https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+Definition+of+fixed+point+numbers
--
-- Usage:
-- > as 5, observe signals with radix decimal
-- > run -all
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.MATH_REAL.ALL;
USE work.common_pkg.ALL;
ENTITY tb_common_to_sreal IS
END tb_common_to_sreal;
ARCHITECTURE tb OF tb_common_to_sreal IS
CONSTANT clk_period : TIME := 10 ns;
CONSTANT c_resolution_w : NATURAL := 5;
CONSTANT c_width : NATURAL := 4;
CONSTANT c_min : INTEGER := -2**(c_width-1);
CONSTANT c_max : INTEGER := 2**(c_width-1)-1;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL a_real : REAL := 0.0;
SIGNAL a_sint : INTEGER := 0;
SIGNAL a_slv : STD_LOGIC_VECTOR(c_width-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL dbg_resolution_w : INTEGER := 0;
SIGNAL dbg_resolution : REAL := 0.0;
PROCEDURE proc_wait_some_cycles(SIGNAL clk : IN STD_LOGIC;
c_nof_cycles : IN NATURAL) IS
BEGIN
FOR I IN 0 TO c_nof_cycles-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
END proc_wait_some_cycles;
BEGIN
-- Stimuli
clk <= NOT clk OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER 3*clk_period;
-- Testbench end
p_tb : PROCESS
VARIABLE v_slv : STD_LOGIC_VECTOR(c_width-1 DOWNTO 0) := (OTHERS => '0');
VARIABLE v_real : REAL;
BEGIN
-- Simulator evaluates process until first WAIT at startup 0 ps, but
-- simulator does not recognise WAIT in proc_wait_some_cycles() then.
-- Therefore add WAIT here to avoid ASSERT messages that occur later.
WAIT UNTIL rising_edge(clk);
proc_wait_some_cycles(clk, 10);
-- Try all v_slv for c_width and resolutions beyond c_width
FOR R IN -c_resolution_w TO c_resolution_w LOOP
dbg_resolution_w <= R;
dbg_resolution <= 1.0 / 2.0**REAL(R);
FOR I IN c_min TO c_max LOOP
v_slv := TO_SVEC(I, c_width);
-- Convert fixed point v_slv with binary point at resolution width R, to real and back to slv
v_real := TO_SREAL(v_slv, R);
-- Show as signals in Wave window
a_real <= v_real;
a_sint <= TO_SINT(v_real, c_width, R);
a_slv <= TO_SVEC(v_real, c_width, R);
WAIT UNTIL rising_edge(clk);
-- Verify
ASSERT a_sint = I REPORT "Wrong REAL to INTEGER conversion for I = " & INTEGER'IMAGE(I) SEVERITY ERROR;
ASSERT a_slv = v_slv REPORT "Wrong REAL to SLV conversion for I = " & INTEGER'IMAGE(I) SEVERITY ERROR;
END LOOP;
proc_wait_some_cycles(clk, 10);
END LOOP;
proc_wait_some_cycles(clk, 10);
-- Try overflow
-- . No overflow with 4 bit integers for -16.49 : +15.49
v_real := -9.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -9.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -8.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -8.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -7.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -7.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -6.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -6.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 6.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 6.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 7.49; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 7.51; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
proc_wait_some_cycles(clk, 5);
-- . Just overflow with 4 bit integers for -16.5 : +15.5
v_real := -15.5; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 15.5; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
proc_wait_some_cycles(clk, 5);
-- . Large overflow with 4 bit integers for << -16.5 : >> +15.5
v_real := -18.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 18.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -28.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 28.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -38.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 38.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -48.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 48.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -58.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 58.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := -68.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
v_real := 68.0; a_real <= v_real; a_sint <= TO_SINT(v_real, 4, 0); a_slv <= TO_SVEC(v_real, 4, 0); WAIT UNTIL rising_edge(clk);
proc_wait_some_cycles(clk, 10);
tb_end <= '1';
WAIT;
END PROCESS;
-- TO_SINT() and TO_SVEC() must always yield same result
ASSERT a_sint = TO_SINT(a_slv) REPORT "Unexpected difference between TO_SINT() and TO_SVEC() :" & INTEGER'IMAGE(a_sint) & " /= " & INTEGER'IMAGE(TO_SINT(a_slv));
END tb;