aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2015-09-10 20:24:33 +0200
committerTristan Gingold <tgingold@free.fr>2015-09-10 20:24:33 +0200
commita67ae38eeedd5d0ca5a75b8174aed201e5c801ad (patch)
tree9e24b723ab5c8d0d46041433bb3154ffed4527b4
parent0e257fe7341a44f097ea282c0cbabda42f4ecc41 (diff)
downloadghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.tar.gz
ghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.tar.bz2
ghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.zip
Add bug019 testcase.
-rw-r--r--testsuite/gna/bug019/PoC/.gitignore38
-rw-r--r--testsuite/gna/bug019/PoC/src/common/components.vhdl310
-rw-r--r--testsuite/gna/bug019/PoC/src/common/config.vhdl962
-rw-r--r--testsuite/gna/bug019/PoC/src/common/debug.vhdl87
-rw-r--r--testsuite/gna/bug019/PoC/src/common/fileio.vhdl93
-rw-r--r--testsuite/gna/bug019/PoC/src/common/my_config.vhdl.template58
-rw-r--r--testsuite/gna/bug019/PoC/src/common/my_project.vhdl.template52
-rw-r--r--testsuite/gna/bug019/PoC/src/common/physical.vhdl1014
-rw-r--r--testsuite/gna/bug019/PoC/src/common/strings.vhdl899
-rw-r--r--testsuite/gna/bug019/PoC/src/common/utils.vhdl946
-rw-r--r--testsuite/gna/bug019/PoC/src/common/vectors.vhdl764
-rw-r--r--testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl155
-rw-r--r--testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl108
-rw-r--r--testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl320
-rw-r--r--testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl174
-rw-r--r--testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl140
-rw-r--r--testsuite/gna/bug019/PoC/tb/.gitignore2
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/config_tb.vhdl76
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/my_config_ML505.vhdl48
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/my_config_ML605.vhdl50
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/my_project.vhdl52
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/simulation.v08.vhdl363
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/simulation.v93.vhdl308
-rw-r--r--testsuite/gna/bug019/PoC/tb/common/strings_tb.vhdl123
-rw-r--r--testsuite/gna/bug019/PoC/tb/io/uart/uart_rx_tb.vhdl141
-rw-r--r--testsuite/gna/bug019/repro.vhdl43
-rw-r--r--testsuite/gna/bug019/repro1.vhdl51
-rwxr-xr-xtestsuite/gna/bug019/testsuite.sh25
28 files changed, 7402 insertions, 0 deletions
diff --git a/testsuite/gna/bug019/PoC/.gitignore b/testsuite/gna/bug019/PoC/.gitignore
new file mode 100644
index 000000000..2c619f647
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/.gitignore
@@ -0,0 +1,38 @@
+# general file excludes
+~*.tmp
+~*.docx
+*.fmt
+*~
+*.o
+~$*
+
+# ignore Python caches
+__pycache__
+
+# ignore files in netlist/
+/netlist/
+!/netlist/configuration.ini
+!/netlist/netlist.ps1
+!/netlist/netlist.sh
+!/netlist/template.cgc
+
+# ignore folders
+temp/
+vSim/
+
+# ignore files from PoC
+/tb/common/my_project.vhdl
+/py/config.private.ini
+
+# ignore Quartus files
+other/quartus/*/db/
+other/quartus/*/incremental_db/
+other/quartus/*/output_files/
+other/quartus/*/simulation/
+other/quartus/*/*.rpt
+other/quartus/*/*.qws
+other/quartus/*/*.bak
+
+# general whitelist
+!.publish
+!.git*
diff --git a/testsuite/gna/bug019/PoC/src/common/components.vhdl b/testsuite/gna/bug019/PoC/src/common/components.vhdl
new file mode 100644
index 000000000..1252edc19
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/components.vhdl
@@ -0,0 +1,310 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Patrick Lehmann
+--
+-- Package: Common primitives described as a function
+--
+-- Description:
+-- ------------------------------------
+-- This packages describes common primitives like flip flops and multiplexers
+-- as a function to use them as one-liners.
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.NUMERIC_STD.all;
+
+library PoC;
+use PoC.utils.all;
+
+
+PACKAGE components IS
+ -- FlipFlop functions
+ function ffdre(q : STD_LOGIC; d : STD_LOGIC; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC; -- D-FlipFlop with reset and enable
+ function ffdre(q : STD_LOGIC_VECTOR; d : STD_LOGIC_VECTOR; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC_VECTOR; -- D-FlipFlop with reset and enable
+ function ffdse(q : STD_LOGIC; d : STD_LOGIC; set : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC; -- D-FlipFlop with set and enable
+ function fftre(q : STD_LOGIC; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC; -- T-FlipFlop with reset and enable
+ function ffrs(q : STD_LOGIC; rst : STD_LOGIC := '0'; set : STD_LOGIC := '0') return STD_LOGIC; -- RS-FlipFlop with dominant rst
+ function ffsr(q : STD_LOGIC; rst : STD_LOGIC := '0'; set : STD_LOGIC := '0') return STD_LOGIC; -- RS-FlipFlop with dominant set
+
+ -- adder
+ function inc(value : STD_LOGIC_VECTOR; increment : NATURAL := 1) return STD_LOGIC_VECTOR;
+ function inc(value : UNSIGNED; increment : NATURAL := 1) return UNSIGNED;
+ function inc(value : SIGNED; increment : NATURAL := 1) return SIGNED;
+ function dec(value : STD_LOGIC_VECTOR; decrement : NATURAL := 1) return STD_LOGIC_VECTOR;
+ function dec(value : UNSIGNED; decrement : NATURAL := 1) return UNSIGNED;
+ function dec(value : SIGNED; decrement : NATURAL := 1) return SIGNED;
+
+ -- negate
+ function neg(value : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; -- calculate 2's complement
+
+ -- counter
+ function upcounter_next(cnt : UNSIGNED; rst : STD_LOGIC; en : STD_LOGIC := '1'; init : NATURAL := 0) return UNSIGNED;
+ function upcounter_equal(cnt : UNSIGNED; value : NATURAL) return STD_LOGIC;
+ function downcounter_next(cnt : SIGNED; rst : STD_LOGIC; en : STD_LOGIC := '1'; init : INTEGER := 0) return SIGNED;
+ function downcounter_equal(cnt : SIGNED; value : INTEGER) return STD_LOGIC;
+ function downcounter_neg(cnt : SIGNED) return STD_LOGIC;
+
+ -- shift/rotate registers
+ function sr_left(q : STD_LOGIC_VECTOR; i : STD_LOGIC) return STD_LOGIC_VECTOR;
+ function sr_right(q : STD_LOGIC_VECTOR; i : STD_LOGIC) return STD_LOGIC_VECTOR;
+ function rr_left(q : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
+ function rr_right(q : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
+
+ -- compare
+ function comp(value1 : STD_LOGIC_VECTOR; value2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
+ function comp(value1 : UNSIGNED; value2 : UNSIGNED) return UNSIGNED;
+ function comp(value1 : SIGNED; value2 : SIGNED) return SIGNED;
+ function comp_allzero(value : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function comp_allzero(value : UNSIGNED) return STD_LOGIC;
+ function comp_allzero(value : SIGNED) return STD_LOGIC;
+ function comp_allone(value : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function comp_allone(value : UNSIGNED) return STD_LOGIC;
+ function comp_allone(value : SIGNED) return STD_LOGIC;
+
+ -- multiplexing
+ function mux(sel : STD_LOGIC; sl0 : STD_LOGIC; sl1 : STD_LOGIC) return STD_LOGIC;
+ function mux(sel : STD_LOGIC; slv0 : STD_LOGIC_VECTOR; slv1 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
+ function mux(sel : STD_LOGIC; us0 : UNSIGNED; us1 : UNSIGNED) return UNSIGNED;
+ function mux(sel : STD_LOGIC; s0 : SIGNED; s1 : SIGNED) return SIGNED;
+end;
+
+
+package body components is
+ -- d-flipflop with reset and enable
+ function ffdre(q : STD_LOGIC; d : STD_LOGIC; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC is
+ begin
+ return ((d and en) or (q and not en)) and not rst;
+ end function;
+
+ function ffdre(q : STD_LOGIC_VECTOR; d : STD_LOGIC_VECTOR; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC_VECTOR is
+ begin
+ return ((d and (q'range => en)) or (q and not (q'range => en))) and not (q'range => rst);
+ end function;
+
+ -- d-flipflop with set and enable
+ function ffdse(q : STD_LOGIC; d : STD_LOGIC; set : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC is
+ begin
+ return ((d and en) or (q and not en)) or set;
+ end function;
+
+ -- t-flipflop with reset and enable
+ function fftre(q : STD_LOGIC; rst : STD_LOGIC := '0'; en : STD_LOGIC := '1') return STD_LOGIC is
+ begin
+ return ((not q and en) or (q and not en)) and not rst;
+ end function;
+
+ -- rs-flipflop with dominant rst
+ function ffrs(q : STD_LOGIC; rst : STD_LOGIC := '0'; set : STD_LOGIC := '0') return STD_LOGIC is
+ begin
+ return (q or set) and not rst;
+ end function;
+
+ -- rs-flipflop with dominant set
+ function ffsr(q : STD_LOGIC; rst : STD_LOGIC := '0'; set : STD_LOGIC := '0') return STD_LOGIC is
+ begin
+ return (q and not rst) or set;
+ end function;
+
+ -- adder
+ function inc(value : STD_LOGIC_VECTOR; increment : NATURAL := 1) return STD_LOGIC_VECTOR is
+ begin
+ return std_logic_vector(inc(unsigned(value), increment));
+ end function;
+
+ function inc(value : UNSIGNED; increment : NATURAL := 1) return UNSIGNED is
+ begin
+ return value + increment;
+ end function;
+
+ function inc(value : SIGNED; increment : NATURAL := 1) return SIGNED is
+ begin
+ return value + increment;
+ end function;
+
+ function dec(value : STD_LOGIC_VECTOR; decrement : NATURAL := 1) return STD_LOGIC_VECTOR is
+ begin
+ return std_logic_vector(dec(unsigned(value), decrement));
+ end function;
+
+ function dec(value : UNSIGNED; decrement : NATURAL := 1) return UNSIGNED is
+ begin
+ return value + decrement;
+ end function;
+
+ function dec(value : SIGNED; decrement : NATURAL := 1) return SIGNED is
+ begin
+ return value + decrement;
+ end function;
+
+ -- negate
+ function neg(value : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ return std_logic_vector(inc(unsigned(not value))); -- 2's complement
+ end function;
+
+ -- counter
+ function upcounter_next(cnt : UNSIGNED; rst : STD_LOGIC; en : STD_LOGIC := '1'; init : NATURAL := 0) return UNSIGNED is
+ begin
+ if (rst = '1') then
+ return to_unsigned(init, cnt'length);
+ elsif (en = '1') then
+ return cnt + 1;
+ else
+ return cnt;
+ end if;
+ end function;
+
+ function upcounter_equal(cnt : UNSIGNED; value : NATURAL) return STD_LOGIC is
+ begin
+ -- optimized comparison for only up counting values
+ return to_sl((cnt and to_unsigned(value, cnt'length)) = value);
+ end function;
+
+ function downcounter_next(cnt : SIGNED; rst : STD_LOGIC; en : STD_LOGIC := '1'; init : INTEGER := 0) return SIGNED is
+ begin
+ if (rst = '1') then
+ return to_signed(init, cnt'length);
+ elsif (en = '1') then
+ return cnt - 1;
+ else
+ return cnt;
+ end if;
+ end function;
+
+ function downcounter_equal(cnt : SIGNED; value : INTEGER) return STD_LOGIC is
+ begin
+ -- optimized comparison for only down counting values
+ return to_sl((cnt nor to_signed(value, cnt'length)) /= value);
+ end function;
+
+ function downcounter_neg(cnt : SIGNED) return STD_LOGIC is
+ begin
+ return cnt(cnt'high);
+ end function;
+
+ -- shift/rotate registers
+ function sr_left(q : STD_LOGIC_VECTOR; i : std_logic) return STD_LOGIC_VECTOR is
+ begin
+ return q(q'left - 1 downto q'right) & i;
+ end function;
+
+ function sr_right(q : STD_LOGIC_VECTOR; i : std_logic) return STD_LOGIC_VECTOR is
+ begin
+ return i & q(q'left downto q'right - 1);
+ end function;
+
+ function rr_left(q : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ return q(q'left - 1 downto q'right) & q(q'left);
+ end function;
+
+ function rr_right(q : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ return q(q'right) & q(q'left downto q'right - 1);
+ end function;
+
+ -- compare functions
+ -- return value 1- => value1 < value2 (difference is negative)
+ -- return value 00 => value1 = value2 (difference is zero)
+ -- return value -1 => value1 > value2 (difference is positive)
+ function comp(value1 : STD_LOGIC_VECTOR; value2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ report "Comparing two STD_LOGIC_VECTORs - implicit conversion to UNSIGNED" severity WARNING;
+ return std_logic_vector(comp(unsigned(value1), unsigned(value2)));
+ end function;
+
+ function comp(value1 : UNSIGNED; value2 : UNSIGNED) return UNSIGNED is
+ begin
+ if (value1 < value2) then
+ return "10";
+ elsif (value1 = value2) then
+ return "00";
+ else
+ return "01";
+ end if;
+ end function;
+
+ function comp(value1 : SIGNED; value2 : SIGNED) return SIGNED is
+ begin
+ if (value1 < value2) then
+ return "10";
+ elsif (value1 = value2) then
+ return "00";
+ else
+ return "01";
+ end if;
+ end function;
+
+ function comp_allzero(value : STD_LOGIC_VECTOR) return STD_LOGIC is
+ begin
+ return comp_allzero(unsigned(value));
+ end function;
+
+ function comp_allzero(value : UNSIGNED) return STD_LOGIC is
+ begin
+ return to_sl(value = (value'range => '0'));
+ end function;
+
+ function comp_allzero(value : SIGNED) return STD_LOGIC is
+ begin
+ return to_sl(value = (value'range => '0'));
+ end function;
+
+ function comp_allone(value : STD_LOGIC_VECTOR) return STD_LOGIC is
+ begin
+ return comp_allone(unsigned(value));
+ end function;
+
+ function comp_allone(value : UNSIGNED) return STD_LOGIC is
+ begin
+ return to_sl(value = (value'range => '1'));
+ end function;
+
+ function comp_allone(value : SIGNED) return STD_LOGIC is
+ begin
+ return to_sl(value = (value'range => '1'));
+ end function;
+
+
+ -- multiplexing
+ function mux(sel : STD_LOGIC; sl0 : STD_LOGIC; sl1 : STD_LOGIC) return STD_LOGIC is
+ begin
+ return (sl0 and not sel) or (sl1 and sel);
+ end function;
+
+ function mux(sel : STD_LOGIC; slv0 : STD_LOGIC_VECTOR; slv1 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ return (slv0 and not (slv0'range => sel)) or (slv1 and (slv1'range => sel));
+ end function;
+
+ function mux(sel : STD_LOGIC; us0 : UNSIGNED; us1 : UNSIGNED) return UNSIGNED is
+ begin
+ return (us0 and not (us0'range => sel)) or (us1 and (us1'range => sel));
+ end function;
+
+ function mux(sel : STD_LOGIC; s0 : SIGNED; s1 : SIGNED) return SIGNED is
+ begin
+ return (s0 and not (s0'range => sel)) or (s1 and (s1'range => sel));
+ end function;
+END PACKAGE BODY; \ No newline at end of file
diff --git a/testsuite/gna/bug019/PoC/src/common/config.vhdl b/testsuite/gna/bug019/PoC/src/common/config.vhdl
new file mode 100644
index 000000000..62536286b
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/config.vhdl
@@ -0,0 +1,962 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Global configuration settings.
+--
+-- Description:
+-- ------------------------------------
+-- This file evaluates the settings declared in the project specific package my_config.
+-- See also template file my_config.vhdl.template.
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.my_config.all;
+use PoC.my_project.all;
+use PoC.utils.all;
+
+
+package config is
+ constant PROJECT_DIR : string := MY_PROJECT_DIR;
+ constant OPERATING_SYSTEM : string := MY_OPERATING_SYSTEM;
+
+ -- TODO:
+ -- ===========================================================================
+ subtype T_BOARD_STRING is STRING(1 to 8);
+ subtype T_BOARD_CONFIG_STRING8 is STRING(1 to 8);
+ subtype T_BOARD_CONFIG_STRING16 is STRING(1 to 16);
+ subtype T_BOARD_CONFIG_STRING32 is STRING(1 to 32);
+-- subtype T_BOARD_CONFIG_STRING64 is STRING(1 to 64);
+ subtype T_DEVICE_STRING is STRING(1 to 32);
+
+ constant C_BOARD_STRING_EMPTY : T_BOARD_STRING;
+ constant C_BOARD_CONFIG_STRING8_EMPTY : T_BOARD_CONFIG_STRING8;
+ constant C_BOARD_CONFIG_STRING16_EMPTY : T_BOARD_CONFIG_STRING16;
+ constant C_BOARD_CONFIG_STRING32_EMPTY : T_BOARD_CONFIG_STRING32;
+-- constant C_BOARD_CONFIG_STRING64_EMPTY : T_BOARD_CONFIG_STRING64;
+ constant C_DEVICE_STRING_EMPTY : T_DEVICE_STRING;
+
+ -- List of known boards
+ -- ---------------------------------------------------------------------------
+ type T_BOARD is (
+ BOARD_CUSTOM,
+ -- Spartan-3 boards
+ BOARD_S3SK200, BOARD_S3SK1000,
+ BOARD_S3ESK500, BOARD_S3ESK1600,
+ -- Spartan-6 boards
+ BOARD_ATLYS,
+ -- Kintex-7 boards
+ BOARD_KC705,
+ -- Virtex-5 boards
+ BOARD_ML505,
+ -- Virtex-6 boards
+ BOARD_ML605,
+ -- Virtex-7 boards
+ BOARD_VC707,
+ -- Zynq-7000 boards
+ BOARD_ZEDBOARD,
+ -- Cyclon III boards
+ BOARD_DE0,
+ -- Stratix II boards
+ BOARD_S2GXAV,
+ -- Stratix IV boards
+ BOARD_DE4,
+ -- Stratix V boards
+ BOARD_DE5
+ );
+
+ -- List of known FPGA / Chip vendors
+ -- ---------------------------------------------------------------------------
+ type T_VENDOR is (
+ VENDOR_ALTERA,
+ VENDOR_LATTICE,
+ VENDOR_XILINX
+ );
+ subtype vendor_t is T_VENDOR;
+
+ -- List of known synthesis tool chains
+ -- ---------------------------------------------------------------------------
+ type T_SYNTHESIS_TOOL is (
+ SYNTHESIS_TOOL_ALTERA_QUARTUS2,
+ SYNTHESIS_TOOL_SYNOPSIS,
+ SYNTHESIS_TOOL_XILINX_XST,
+ SYNTHESIS_TOOL_XILINX_VIVADO
+ );
+
+ -- List of known devices
+ -- ---------------------------------------------------------------------------
+ type T_DEVICE is (
+ DEVICE_SPARTAN3, DEVICE_SPARTAN6, -- Xilinx.Spartan
+ DEVICE_ZYNQ7, -- Xilinx.Zynq
+ DEVICE_ARTIX7, -- Xilinx.Artix
+ DEVICE_KINTEX7, -- Xilinx.Kintex
+ DEVICE_VIRTEX5, DEVICE_VIRTEX6, DEVICE_VIRTEX7, -- Xilinx.Virtex
+
+ DEVICE_CYCLONE1, DEVICE_CYCLONE2, DEVICE_CYCLONE3, -- Altera.Cyclone
+ DEVICE_STRATIX1, DEVICE_STRATIX2, DEVICE_STRATIX4, DEVICE_STRATIX5 -- Altera.Stratix
+ );
+ subtype device_t is T_DEVICE;
+
+ -- List of known device families
+ -- ---------------------------------------------------------------------------
+ type T_DEVICE_FAMILY is (
+ -- Xilinx
+ DEVICE_FAMILY_SPARTAN,
+ DEVICE_FAMILY_ZYNQ,
+ DEVICE_FAMILY_ARTIX,
+ DEVICE_FAMILY_KINTEX,
+ DEVICE_FAMILY_VIRTEX,
+
+ DEVICE_FAMILY_CYCLONE,
+ DEVICE_FAMILY_STRATIX
+ );
+
+ -- List of known device subtypes
+ -- ---------------------------------------------------------------------------
+ type T_DEVICE_SUBTYPE is (
+ DEVICE_SUBTYPE_NONE,
+ -- Xilinx
+ DEVICE_SUBTYPE_X,
+ DEVICE_SUBTYPE_T,
+ DEVICE_SUBTYPE_XT,
+ DEVICE_SUBTYPE_HT,
+ DEVICE_SUBTYPE_LX,
+ DEVICE_SUBTYPE_SXT,
+ DEVICE_SUBTYPE_LXT,
+ DEVICE_SUBTYPE_TXT,
+ DEVICE_SUBTYPE_FXT,
+ DEVICE_SUBTYPE_CXT,
+ DEVICE_SUBTYPE_HXT,
+ -- Altera
+ DEVICE_SUBTYPE_E,
+ DEVICE_SUBTYPE_GS,
+ DEVICE_SUBTYPE_GX,
+ DEVICE_SUBTYPE_GT
+ );
+
+ -- List of known transceiver (sub-)types
+ -- ---------------------------------------------------------------------------
+ type T_TRANSCEIVER is (
+ TRANSCEIVER_GTP_DUAL, TRANSCEIVER_GTPE1, TRANSCEIVER_GTPE2, -- Xilinx GTP transceivers
+ TRANSCEIVER_GTX, TRANSCEIVER_GTXE1, TRANSCEIVER_GTXE2, -- Xilinx GTX transceivers
+ TRANSCEIVER_GTH, TRANSCEIVER_GTHE1, TRANSCEIVER_GTHE2, -- Xilinx GTH transceivers
+ TRANSCEIVER_GTZ, -- Xilinx GTZ transceivers
+
+ -- TODO: add Altera transceivers
+ TRANSCEIVER_GXB, -- Altera GXB transceiver
+
+ TRANSCEIVER_NONE
+ );
+
+ -- Properties of an FPGA architecture
+ -- ===========================================================================
+ type T_DEVICE_INFO is record
+ Vendor : T_VENDOR;
+ Device : T_DEVICE;
+ DevFamily : T_DEVICE_FAMILY;
+ DevNumber : natural;
+ DevSubType : T_DEVICE_SUBTYPE;
+ DevSeries : natural;
+
+ TransceiverType : T_TRANSCEIVER;
+ LUT_FanIn : positive;
+ end record;
+
+ -- Data structures to describe UART / RS232
+ type T_BOARD_UART_DESC is record
+ IsDTE : BOOLEAN; -- Data terminal Equipment (e.g. PC, Printer)
+ FlowControl : T_BOARD_CONFIG_STRING16; -- (NONE, SW, HW_CTS_RTS, HW_RTR_RTS)
+ BaudRate : T_BOARD_CONFIG_STRING16; -- e.g. "115.2 kBd"
+ BaudRate_Max : T_BOARD_CONFIG_STRING16;
+ end record;
+
+ -- Data structures to describe Ethernet
+ type T_BOARD_ETHERNET_DESC is record
+ IPStyle : T_BOARD_CONFIG_STRING8;
+ RS_DataInterface : T_BOARD_CONFIG_STRING8;
+ PHY_Device : T_BOARD_CONFIG_STRING16;
+ PHY_DeviceAddress : STD_LOGIC_VECTOR(7 downto 0);
+ PHY_DataInterface : T_BOARD_CONFIG_STRING8;
+ PHY_ManagementInterface : T_BOARD_CONFIG_STRING16;
+ end record;
+
+ subtype T_BOARD_ETHERNET_DESC_INDEX is NATURAL range 0 to 7;
+ type T_BOARD_ETHERNET_DESC_VECTOR is array(NATURAL range <>) of T_BOARD_ETHERNET_DESC;
+
+ -- Data structures to describe a board layout
+ type T_BOARD_INFO is record
+ FPGADevice : T_DEVICE_STRING;
+ UART : T_BOARD_UART_DESC;
+ Ethernet : T_BOARD_ETHERNET_DESC_VECTOR(T_BOARD_ETHERNET_DESC_INDEX);
+ EthernetCount : T_BOARD_ETHERNET_DESC_INDEX;
+ end record;
+
+ type T_BOARD_INFO_VECTOR is array (T_BOARD) of T_BOARD_INFO;
+
+ -- QUESTION: replace archprops with DEVICE_INFO ?
+ type archprops_t is record
+ LUT_K : positive; -- LUT Fanin
+ end record;
+
+ -- Functions extracting board and PCB properties from "MY_BOARD"
+ -- which is declared in package "my_config".
+ -- ===========================================================================
+ function BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY) return T_BOARD;
+ function BOARD_INFO(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return T_BOARD_INFO;
+ function BOARD_DEVICE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING;
+ function BOARD_UART_BAUDRATE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING;
+
+ -- Functions extracting device and architecture properties from "MY_DEVICE"
+ -- which is declared in package "my_config".
+ -- ===========================================================================
+ function VENDOR(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_VENDOR;
+ function SYNTHESIS_TOOL(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_SYNTHESIS_TOOL;
+ function DEVICE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE;
+ function DEVICE_FAMILY(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_FAMILY;
+ function DEVICE_NUMBER(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural;
+ function DEVICE_SUBTYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_SUBTYPE;
+ function DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural;
+
+ function TRANSCEIVER_TYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_TRANSCEIVER;
+ function LUT_FANIN(DeviceString : string := C_DEVICE_STRING_EMPTY) return positive;
+
+ function DEVICE_INFO(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_INFO;
+
+ function ARCH_PROPS return archprops_t;
+
+ -- force FSM to predefined encoding in debug mode
+ function getFSMEncoding_gray(debug : BOOLEAN) return STRING;
+end package;
+
+
+package body config is
+ -- private functions required by board description
+ -- ModelSim requires that this functions is defined before it is used below.
+ -- ===========================================================================
+ function ite(cond : BOOLEAN; value1 : CHARACTER; value2 : CHARACTER) return CHARACTER is
+ begin
+ if cond then return value1; else return value2; end if;
+ end function;
+
+ -- default fill and string termination character for fixed size strings
+ -- ===========================================================================
+ constant C_POC_NUL : CHARACTER := '`';
+
+ -- deferred constant
+ -- ===========================================================================
+ constant C_BOARD_STRING_EMPTY : T_BOARD_STRING := (others => C_POC_NUL);
+ constant C_BOARD_CONFIG_STRING8_EMPTY : T_BOARD_CONFIG_STRING8 := (others => C_POC_NUL);
+ constant C_BOARD_CONFIG_STRING16_EMPTY : T_BOARD_CONFIG_STRING16 := (others => C_POC_NUL);
+ constant C_BOARD_CONFIG_STRING32_EMPTY : T_BOARD_CONFIG_STRING32 := (others => C_POC_NUL);
+ constant C_DEVICE_STRING_EMPTY : T_DEVICE_STRING := (others => C_POC_NUL);
+
+
+ -- chr_is* function
+ function chr_isDigit(chr : CHARACTER) return boolean is
+ begin
+ return ((CHARACTER'pos('0') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('9')));
+ end function;
+
+ function chr_isAlpha(chr : character) return boolean is
+ begin
+ return (((CHARACTER'pos('a') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('z'))) or
+ ((CHARACTER'pos('A') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('Z'))));
+ end function;
+
+ function str_length(str : STRING) return NATURAL is
+ begin
+ for i in str'range loop
+ if (str(i) = C_POC_NUL) then
+ return i - str'low;
+ end if;
+ end loop;
+ return str'length;
+ end function;
+
+ function str_trim(str : STRING) return STRING is
+ begin
+ return str(str'low to str'low + str_length(str) - 1);
+ end function;
+
+ function str_imatch(str1 : STRING; str2 : STRING) return BOOLEAN is
+ constant len : NATURAL := imin(str1'length, str2'length);
+ variable chr1 : CHARACTER;
+ variable chr2 : CHARACTER;
+ begin
+ -- if both strings are empty
+ if ((str1'length = 0 ) and (str2'length = 0)) then return TRUE; end if;
+ -- compare char by char
+ for i in str1'low to str1'low + len - 1 loop
+ chr1 := str1(i);
+ chr2 := str2(str2'low + (i - str1'low ));
+ if (CHARACTER'pos('A') <= CHARACTER'pos(chr1)) and (CHARACTER'pos(chr1) <= CHARACTER'pos('Z')) then
+ chr1 := CHARACTER'val(CHARACTER'pos(chr1) - CHARACTER'pos('A') + CHARACTER'pos('a'));
+ end if;
+ if (CHARACTER'pos('A') <= CHARACTER'pos(chr2)) and (CHARACTER'pos(chr2) <= CHARACTER'pos('Z')) then
+ chr2 := CHARACTER'val(CHARACTER'pos(chr2) - CHARACTER'pos('A') + CHARACTER'pos('a'));
+ end if;
+ if (chr1 /= chr2) then
+ return FALSE;
+ elsif ((chr1 = C_POC_NUL) xor (chr2 = C_POC_NUL)) then
+ return FALSE;
+ elsif ((chr1 = C_POC_NUL) and (chr2 = C_POC_NUL)) then
+ return TRUE;
+ end if;
+ end loop;
+ -- check special cases,
+ return (((str1'length = len) and (str2'length = len)) or -- both strings are fully consumed and equal
+ ((str1'length > len) and (str1(str1'low + len) = C_POC_NUL)) or -- str1 is longer, but str_length equals len
+ ((str2'length > len) and (str2(str2'low + len) = C_POC_NUL))); -- str2 is longer, but str_length equals len
+ end function;
+
+ function str_find(str : STRING; pattern : STRING; start : NATURAL := 0) return BOOLEAN is
+ begin
+ for i in imax(str'low, start) to (str'high - pattern'length + 1) loop
+ exit when (str(i) = C_POC_NUL);
+ if (str(i to i + pattern'length - 1) = pattern) then
+ return TRUE;
+ end if;
+ end loop;
+ return FALSE;
+ end function;
+
+
+ -- helper function to create configuration strings
+ -- ===========================================================================
+ function getLocalDeviceString(DeviceString : STRING) return STRING is
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is begin
+ if cond then return value1; else return value2; end if;
+ end function;
+
+ constant ConstNUL : STRING(1 to 1) := (others => C_POC_NUL);
+ constant MY_DEVICE_STR : STRING := BOARD_DEVICE;
+ variable Result : STRING(1 to T_DEVICE_STRING'length);
+ begin
+ Result := (others => C_POC_NUL);
+ -- report DeviceString for debugging
+ if (POC_VERBOSE = TRUE) then
+ report "getLocalDeviceString: DeviceString='" & str_trim(DeviceString) & "' MY_DEVICE='" & str_trim(MY_DEVICE) & "' MY_DEVICE_STR='" & str_trim(MY_DEVICE_STR) & "'" severity NOTE;
+ end if;
+ -- if DeviceString is populated
+ if ((str_length(DeviceString) /= 0) and (str_imatch(DeviceString, "None") = FALSE)) then
+ Result(1 to imin(T_DEVICE_STRING'length, imax(1, DeviceString'length))) := ite((DeviceString'length > 0), DeviceString(1 to imin(T_DEVICE_STRING'length, DeviceString'length)), ConstNUL);
+ -- if MY_DEVICE is set, prefer it
+ elsif ((str_length(MY_DEVICE) /= 0) and (str_imatch(MY_DEVICE, "None") = FALSE)) then
+ Result(1 to imin(T_DEVICE_STRING'length, imax(1, MY_DEVICE'length))) := ite((MY_DEVICE'length > 0), MY_DEVICE(1 to imin(T_DEVICE_STRING'length, MY_DEVICE'length)), ConstNUL);
+ -- otherwise use MY_BOARD
+ else
+ Result(1 to imin(T_DEVICE_STRING'length, imax(1, MY_DEVICE_STR'length))) := ite((MY_DEVICE_STR'length > 0), MY_DEVICE_STR(1 to imin(T_DEVICE_STRING'length, MY_DEVICE_STR'length)), ConstNUL);
+ end if;
+ return Result;
+ end function;
+
+ -- helper function to create configuration strings
+ -- ===========================================================================
+ function conf(str : string; Size : POSITIVE) return STRING is
+ constant ConstNUL : STRING(1 to 1) := (others => C_POC_NUL);
+ variable Result : STRING(1 to Size);
+ -- inlined function from PoC.utils, to break dependency
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is begin
+ if cond then return value1; else return value2; end if;
+ end function;
+ function imin(arg1 : integer; arg2 : integer) return integer is begin
+ if arg1 < arg2 then return arg1; else return arg2; end if;
+ end function;
+ function imax(arg1 : integer; arg2 : integer) return integer is begin
+ if arg1 > arg2 then return arg1; else return arg2; end if;
+ end function;
+ begin
+ Result := (others => C_POC_NUL);
+ if (str'length > 0) then
+ Result(1 to imin(Size, imax(1, str'length))) := ite((str'length > 0), str(1 to imin(Size, str'length)), ConstNUL);
+ end if;
+ return Result;
+ end function;
+
+ function conf8(str : string) return T_BOARD_CONFIG_STRING8 is
+ begin
+ return conf(str, 8);
+ end function;
+
+ function conf16(str : string) return T_BOARD_CONFIG_STRING16 is
+ begin
+ return conf(str, 16);
+ end function;
+
+ function conf32(str : string) return T_BOARD_CONFIG_STRING32 is
+ begin
+ return conf(str, 32);
+ end function;
+
+-- function conf64(str : string) return T_BOARD_CONFIG_STRING64 is
+-- begin
+-- return conf(str, 64);
+-- end function;
+
+ function extractFirstNumber(str : STRING) return NATURAL is
+ variable low : integer;
+ variable high : integer;
+ variable Result : NATURAL;
+ variable Digit : INTEGER;
+ begin
+ low := -1;
+ high := -1;
+ for i in str'low to str'high loop
+ if chr_isDigit(str(i)) then
+ low := i;
+ exit;
+ end if;
+ end loop;
+ -- abort if no digit can be found
+ if (low = -1) then return 0; end if;
+
+ for i in (low + 1) to str'high loop
+ if chr_isAlpha(str(i)) then
+ high := i - 1;
+ exit;
+ end if;
+ end loop;
+
+ if (high = -1) then return 0; end if;
+ -- return INTEGER'value(str(low to high)); -- 'value(...) is not supported by Vivado Synth 2014.1
+
+ -- convert substring to a number
+ for i in low to high loop
+ if (chr_isDigit(str(i)) = FALSE) then
+ return -1;
+ end if;
+ Result := (Result * 10) + (character'pos(str(i)) - character'pos('0'));
+ end loop;
+ return Result;
+ end function;
+
+ -- predefined UART descriptions
+ function brd_CreateUART(IsDTE : BOOLEAN; FlowControl : STRING; BaudRate : STRING; BaudRate_Max : STRING := "") return T_BOARD_UART_DESC is
+ variable Result : T_BOARD_UART_DESC;
+ begin
+ Result.IsDTE := IsDTE;
+ Result.FlowControl := conf16(FlowControl);
+ Result.BaudRate := conf16(BaudRate);
+ Result.BaudRate_Max := conf16(BaudRate_Max);
+ return Result;
+ end function;
+
+ constant C_BOARD_UART_EMPTY : T_BOARD_UART_DESC := brd_CreateUART(TRUE, "NONE", "0 Bd");
+ constant C_BOARD_UART_DTE_115200_NONE : T_BOARD_UART_DESC := brd_CreateUART(TRUE, "NONE", "115.2 kBd");
+ constant C_BOARD_UART_DCE_115200_NONE : T_BOARD_UART_DESC := brd_CreateUART(FALSE, "NONE", "115.2 kBd");
+ constant C_BOARD_UART_DCE_115200_HWCTS : T_BOARD_UART_DESC := brd_CreateUART(FALSE, "HW_CTS_RTS", "115.2 kBd");
+ constant C_BOARD_UART_DTE_460800_NONE : T_BOARD_UART_DESC := brd_CreateUART(FALSE, "NONE", "460.8 kBd");
+ constant C_BOARD_UART_DTE_921600_NONE : T_BOARD_UART_DESC := brd_CreateUART(FALSE, "NONE", "921.6 kBd");
+
+ function brd_CreateEthernet(IPStyle : STRING; RS_DataInt : STRING; PHY_Device : STRING; PHY_DevAddress : STD_LOGIC_VECTOR(7 downto 0); PHY_DataInt : STRING; PHY_MgntInt : STRING) return T_BOARD_ETHERNET_DESC is
+ variable Result : T_BOARD_ETHERNET_DESC;
+ begin
+ Result.IPStyle := conf8(IPStyle);
+ Result.RS_DataInterface := conf8(RS_DataInt);
+ Result.PHY_Device := conf16(PHY_Device);
+ Result.PHY_DeviceAddress := PHY_DevAddress;
+ Result.PHY_DataInterface := conf8(PHY_DataInt);
+ Result.PHY_ManagementInterface := conf16(PHY_MgntInt);
+ return Result;
+ end function;
+
+ constant C_BOARD_ETH_EMPTY : T_BOARD_ETHERNET_DESC := brd_CreateEthernet("", "", "", x"00", "", "");
+ constant C_BOARD_ETH_SOFT_GMII_88E1111 : T_BOARD_ETHERNET_DESC := brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"07", "GMII", "MDIO");
+ constant C_BOARD_ETH_HARD_GMII_88E1111 : T_BOARD_ETHERNET_DESC := brd_CreateEthernet("HARD", "GMII", "MARVEL_88E1111", x"07", "GMII", "MDIO");
+ constant C_BOARD_ETH_SOFT_SGMII_88E1111 : T_BOARD_ETHERNET_DESC := brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"07", "SGMII", "MDIO_OVER_IIC");
+
+ constant C_BOARD_ETH_NONE : T_BOARD_ETHERNET_DESC_VECTOR(T_BOARD_ETHERNET_DESC_INDEX) := (others => C_BOARD_ETH_EMPTY);
+
+
+ -- board description
+ -- ===========================================================================
+ CONSTANT C_BOARD_INFO_LIST : T_BOARD_INFO_VECTOR := (
+ -- Xilinx boards
+ -- =========================================================================
+ BOARD_S3SK200 => (
+ FPGADevice => conf32("XC3S200FT256"), -- XC2S200FT256
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_S3SK1000 => (
+ FPGADevice => conf32("XC3S1000FT256"), -- XC2S200FT256
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_S3ESK500 => (
+ FPGADevice => conf32("XC3S500EFT256"), -- XC2S200FT256
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_S3ESK1600 => (
+ FPGADevice => conf32("XC3S1600EFT256"), -- XC2S200FT256
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_ATLYS => (
+ FPGADevice => conf32("XC6SLX45-3CSG324"), -- XC6SLX45-3CSG324
+ UART => C_BOARD_UART_DTE_460800_NONE,
+ Ethernet => (
+ 0 => C_BOARD_ETH_HARD_GMII_88E1111,
+ others => C_BOARD_ETH_EMPTY),
+ EthernetCount => 1
+ ),
+ BOARD_KC705 => (
+ FPGADevice => conf32("XC7K325T-2FFG900C"), -- XC7K325T-2FFG900C
+ UART => C_BOARD_UART_DTE_921600_NONE,
+ Ethernet => (
+ 0 => C_BOARD_ETH_SOFT_GMII_88E1111,
+ others => C_BOARD_ETH_EMPTY),
+ EthernetCount => 1
+ ),
+ BOARD_ML505 => (
+ FPGADevice => conf32("XC5VLX50T-1FF1136"), -- XC5VLX50T-1FF1136
+ UART => C_BOARD_UART_DCE_115200_NONE,
+ Ethernet => (
+ 0 => C_BOARD_ETH_HARD_GMII_88E1111,
+ others => C_BOARD_ETH_EMPTY),
+ EthernetCount => 1
+ ),
+ BOARD_ML605 => (
+ FPGADevice => conf32("XC6VLX240T-1FF1156"), -- XC6VLX240T-1FF1156
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => (
+ 0 => C_BOARD_ETH_HARD_GMII_88E1111,
+ others => C_BOARD_ETH_EMPTY),
+ EthernetCount => 1
+ ),
+ BOARD_VC707 => (
+ FPGADevice => conf32("XC7VX485T-2FFG1761C"), -- XC7VX485T-2FFG1761C
+ UART => C_BOARD_UART_DTE_921600_NONE,
+ Ethernet => (
+ 0 => C_BOARD_ETH_SOFT_SGMII_88E1111,
+ others => C_BOARD_ETH_EMPTY),
+ EthernetCount => 1
+ ),
+ BOARD_ZEDBOARD => (
+ FPGADevice => conf32("XC7Z020-1CLG484"), -- XC7Z020-1CLG484
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ -- Altera boards
+ -- =========================================================================
+ BOARD_DE0 => (
+ FPGADevice => conf32("EP3C16F484"), -- EP3C16F484
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_S2GXAV => (
+ FPGADevice => conf32("EP2SGX90FF1508C3"), -- EP2SGX90FF1508C3
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+ BOARD_DE4 => (
+ FPGADevice => conf32("EP4SGX230KF40C2"), -- EP4SGX230KF40C2
+ UART => C_BOARD_UART_DTE_460800_NONE,
+ Ethernet => (
+ 0 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"00", "RGMII", "MDIO"),
+ 1 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"01", "RGMII", "MDIO"),
+ 2 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"02", "RGMII", "MDIO"),
+ 3 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"03", "RGMII", "MDIO"),
+ others => C_BOARD_ETH_EMPTY
+ ),
+ EthernetCount => 4
+ ),
+ BOARD_DE5 => (
+ FPGADevice => conf32("EP5SGXEA7N2F45C2"), -- EP5SGXEA7N2F45C2
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ ),
+
+ -- custom board / dummy entry
+ BOARD_CUSTOM => (
+ FPGADevice => conf32("Device is unknown for a custom board"),
+ UART => C_BOARD_UART_EMPTY,
+ Ethernet => C_BOARD_ETH_NONE,
+ EthernetCount => 0
+ )
+ );
+
+ -- Public functions
+ -- ===========================================================================
+ -- TODO: comment
+ function BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY) return T_BOARD is
+ -- inlined function from PoC.utils, to break dependency
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is begin
+ if cond then return value1; else return value2; end if;
+ end function;
+
+ constant MY_BRD : T_BOARD_STRING := ite((BoardConfig /= C_BOARD_STRING_EMPTY), conf(BoardConfig, T_BOARD_STRING'length), conf(MY_BOARD, T_BOARD_STRING'length));
+ begin
+ if (POC_VERBOSE = TRUE) then
+ report "PoC configuration: Used board is '" & str_trim(MY_BRD) & "'" severity NOTE;
+ end if;
+ for i in T_BOARD loop
+ if str_imatch(T_BOARD'image(i), "BOARD_" & str_trim(MY_BRD)) then
+ return i;
+ end if;
+ end loop;
+
+ report "Unknown board name in MY_BOARD = " & MY_BRD & "." severity failure;
+ return BOARD_CUSTOM;
+ end function;
+
+ function BOARD_INFO(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return T_BOARD_INFO is
+ constant BRD : T_BOARD := BOARD(BoardConfig);
+ begin
+ return C_BOARD_INFO_LIST(BRD);
+ end function;
+
+ -- TODO: comment
+ function BOARD_DEVICE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING is
+ constant BRD : T_BOARD := BOARD(BoardConfig);
+ begin
+ return str_trim(C_BOARD_INFO_LIST(BRD).FPGADevice);
+ end function;
+
+ function BOARD_UART_BAUDRATE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING is
+ constant BRD : T_BOARD := BOARD(BoardConfig);
+ begin
+ return str_trim(C_BOARD_INFO_LIST(BRD).UART.BaudRate);
+ end function;
+
+ -- purpose: extract vendor from MY_DEVICE
+ function VENDOR(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_VENDOR is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant VEN_STR : string(1 to 2) := MY_DEV(1 to 2);
+ begin
+ case VEN_STR is
+ when "XC" => return VENDOR_XILINX;
+ when "EP" => return VENDOR_ALTERA;
+ when others => report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ function SYNTHESIS_TOOL(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_SYNTHESIS_TOOL is
+ constant VEN : T_VENDOR := VENDOR(DeviceString);
+ begin
+ case VEN is
+ when VENDOR_ALTERA =>
+ return SYNTHESIS_TOOL_ALTERA_QUARTUS2;
+ when VENDOR_LATTICE =>
+ return SYNTHESIS_TOOL_SYNOPSIS;
+ when VENDOR_XILINX =>
+ if (1 fs /= 1 us) then
+ return SYNTHESIS_TOOL_XILINX_XST;
+ else
+ return SYNTHESIS_TOOL_XILINX_VIVADO;
+ end if;
+ end case;
+ end function;
+
+ -- purpose: extract device from MY_DEVICE
+ function DEVICE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant VEN : T_VENDOR := VENDOR(DeviceString);
+ constant DEV_STR : string(3 to 4) := MY_DEV(3 to 4);
+ begin
+ case VEN is
+ when VENDOR_ALTERA =>
+ case DEV_STR is
+ when "1C" => return DEVICE_CYCLONE1;
+ when "2C" => return DEVICE_CYCLONE2;
+ when "3C" => return DEVICE_CYCLONE3;
+ when "1S" => return DEVICE_STRATIX1;
+ when "2S" => return DEVICE_STRATIX2;
+ when "4S" => return DEVICE_STRATIX4;
+ when "5S" => return DEVICE_STRATIX5;
+ when others => report "Unknown Altera device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end case;
+
+ when VENDOR_XILINX =>
+ case DEV_STR is
+ when "7A" => return DEVICE_ARTIX7;
+ when "7K" => return DEVICE_KINTEX7;
+ when "3S" => return DEVICE_SPARTAN3;
+ when "6S" => return DEVICE_SPARTAN6;
+ when "5V" => return DEVICE_VIRTEX5;
+ when "6V" => return DEVICE_VIRTEX6;
+ when "7V" => return DEVICE_VIRTEX7;
+ when "7Z" => return DEVICE_ZYNQ7;
+ when others => report "Unknown Xilinx device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end case;
+
+ when others => report "Unknown vendor in MY_DEVICE = " & MY_DEV & "." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ -- purpose: extract device from MY_DEVICE
+ function DEVICE_FAMILY(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_FAMILY is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant VEN : T_VENDOR := VENDOR(DeviceString);
+ constant FAM_CHAR : character := MY_DEV(4);
+ begin
+ case VEN is
+ when VENDOR_ALTERA =>
+ case FAM_CHAR is
+ when 'C' => return DEVICE_FAMILY_CYCLONE;
+ when 'S' => return DEVICE_FAMILY_STRATIX;
+ when others => report "Unknown Altera device family in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end case;
+
+ when VENDOR_XILINX =>
+ case FAM_CHAR is
+ when 'A' => return DEVICE_FAMILY_ARTIX;
+ when 'K' => return DEVICE_FAMILY_KINTEX;
+ when 'S' => return DEVICE_FAMILY_SPARTAN;
+ when 'V' => return DEVICE_FAMILY_VIRTEX;
+ when 'Z' => return DEVICE_FAMILY_ZYNQ;
+ when others => report "Unknown Xilinx device family in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end case;
+
+ when others => report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ function DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant DEV : T_DEVICE := DEVICE(DeviceString);
+ begin
+ case DEV is
+ when DEVICE_ARTIX7 | DEVICE_KINTEX7 | DEVICE_VIRTEX7 | DEVICE_ZYNQ7 => return 7; -- all Xilinx ****7 devices share some common features: e.g. XADC
+ when others => return 0;
+ end case;
+ end function;
+
+ function DEVICE_NUMBER(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant VEN : T_VENDOR := VENDOR(DeviceString);
+ begin
+ case VEN is
+ when VENDOR_ALTERA => return extractFirstNumber(MY_DEV(5 to MY_DEV'high));
+ when VENDOR_XILINX => return extractFirstNumber(MY_DEV(5 to MY_DEV'high));
+ when others => report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ function DEVICE_SUBTYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return t_device_subtype is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant DEV : T_DEVICE := DEVICE(MY_DEV);
+ constant DEV_SUB_STR : string(1 to 2) := MY_DEV(5 to 6); -- work around for GHDL
+ begin
+ case DEV is
+ when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 => return DEVICE_SUBTYPE_NONE; -- Altera Cyclon I, II, III devices have no subtype
+
+ when DEVICE_STRATIX2 =>
+ if chr_isDigit(DEV_SUB_STR(1)) then return DEVICE_SUBTYPE_NONE;
+ elsif (DEV_SUB_STR = "GX") then return DEVICE_SUBTYPE_GX;
+ else report "Unknown Stratix II subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_STRATIX4 =>
+ if (DEV_SUB_STR(1) = 'E') then return DEVICE_SUBTYPE_E;
+ elsif (DEV_SUB_STR = "GX") then return DEVICE_SUBTYPE_GX;
+-- elsif (DEV_SUB_STR = "GT") then return DEVICE_SUBTYPE_GT;
+ else report "Unknown Stratix II subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_SPARTAN3 => report "TODO: parse Spartan3 / Spartan3E / Spartan3AN device subtype." severity failure;
+
+ when DEVICE_SPARTAN6 =>
+ if ((DEV_SUB_STR = "LX") and (not str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LX;
+ elsif ((DEV_SUB_STR = "LX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LXT;
+ else report "Unknown Virtex-5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_VIRTEX5 =>
+ if ((DEV_SUB_STR = "LX") and (not str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LX;
+ elsif ((DEV_SUB_STR = "LX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LXT;
+ elsif ((DEV_SUB_STR = "SX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_SXT;
+ elsif ((DEV_SUB_STR = "TX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_TXT;
+ elsif ((DEV_SUB_STR = "FX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_FXT;
+ else report "Unknown Virtex-5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_VIRTEX6 =>
+ if ((DEV_SUB_STR = "LX") and (not str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LX;
+ elsif ((DEV_SUB_STR = "LX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_LXT;
+ elsif ((DEV_SUB_STR = "SX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_SXT;
+ elsif ((DEV_SUB_STR = "CX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_CXT;
+ elsif ((DEV_SUB_STR = "HX") and ( str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_HXT;
+ else report "Unknown Virtex-6 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_ARTIX7 =>
+ if ( ( str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_T;
+ else report "Unknown Artix-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_KINTEX7 =>
+ if ( ( str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_T;
+ else report "Unknown Kintex-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when DEVICE_VIRTEX7 =>
+ if ( ( str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_T;
+ elsif ((DEV_SUB_STR(1) = 'X') and ( str_find(MY_DEV(6 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_XT;
+ elsif ((DEV_SUB_STR(1) = 'H') and ( str_find(MY_DEV(6 TO MY_DEV'high), "T"))) then return DEVICE_SUBTYPE_HT;
+ else report "Unknown Virtex-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
+ end if;
+
+ when others => report "Transceiver type is unknown for the given device." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+
+ end function;
+
+ function LUT_FANIN(DeviceString : string := C_DEVICE_STRING_EMPTY) return positive is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant DEV : T_DEVICE := DEVICE(DeviceString);
+ begin
+ case DEV is
+ when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 => return 4;
+ when DEVICE_STRATIX1 | DEVICE_STRATIX2 => return 4;
+ when DEVICE_STRATIX4 | DEVICE_STRATIX5 => return 6;
+
+ when DEVICE_SPARTAN3 => return 4;
+ when DEVICE_SPARTAN6 => return 6;
+ when DEVICE_ARTIX7 => return 6;
+ when DEVICE_KINTEX7 => return 6;
+ when DEVICE_VIRTEX5 | DEVICE_VIRTEX6 | DEVICE_VIRTEX7 => return 6;
+ when DEVICE_ZYNQ7 => return 6;
+
+ when others => report "LUT fan-in is unknown for the given device." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ function TRANSCEIVER_TYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_TRANSCEIVER is
+ constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
+ constant DEV : T_DEVICE := DEVICE(DeviceString);
+ constant DEV_NUM : natural := DEVICE_NUMBER(DeviceString);
+ constant DEV_SUB : t_device_subtype := DEVICE_SUBTYPE(DeviceString);
+ begin
+ case DEV is
+ when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 => return TRANSCEIVER_NONE; -- Altera Cyclon I, II, III devices have no transceivers
+
+ when DEVICE_SPARTAN3 => return TRANSCEIVER_NONE; -- Xilinx Spartan3 devices have no transceivers
+
+ when DEVICE_SPARTAN6 =>
+ case DEV_SUB is
+ when DEVICE_SUBTYPE_LX => return TRANSCEIVER_NONE;
+ when DEVICE_SUBTYPE_LXT => return TRANSCEIVER_GTPE1;
+ when others => report "Unknown Spartan-6 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
+ end case;
+
+ when DEVICE_VIRTEX5 =>
+ case DEV_SUB is
+ when DEVICE_SUBTYPE_LX => return TRANSCEIVER_NONE;
+ when DEVICE_SUBTYPE_SXT => return TRANSCEIVER_GTP_DUAL;
+ when DEVICE_SUBTYPE_LXT => return TRANSCEIVER_GTP_DUAL;
+ when DEVICE_SUBTYPE_TXT => return TRANSCEIVER_GTX;
+ when DEVICE_SUBTYPE_FXT => return TRANSCEIVER_GTX;
+ when others => report "Unknown Virtex-5 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
+ end case;
+
+ when DEVICE_VIRTEX6 =>
+ case DEV_SUB is
+ when DEVICE_SUBTYPE_LX => return TRANSCEIVER_NONE;
+ when DEVICE_SUBTYPE_SXT => return TRANSCEIVER_GTXE1;
+ when DEVICE_SUBTYPE_LXT => return TRANSCEIVER_GTXE1;
+ when DEVICE_SUBTYPE_HXT => return TRANSCEIVER_GTXE1;
+ when others => report "Unknown Virtex-6 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
+ end case;
+
+ when DEVICE_ARTIX7 => return TRANSCEIVER_GTPE2;
+ when DEVICE_KINTEX7 => return TRANSCEIVER_GTXE2;
+ when DEVICE_VIRTEX7 =>
+ case DEV_SUB is
+ when DEVICE_SUBTYPE_T => return TRANSCEIVER_GTXE2;
+ when DEVICE_SUBTYPE_XT =>
+ if (DEV_NUM = 485) then return TRANSCEIVER_GTXE2;
+ else return TRANSCEIVER_GTHE2;
+ end if;
+ when DEVICE_SUBTYPE_HT => return TRANSCEIVER_GTHE2;
+ when others => report "Unknown Virtex-7 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
+ end case;
+
+ when DEVICE_STRATIX2 => return TRANSCEIVER_GXB;
+ when DEVICE_STRATIX4 => return TRANSCEIVER_GXB;
+
+ when others => report "Unknown device." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ -- purpose: extract architecture properties from DEVICE
+ function DEVICE_INFO(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_INFO is
+ variable Result : T_DEVICE_INFO;
+ begin
+ Result.Vendor := VENDOR(DeviceString);
+ Result.Device := DEVICE(DeviceString);
+ Result.DevFamily := DEVICE_FAMILY(DeviceString);
+ Result.DevNumber := DEVICE_NUMBER(DeviceString);
+ Result.DevSubType := DEVICE_SUBTYPE(DeviceString);
+ Result.DevSeries := DEVICE_SERIES(DeviceString);
+ Result.TransceiverType := TRANSCEIVER_TYPE(DeviceString);
+ Result.LUT_FanIn := LUT_FANIN(DeviceString);
+
+ return Result;
+ end function;
+
+ function ARCH_PROPS return archprops_t is
+ variable result : archprops_t;
+ begin
+ result.LUT_K := LUT_FANIN;
+
+ return result;
+ end function;
+
+ -- force FSM to predefined encoding in debug mode
+ function getFSMEncoding_gray(debug : BOOLEAN) return STRING is
+ begin
+ if (debug = true) then
+ return "gray";
+ else
+ case VENDOR is
+ when VENDOR_XILINX => return "auto";
+ when VENDOR_ALTERA => return "default";
+ when others => report "Unknown vendor." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end if;
+ end function;
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/debug.vhdl b/testsuite/gna/bug019/PoC/src/common/debug.vhdl
new file mode 100644
index 000000000..dda3cb0b8
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/debug.vhdl
@@ -0,0 +1,87 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Debug helper functions.
+--
+-- Description:
+-- ------------------------------------
+-- This file declares a debug helper function to export enum encodings as a
+-- ChipScope readable token file (*.tok).
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+use STD.TextIO.all;
+
+library PoC;
+use PoC.strings.all;
+
+
+package debug is
+ impure function dbg_ExportEncoding(Name : STRING; encodings : string; tokenFileName : STRING) return BOOLEAN;
+
+end package;
+
+
+package body debug is
+ impure function dbg_ExportEncoding(Name : STRING; encodings : string; tokenFileName : STRING) return BOOLEAN is
+ file tokenFile : TEXT open WRITE_MODE is tokenFileName;
+
+ variable cnt, base : integer;
+ variable l : line;
+ begin
+ report "Exporting encoding of '" & Name & "' to '" & tokenFileName & "'..." severity note;
+ report "dbg_ExportEncoding: '" & encodings & "'" severity note;
+
+ -- write file header
+ write(l, STRING'("# Encoding file for '" & Name & "'")); writeline(tokenFile, l);
+ write(l, STRING'("#")); writeline(tokenFile, l);
+ write(l, STRING'("# ChipScope Token File Version")); writeline(tokenFile, l);
+ write(l, STRING'("@FILE_VERSION=1.0.0")); writeline(tokenFile, l);
+ write(l, STRING'("#")); writeline(tokenFile, l);
+ write(l, STRING'("# Default token value")); writeline(tokenFile, l);
+ write(l, STRING'("@DEFAULT_TOKEN=")); writeline(tokenFile, l);
+ write(l, STRING'("#")); writeline(tokenFile, l);
+
+ -- write state entires
+ cnt := 0;
+ base := encodings'left;
+ for i in encodings'range loop
+ if encodings(i) = ';' then
+ -- Leave the str_trim call in!
+ -- Otherwise, the new parser of ISE 14.7 fails to slice properly.
+ write(l, str_trim(encodings(base to i-1)));
+ write(l, character'('='));
+ write(l, raw_format_nat_hex(cnt));
+ writeline(tokenFile, l);
+ cnt := cnt + 1;
+ base := i+1;
+ end if;
+ end loop;
+
+ file_close(tokenFile);
+ return true;
+ end function;
+end package body;
+
diff --git a/testsuite/gna/bug019/PoC/src/common/fileio.vhdl b/testsuite/gna/bug019/PoC/src/common/fileio.vhdl
new file mode 100644
index 000000000..d0657e93e
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/fileio.vhdl
@@ -0,0 +1,93 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Package: File I/O-related Functions.
+--
+-- Authors: Patrick Lehmann
+-- Thomas B. Preusser
+--
+-- Description:
+-- Exploring the options for providing a more convenient API than std.textio.
+-- Not yet recommended for adoption as it depends on the VHDL generation and
+-- still is under discussion.
+--
+-- Open problems:
+-- - verify that std.textio.write(text, string) is, indeed, specified and
+-- that it does *not* print a trailing \newline
+-- -> would help to eliminate line buffering in shared variables
+-- - move C_LINEBREAK to my_config to keep platform dependency out?
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+use STD.TextIO.all;
+
+library PoC;
+use PoC.my_project.all;
+
+
+package FileIO is
+ -- Constant declarations
+ constant C_LINEBREAK : STRING;
+
+ -- =============================================================================
+ procedure stdout_write (str : STRING);
+ procedure stdout_writeline(str : STRING := "");
+
+end package;
+
+package body FileIO is
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function str_equal(str1 : STRING; str2 : STRING) return BOOLEAN is
+ begin
+ if str1'length /= str2'length then
+ return FALSE;
+ else
+ return (str1 = str2);
+ end if;
+ end function;
+
+ -- =============================================================================
+ constant C_LINEBREAK : STRING := ite(str_equal(MY_OPERATING_SYSTEM, "WINDOWS"), (CR & LF), (1 => LF));
+
+ -- =============================================================================
+ shared variable stdout_line : line;
+ shared variable stderr_line : line;
+
+ procedure stdout_write(str : STRING) is
+ begin
+ write(stdout_line, str);
+ end procedure;
+
+ procedure stdout_writeline(str : STRING := "") is
+ begin
+ write(stdout_line, str);
+ writeline(output, stdout_line);
+ end procedure;
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/my_config.vhdl.template b/testsuite/gna/bug019/PoC/src/common/my_config.vhdl.template
new file mode 100644
index 000000000..58103add5
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/my_config.vhdl.template
@@ -0,0 +1,58 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Project specific configuration.
+--
+-- Description:
+-- ------------------------------------
+-- This is a template file.
+--
+-- The global packages common/config and common/board evaluate the settings
+-- declared in this file.
+--
+-- USAGE:
+-- 1) Copy this file into your project's source directory and rename it to
+-- "my_config.vhdl".
+-- 2) Add file to library "PoC" in your synthesis tool.
+-- 3) Change setup appropriately.
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library PoC;
+
+
+package my_config is
+ -- Change these lines to setup configuration.
+ constant MY_BOARD : string := "CHANGE THIS"; -- e.g. Custom, ML505, KC705, Atlys
+ constant MY_DEVICE : string := "CHANGE THIS"; -- e.g. None, XC5VLX50T-1FF1136, EP2SGX90FF1508C3
+
+ -- For internal use only
+ constant MY_VERBOSE : boolean := FALSE; -- activate detailed report statements in functions and procedures
+end package;
+
+
+package body my_config is
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/my_project.vhdl.template b/testsuite/gna/bug019/PoC/src/common/my_project.vhdl.template
new file mode 100644
index 000000000..6c88d7913
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/my_project.vhdl.template
@@ -0,0 +1,52 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Patrick Lehmann
+--
+-- Package: Project specific configuration.
+--
+-- Description:
+-- ------------------------------------
+-- This is a template file.
+--
+-- TODO
+--
+-- USAGE:
+-- 1) Copy this file into your project's source directory and rename it to
+-- "my_project.vhdl".
+-- 2) Add file to library "poc" in your synthesis tool.
+-- 3) Change setup appropriately.
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library PoC;
+
+
+package my_project is
+ -- Change these lines to setup configuration.
+ constant MY_PROJECT_DIR : string := "CHANGE THIS"; -- e.g. "d:/vhdl/myproject/", "/home/me/projects/myproject/"
+ constant MY_OPERATING_SYSTEM : string := "CHANGE THIS"; -- e.g. "WINDOWS", "LINUX"
+end package;
+
+
+package body my_project is
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/physical.vhdl b/testsuite/gna/bug019/PoC/src/common/physical.vhdl
new file mode 100644
index 000000000..a38604cde
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/physical.vhdl
@@ -0,0 +1,1014 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Patrick Lehmann
+--
+-- Package: This VHDL package declares new physical types and their
+-- conversion functions.
+--
+-- Description:
+-- ------------------------------------
+-- For detailed documentation see below.
+--
+-- NAMING CONVENTION:
+-- t - time
+-- p - period
+-- d - delay
+-- f - frequency
+-- br - baud rate
+-- vec - vector
+--
+-- ATTENTION:
+-- This package is not supported by Xilinx Synthese Tools prior to 14.7!
+--
+-- It was successfully tested with:
+-- - Xilinx Synthesis Tool (XST) 14.7 and Xilinx ISE Simulator (iSim) 14.7
+-- - Quartus II 13.1
+-- - QuestaSim 10.0d
+-- - GHDL 0.31
+--
+-- Tool chains with known issues:
+-- - Xilinx Vivado Synthesis 2014.4
+--
+-- Untested tool chains
+-- - Xilinx Vivado Simulator (xSim) 2014.4
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.math_real.all;
+
+library PoC;
+use PoC.config.all;
+use PoC.utils.all;
+use PoC.strings.all;
+
+
+package physical is
+
+ type FREQ is range 0 to INTEGER'high units
+ Hz;
+ kHz = 1000 Hz;
+ MHz = 1000 kHz;
+ GHz = 1000 MHz;
+-- THz = 1000 GHz;
+ end units;
+
+ type BAUD is range 0 to INTEGER'high units
+ Bd;
+ kBd = 1000 Bd;
+ MBd = 1000 kBd;
+ GBd = 1000 MBd;
+ end units;
+
+ type MEMORY is range 0 to INTEGER'high units
+ Byte;
+ KiB = 1024 Byte;
+ MiB = 1024 KiB;
+ GiB = 1024 MiB;
+-- TiB = 1024 GiB;
+ end units;
+
+ --
+ type T_TIMEVEC is array(NATURAL range <>) of TIME;
+ type T_FREQVEC is array(NATURAL range <>) of FREQ;
+ type T_BAUDVEC is array(NATURAL range <>) of BAUD;
+ type T_MEMVEC is array(NATURAL range <>) of MEMORY;
+
+ -- TODO
+ constant C_PHYSICAL_REPORT_TIMING_DEVIATION : BOOLEAN := TRUE;
+
+ -- conversion functions
+ function to_time(f : FREQ) return TIME;
+ function to_freq(p : TIME) return FREQ;
+ function to_freq(br : BAUD) return FREQ;
+ function to_baud(str : STRING) return BAUD;
+
+ -- if-then-else
+ function ite(cond : BOOLEAN; value1 : TIME; value2 : TIME) return TIME;
+ function ite(cond : BOOLEAN; value1 : FREQ; value2 : FREQ) return FREQ;
+ function ite(cond : BOOLEAN; value1 : BAUD; value2 : BAUD) return BAUD;
+ function ite(cond : BOOLEAN; value1 : MEMORY; value2 : MEMORY) return MEMORY;
+
+ -- min/ max for 2 arguments
+ function min(arg1 : TIME; arg2 : TIME) return TIME; -- Calculates: min(arg1, arg2) for times
+ function min(arg1 : FREQ; arg2 : FREQ) return FREQ; -- Calculates: min(arg1, arg2) for frequencies
+ function min(arg1 : BAUD; arg2 : BAUD) return BAUD; -- Calculates: min(arg1, arg2) for symbols per second
+ function min(arg1 : MEMORY; arg2 : MEMORY) return MEMORY; -- Calculates: min(arg1, arg2) for memory
+
+ function max(arg1 : TIME; arg2 : TIME) return TIME; -- Calculates: max(arg1, arg2) for times
+ function max(arg1 : FREQ; arg2 : FREQ) return FREQ; -- Calculates: max(arg1, arg2) for frequencies
+ function max(arg1 : BAUD; arg2 : BAUD) return BAUD; -- Calculates: max(arg1, arg2) for symbols per second
+ function max(arg1 : MEMORY; arg2 : MEMORY) return MEMORY; -- Calculates: max(arg1, arg2) for memory
+
+ -- min/max/sum as vector aggregation
+ function min(vec : T_TIMEVEC) return TIME; -- Calculates: min(vec) for a time vector
+ function min(vec : T_FREQVEC) return FREQ; -- Calculates: min(vec) for a frequency vector
+ function min(vec : T_BAUDVEC) return BAUD; -- Calculates: min(vec) for a baud vector
+ function min(vec : T_MEMVEC) return MEMORY; -- Calculates: min(vec) for a memory vector
+
+ function max(vec : T_TIMEVEC) return TIME; -- Calculates: max(vec) for a time vector
+ function max(vec : T_FREQVEC) return FREQ; -- Calculates: max(vec) for a frequency vector
+ function max(vec : T_BAUDVEC) return BAUD; -- Calculates: max(vec) for a baud vector
+ function max(vec : T_MEMVEC) return MEMORY; -- Calculates: max(vec) for a memory vector
+
+ -- QUESTION: some sum functions are not meaningful -> orthogonal function/type system
+ function sum(vec : T_TIMEVEC) return TIME; -- Calculates: sum(vec) for a time vector
+ function sum(vec : T_FREQVEC) return FREQ; -- Calculates: sum(vec) for a frequency vector
+ function sum(vec : T_BAUDVEC) return BAUD; -- Calculates: sum(vec) for a baud vector
+ function sum(vec : T_MEMVEC) return MEMORY; -- Calculates: sum(vec) for a memory vector
+
+ -- convert standard types (NATURAL, REAL) to time (TIME)
+ function fs2Time(t_fs : NATURAL) return TIME;
+ function ps2Time(t_ps : NATURAL) return TIME;
+ function ns2Time(t_ns : NATURAL) return TIME;
+ function us2Time(t_us : NATURAL) return TIME;
+ function ms2Time(t_ms : NATURAL) return TIME;
+ function sec2Time(t_sec : NATURAL) return TIME;
+
+ function fs2Time(t_fs : REAL) return TIME;
+ function ps2Time(t_ps : REAL) return TIME;
+ function ns2Time(t_ns : REAL) return TIME;
+ function us2Time(t_us : REAL) return TIME;
+ function ms2Time(t_ms : REAL) return TIME;
+ function sec2Time(t_sec : REAL) return TIME;
+
+ -- convert standard types (NATURAL, REAL) to period (TIME)
+ function Hz2Time(f_Hz : NATURAL) return TIME;
+ function kHz2Time(f_kHz : NATURAL) return TIME;
+ function MHz2Time(f_MHz : NATURAL) return TIME;
+ function GHz2Time(f_GHz : NATURAL) return TIME;
+-- function THz2Time(f_THz : NATURAL) return TIME;
+
+ function Hz2Time(f_Hz : REAL) return TIME;
+ function kHz2Time(f_kHz : REAL) return TIME;
+ function MHz2Time(f_MHz : REAL) return TIME;
+ function GHz2Time(f_GHz : REAL) return TIME;
+-- function THz2Time(f_THz : REAL) return TIME;
+
+ -- convert standard types (NATURAL, REAL) to frequency (FREQ)
+ function Hz2Freq(f_Hz : NATURAL) return FREQ;
+ function kHz2Freq(f_kHz : NATURAL) return FREQ;
+ function MHz2Freq(f_MHz : NATURAL) return FREQ;
+ function GHz2Freq(f_GHz : NATURAL) return FREQ;
+-- function THz2Freq(f_THz : NATURAL) return FREQ;
+
+ function Hz2Freq(f_Hz : REAL) return FREQ;
+ function kHz2Freq(f_kHz : REAL) return FREQ;
+ function MHz2Freq(f_MHz : REAL) return FREQ;
+ function GHz2Freq(f_GHz : REAL) return FREQ;
+-- function THz2Freq(f_THz : REAL) return FREQ;
+
+ -- convert physical types to standard type (REAL)
+ function to_real(t : TIME; scale : TIME) return REAL;
+ function to_real(f : FREQ; scale : FREQ) return REAL;
+ function to_real(br : BAUD; scale : BAUD) return REAL;
+ function to_real(mem : MEMORY; scale : MEMORY) return REAL;
+
+ -- convert physical types to standard type (INTEGER)
+ function to_int(t : TIME; scale : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER;
+ function to_int(f : FREQ; scale : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER;
+ function to_int(br : BAUD; scale : BAUD; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER;
+ function to_int(mem : MEMORY; scale : MEMORY; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return INTEGER;
+
+ -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
+ function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return NATURAL;
+ function TimingToCycles(Timing : TIME; Clock_Frequency : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return NATURAL;
+
+ function CyclesToDelay(Cycles : NATURAL; Clock_Period : TIME) return TIME;
+ function CyclesToDelay(Cycles : NATURAL; Clock_Frequency : FREQ) return TIME;
+
+ -- convert and format physical types to STRING
+ function to_string(t : TIME; precision : NATURAL) return STRING;
+ function to_string(f : FREQ; precision : NATURAL) return STRING;
+ function to_string(br : BAUD; precision : NATURAL) return STRING;
+ function to_string(mem : MEMORY; precision : NATURAL) return STRING;
+end physical;
+
+
+package body physical is
+
+ -- iSim 14.7 does not support fs in simulation (fs values are converted to 0 ps)
+ function MinimalTimeResolutionInSimulation return TIME is
+ begin
+ if (1 fs > 0 sec) then return 1 fs;
+ elsif (1 ps > 0 sec) then return 1 ps;
+ elsif (1 ns > 0 sec) then return 1 ns;
+ elsif (1 us > 0 sec) then return 1 us;
+ elsif (1 ms > 0 sec) then return 1 ms;
+ else return 1 sec;
+ end if;
+ end function;
+
+ -- real division for physical types
+ -- ===========================================================================
+ function div(a : TIME; b : TIME) return REAL is
+ constant MTRIS : TIME := MinimalTimeResolutionInSimulation;
+ begin
+ if (a < 1 us) then
+ return real(a / MTRIS) / real(b / MTRIS);
+ elsif (a < 1 ms) then
+ return real(a / (1000 * MTRIS)) / real(b / MTRIS) * 1000.0;
+ elsif (a < 1 sec) then
+ return real(a / (1000000 * MTRIS)) / real(b / MTRIS) * 1000000.0;
+ else
+ return real(a / (1000000000 * MTRIS)) / real(b / MTRIS) * 1000000000.0;
+ end if;
+ end function;
+
+ function div(a : FREQ; b : FREQ) return REAL is
+ begin
+ return real(a / 1 Hz) / real(b / 1 Hz);
+ end function;
+
+ function div(a : BAUD; b : BAUD) return REAL is
+ begin
+ return real(a / 1 Bd) / real(b / 1 Bd);
+ end function;
+
+ function div(a : MEMORY; b : MEMORY) return REAL is
+ begin
+ return real(a / 1 Byte) / real(b / 1 Byte);
+ end function;
+
+ -- conversion functions
+ -- ===========================================================================
+ function to_time(f : FREQ) return TIME is
+ variable res : TIME;
+ begin
+ if (f < 1 kHz) then res := div(1 Hz, f) * 1 sec;
+ elsif (f < 1 MHz) then res := div(1 kHz, f) * 1 ms;
+ elsif (f < 1 GHz) then res := div(1 MHz, f) * 1 us;
+-- elsif (f < 1 THz) then res := div(1 GHz, f) * 1 ns;
+ else res := div(1 GHz, f) * 1 ns;
+-- else res := div(1 THz, f) * 1 ps;
+ end if;
+
+ if (POC_VERBOSE = TRUE) then
+ report "to_time: f= " & to_string(f, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_freq(p : TIME) return FREQ is
+ variable res : FREQ;
+ begin
+-- if (p < 1 ps) then res := div(1 fs, p) * 1 THz;
+ if (p < 1 ns) then res := div(1 ps, p) * 1 GHz;
+-- elsif (p < 1 ns) then res := div(1 ps, p) * 1 GHz;
+ elsif (p < 1 us) then res := div(1 ns, p) * 1 MHz;
+ elsif (p < 1 ms) then res := div(1 us, p) * 1 kHz;
+ elsif (p < 1 sec) then res := div(1 ms, p) * 1 Hz;
+ else report "to_freq: input period exceeds output frequency scale." severity failure;
+ end if;
+ if (POC_VERBOSE = TRUE) then
+ report "to_freq: p= " & to_string(p, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_freq(br : BAUD) return FREQ is
+ variable res : FREQ;
+ begin
+ if (br < 1 kBd) then res := div(br, 1 Bd) * 1 Hz;
+ elsif (br < 1 MBd) then res := div(br, 1 kBd) * 1 kHz;
+ elsif (br < 1 GBd) then res := div(br, 1 MBd) * 1 MHz;
+ else res := div(br, 1 GBd) * 1 GHz;
+ end if;
+
+ if (POC_VERBOSE = TRUE) then
+ report "to_freq: br= " & to_string(br, 3) & " return " & to_string(res, 3) severity note;
+ end if;
+ return res;
+ end function;
+
+ function to_baud(str : STRING) return BAUD is
+ variable pos : INTEGER;
+ variable int : NATURAL;
+ variable base : POSITIVE;
+ variable frac : NATURAL;
+ variable digits : NATURAL;
+ begin
+ pos := str'low;
+ int := 0;
+ frac := 0;
+ digits := 0;
+ -- read integer part
+ for i in pos to str'high loop
+ if (chr_isDigit(str(i)) = TRUE) then int := int * 10 + to_digit_dec(str(i));
+ elsif (str(i) = '.') then pos := -i; exit;
+ elsif (str(i) = ' ') then pos := i; exit;
+ else pos := 0; exit;
+ end if;
+ end loop;
+ -- read fractional part
+ if ((pos < 0) and (-pos < str'high)) then
+ for i in -pos+1 to str'high loop
+ if ((frac = 0) and (str(i) = '0')) then next;
+ elsif (chr_isDigit(str(i)) = TRUE) then frac := frac * 10 + to_digit_dec(str(i));
+ elsif (str(i) = ' ') then digits := i + pos - 1; pos := i; exit;
+ else pos := 0; exit;
+ end if;
+ end loop;
+ end if;
+ -- abort if format is unknown
+ if (pos = 0) then report "to_baud: Unknown format" severity FAILURE; end if;
+ -- parse unit
+ pos := pos + 1;
+ if ((pos + 1 = str'high) and (str(pos to pos + 1) = "Bd")) then
+ return int * 1 Bd;
+ elsif (pos + 2 = str'high) then
+ if (str(pos to pos + 2) = "kBd") then
+ if (frac = 0) then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 kBd) + (frac * 10**(3 - digits) * 1 Bd);
+ else return (int * 1 kBd) + (frac / 10**(digits - 3) * 100 Bd);
+ end if;
+ elsif (str(pos to pos + 2) = "MBd") then
+ if (frac = 0) then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 MBd) + (frac * 10**(3 - digits) * 1 kBd);
+ elsif (digits <= 6) then return (int * 1 MBd) + (frac * 10**(6 - digits) * 1 Bd);
+ else return (int * 1 MBd) + (frac / 10**(digits - 6) * 100000 Bd);
+ end if;
+ elsif (str(pos to pos + 2) = "GBd") then
+ if (frac = 0) then return (int * 1 kBd);
+ elsif (digits <= 3) then return (int * 1 GBd) + (frac * 10**(3 - digits) * 1 MBd);
+ elsif (digits <= 6) then return (int * 1 GBd) + (frac * 10**(6 - digits) * 1 kBd);
+ elsif (digits <= 9) then return (int * 1 GBd) + (frac * 10**(9 - digits) * 1 Bd);
+ else return (int * 1 GBd) + (frac / 10**(digits - 9) * 100000000 Bd);
+ end if;
+ else
+ report "to_baud: Unknown unit." severity FAILURE;
+ end if;
+ else
+ report "to_baud: Unknown format" severity FAILURE;
+ end if;
+ end function;
+
+ -- if-then-else
+ -- ===========================================================================
+ function ite(cond : BOOLEAN; value1 : TIME; value2 : TIME) return TIME is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : FREQ; value2 : FREQ) return FREQ is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : BAUD; value2 : BAUD) return BAUD is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : MEMORY; value2 : MEMORY) return MEMORY is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ -- min/ max for 2 arguments
+ -- ===========================================================================
+ -- Calculates: min(arg1, arg2) for times
+ function min(arg1 : TIME; arg2 : TIME) return TIME is
+ begin
+ if (arg1 < arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for frequencies
+ function min(arg1 : FREQ; arg2 : FREQ) return FREQ is
+ begin
+ if (arg1 < arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for symbols per second
+ function min(arg1 : BAUD; arg2 : BAUD) return BAUD is
+ begin
+ if (arg1 < arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: min(arg1, arg2) for memory
+ function min(arg1 : MEMORY; arg2 : MEMORY) return MEMORY is
+ begin
+ if (arg1 < arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for times
+ function max(arg1 : TIME; arg2 : TIME) return TIME is
+ begin
+ if (arg1 > arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for frequencies
+ function max(arg1 : FREQ; arg2 : FREQ) return FREQ is
+ begin
+ if (arg1 > arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for symbols per second
+ function max(arg1 : BAUD; arg2 : BAUD) return BAUD is
+ begin
+ if (arg1 > arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- Calculates: max(arg1, arg2) for memory
+ function max(arg1 : MEMORY; arg2 : MEMORY) return MEMORY is
+ begin
+ if (arg1 > arg2) then return arg1; end if;
+ return arg2;
+ end function;
+
+ -- min/max/sum as vector aggregation
+ -- ===========================================================================
+ -- Calculates: min(vec) for a time vector
+ function min(vec : T_TIMEVEC) return TIME is
+ variable res : TIME := TIME'high;
+ begin
+ for i in vec'range loop
+ if (vec(i) < res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a frequency vector
+ function min(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := FREQ'high;
+ begin
+ for i in vec'range loop
+ if (vec(i) < res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a baud vector
+ function min(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := BAUD'high;
+ begin
+ for i in vec'range loop
+ if (vec(i) < res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: min(vec) for a memory vector
+ function min(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := MEMORY'high;
+ begin
+ for i in vec'range loop
+ if (vec(i) < res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a time vector
+ function max(vec : T_TIMEVEC) return TIME is
+ variable res : TIME := TIME'low;
+ begin
+ for i in vec'range loop
+ if (vec(i) > res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a frequency vector
+ function max(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := FREQ'low;
+ begin
+ for i in vec'range loop
+ if (vec(i) > res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a baud vector
+ function max(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := BAUD'low;
+ begin
+ for i in vec'range loop
+ if (vec(i) > res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: max(vec) for a memory vector
+ function max(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := MEMORY'low;
+ begin
+ for i in vec'range loop
+ if (vec(i) > res) then
+ res := vec(i);
+ end if;
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a time vector
+ function sum(vec : T_TIMEVEC) return TIME is
+ variable res : TIME := 0 fs;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a frequency vector
+ function sum(vec : T_FREQVEC) return FREQ is
+ variable res : FREQ := 0 Hz;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a baud vector
+ function sum(vec : T_BAUDVEC) return BAUD is
+ variable res : BAUD := 0 Bd;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- Calculates: sum(vec) for a memory vector
+ function sum(vec : T_MEMVEC) return MEMORY is
+ variable res : MEMORY := 0 Byte;
+ begin
+ for i in vec'range loop
+ res := res + vec(i);
+ end loop;
+ return res;
+ end;
+
+ -- convert standard types (NATURAL, REAL) to time (TIME)
+ -- ===========================================================================
+ function fs2Time(t_fs : NATURAL) return TIME is
+ begin
+ return t_fs * 1 fs;
+ end function;
+
+ function ps2Time(t_ps : NATURAL) return TIME is
+ begin
+ return t_ps * 1 ps;
+ end function;
+
+ function ns2Time(t_ns : NATURAL) return TIME is
+ begin
+ return t_ns * 1 ns;
+ end function;
+
+ function us2Time(t_us : NATURAL) return TIME is
+ begin
+ return t_us * 1 us;
+ end function;
+
+ function ms2Time(t_ms : NATURAL) return TIME is
+ begin
+ return t_ms * 1 ms;
+ end function;
+
+ function sec2Time(t_sec : NATURAL) return TIME is
+ begin
+ return t_sec * 1 sec;
+ end function;
+
+ function fs2Time(t_fs : REAL) return TIME is
+ begin
+ return t_fs * 1 fs;
+ end function;
+
+ function ps2Time(t_ps : REAL) return TIME is
+ begin
+ return t_ps * 1 ps;
+ end function;
+
+ function ns2Time(t_ns : REAL) return TIME is
+ begin
+ return t_ns * 1 ns;
+ end function;
+
+ function us2Time(t_us : REAL) return TIME is
+ begin
+ return t_us * 1 us;
+ end function;
+
+ function ms2Time(t_ms : REAL) return TIME is
+ begin
+ return t_ms * 1 ms;
+ end function;
+
+ function sec2Time(t_sec : REAL) return TIME is
+ begin
+ return t_sec * 1 sec;
+ end function;
+
+ -- convert standard types (NATURAL, REAL) to period (TIME)
+ -- ===========================================================================
+ function Hz2Time(f_Hz : NATURAL) return TIME is
+ begin
+ return 1 sec / f_Hz;
+ end function;
+
+ function kHz2Time(f_kHz : NATURAL) return TIME is
+ begin
+ return 1 ms / f_kHz;
+ end function;
+
+ function MHz2Time(f_MHz : NATURAL) return TIME
+ is
+ begin
+ return 1 us / f_MHz;
+ end function;
+
+ function GHz2Time(f_GHz : NATURAL) return TIME is
+ begin
+ return 1 ns / f_GHz;
+ end function;
+
+-- function THz2Time(f_THz : NATURAL) return TIME is
+-- begin
+-- return 1 ps / f_THz;
+-- end function;
+
+
+ function Hz2Time(f_Hz : REAL) return TIME is
+ begin
+ return 1 sec / f_Hz;
+ end function;
+
+ function kHz2Time(f_kHz : REAL) return TIME is
+ begin
+ return 1 ms / f_kHz;
+ end function;
+
+ function MHz2Time(f_MHz : REAL) return TIME is
+ begin
+ return 1 us / f_MHz;
+ end function;
+
+ function GHz2Time(f_GHz : REAL) return TIME is
+ begin
+ return 1 ns / f_GHz;
+ end function;
+
+-- function THz2Time(f_THz : REAL) return TIME is
+-- begin
+-- return 1 ps / f_THz;
+-- end function;
+
+ -- convert standard types (NATURAL, REAL) to frequency (FREQ)
+ -- ===========================================================================
+ function Hz2Freq(f_Hz : NATURAL) return FREQ is
+ begin
+ return f_Hz * 1 Hz;
+ end function;
+
+ function kHz2Freq(f_kHz : NATURAL) return FREQ is
+ begin
+ return f_kHz * 1 kHz;
+ end function;
+
+ function MHz2Freq(f_MHz : NATURAL) return FREQ is
+ begin
+ return f_MHz * 1 MHz;
+ end function;
+
+ function GHz2Freq(f_GHz : NATURAL) return FREQ is
+ begin
+ return f_GHz * 1 GHz;
+ end function;
+
+-- function THz2Freq(f_THz : NATURAL) return FREQ is
+-- begin
+-- return f_THz * 1 THz;
+-- end function;
+
+ function Hz2Freq(f_Hz : REAL) return FREQ is
+ begin
+ return f_Hz * 1 Hz;
+ end function;
+
+ function kHz2Freq(f_kHz : REAL )return FREQ is
+ begin
+ return f_kHz * 1 kHz;
+ end function;
+
+ function MHz2Freq(f_MHz : REAL )return FREQ is
+ begin
+ return f_MHz * 1 MHz;
+ end function;
+
+ function GHz2Freq(f_GHz : REAL )return FREQ is
+ begin
+ return f_GHz * 1 GHz;
+ end function;
+
+-- function THz2Freq(f_THz : REAL )return FREQ is
+-- begin
+-- return f_THz * 1 THz;
+-- end function;
+
+ -- convert physical types to standard type (REAL)
+ -- ===========================================================================
+ function to_real(t : TIME; scale : TIME) return REAL is
+ begin
+ if (scale = 1 fs) then return div(t, 1 fs);
+ elsif (scale = 1 ps) then return div(t, 1 ps);
+ elsif (scale = 1 ns) then return div(t, 1 ns);
+ elsif (scale = 1 us) then return div(t, 1 us);
+ elsif (scale = 1 ms) then return div(t, 1 ms);
+ elsif (scale = 1 sec) then return div(t, 1 sec);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ end;
+
+ function to_real(f : FREQ; scale : FREQ) return REAL is
+ begin
+ if (scale = 1 Hz) then return div(f, 1 Hz);
+ elsif (scale = 1 kHz) then return div(f, 1 kHz);
+ elsif (scale = 1 MHz) then return div(f, 1 MHz);
+ elsif (scale = 1 GHz) then return div(f, 1 GHz);
+-- elsif (scale = 1 THz) then return div(f, 1 THz);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ end;
+
+ function to_real(br : BAUD; scale : BAUD) return REAL is
+ begin
+ if (scale = 1 Bd) then return div(br, 1 Bd);
+ elsif (scale = 1 kBd) then return div(br, 1 kBd);
+ elsif (scale = 1 MBd) then return div(br, 1 MBd);
+ elsif (scale = 1 GBd) then return div(br, 1 GBd);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ end;
+
+ function to_real(mem : MEMORY; scale : MEMORY) return REAL is
+ begin
+ if (scale = 1 Byte) then return div(mem, 1 Byte);
+ elsif (scale = 1 KiB) then return div(mem, 1 KiB);
+ elsif (scale = 1 MiB) then return div(mem, 1 MiB);
+ elsif (scale = 1 GiB) then return div(mem, 1 GiB);
+-- elsif (scale = 1 TiB) then return div(mem, 1 TiB);
+ else report "to_real: scale must have a value of '1 <unit>'" severity failure;
+ end if;
+ end;
+
+ -- convert physical types to standard type (INTEGER)
+ -- ===========================================================================
+ function to_int(t : TIME; scale : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(t, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(t, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(t, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ end;
+
+ function to_int(f : FREQ; scale : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(f, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(f, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(f, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ end;
+
+ function to_int(br : BAUD; scale : BAUD; RoundingStyle : T_ROUNDING_STYLE := ROUND_TO_NEAREST) return INTEGER is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(br, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(br, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(br, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ end;
+
+ function to_int(mem : MEMORY; scale : MEMORY; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return INTEGER is
+ begin
+ case RoundingStyle is
+ when ROUND_UP => return integer(ceil(to_real(mem, scale)));
+ when ROUND_DOWN => return integer(floor(to_real(mem, scale)));
+ when ROUND_TO_NEAREST => return integer(round(to_real(mem, scale)));
+ when others => null;
+ end case;
+ report "to_int: unsupported RoundingStyle: " & T_ROUNDING_STYLE'image(RoundingStyle) severity failure;
+ end;
+
+ -- calculate needed counter cycles to achieve a given 1. timing/delay and 2. frequency/period
+ -- ===========================================================================
+ -- @param Timing A given timing or delay, which should be achived
+ -- @param Clock_Period The period of the circuits clock
+ -- @RoundingStyle Default = round to nearest; other choises: ROUND_UP, ROUND_DOWN
+ function TimingToCycles(Timing : TIME; Clock_Period : TIME; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return NATURAL is
+ variable res_real : REAL;
+ variable res_nat : NATURAL;
+ variable res_time : TIME;
+ variable res_dev : REAL;
+ begin
+ res_real := div(Timing, Clock_Period);
+ case RoundingStyle is
+ when ROUND_TO_NEAREST => res_nat := natural(round(res_real));
+ when ROUND_UP => res_nat := natural(ceil(res_real));
+ when ROUND_DOWN => res_nat := natural(floor(res_real));
+ when others => report "RoundingStyle '" & T_ROUNDING_STYLE'image(RoundingStyle) & "' not supported." severity failure;
+ end case;
+ res_time := CyclesToDelay(res_nat, Clock_Period);
+ res_dev := (1.0 - div(res_time, Timing)) * 100.0;
+
+ if (POC_VERBOSE = TRUE) then
+ report "TimingToCycles: " & CR &
+ " Timing: " & to_string(Timing, 3) & CR &
+ " Clock_Period: " & to_string(Clock_Period, 3) & CR &
+ " RoundingStyle: " & str_substr(T_ROUNDING_STYLE'image(RoundingStyle), 7) & CR &
+ " res_real = " & str_format(res_real, 3) & CR &
+ " => " & INTEGER'image(res_nat)
+ severity note;
+ end if;
+
+-- if (C_PHYSICAL_REPORT_TIMING_DEVIATION = TRUE) then
+-- report "TimingToCycles (timing deviation report): " & CR &
+-- " timing to achieve: " & to_string(Timing) & CR &
+-- " calculated cycles: " & INTEGER'image(res_nat) & " cy" & CR &
+-- " resulting timing: " & to_string(res_time) & CR &
+-- " deviation: " & to_string(Timing - res_time) & " (" & str_format(res_dev, 2) & "%)"
+-- severity note;
+-- end if;
+
+ return res_nat;
+ end;
+
+ function TimingToCycles(Timing : TIME; Clock_Frequency : FREQ; RoundingStyle : T_ROUNDING_STYLE := ROUND_UP) return NATURAL is
+ begin
+ return TimingToCycles(Timing, to_time(Clock_Frequency), RoundingStyle);
+ end function;
+
+ function CyclesToDelay(Cycles : NATURAL; Clock_Period : TIME) return TIME is
+ begin
+ return Clock_Period * Cycles;
+ end function;
+
+ function CyclesToDelay(Cycles : NATURAL; Clock_Frequency : FREQ) return TIME is
+ begin
+ return CyclesToDelay(Cycles, to_time(Clock_Frequency));
+ end function;
+
+ -- convert and format physical types to STRING
+ function to_string(t : TIME; precision : NATURAL) return STRING is
+ variable unit : STRING(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (t < 1 ps) then
+ unit(1 to 2) := "fs";
+ value := to_real(t, 1 fs);
+ elsif (t < 1 ns) then
+ unit(1 to 2) := "ps";
+ value := to_real(t, 1 ps);
+ elsif (t < 1 us) then
+ unit(1 to 2) := "ns";
+ value := to_real(t, 1 ns);
+ elsif (t < 1 ms) then
+ unit(1 to 2) := "us";
+ value := to_real(t, 1 us);
+ elsif (t < 1 sec) then
+ unit(1 to 2) := "ms";
+ value := to_real(t, 1 ms);
+ else
+ unit := "sec";
+ value := to_real(t, 1 sec);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+ function to_string(f : FREQ; precision : NATURAL) return STRING is
+ variable unit : STRING(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (f < 1 kHz) then
+ unit(1 to 2) := "Hz";
+ value := to_real(f, 1 Hz);
+ elsif (f < 1 MHz) then
+ unit := "kHz";
+ value := to_real(f, 1 kHz);
+ elsif (f < 1 GHz) then
+ unit := "MHz";
+ value := to_real(f, 1 MHz);
+ else --if (f < 1 THz) then
+ unit := "GHz";
+ value := to_real(f, 1 GHz);
+-- else
+-- unit := "THz";
+-- value := to_real(f, 1 THz);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+ function to_string(br : BAUD; precision : NATURAL) return STRING is
+ variable unit : STRING(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (br < 1 kBd) then
+ unit(1 to 2) := "Bd";
+ value := to_real(br, 1 Bd);
+ elsif (br < 1 MBd) then
+ unit := "kBd";
+ value := to_real(br, 1 kBd);
+ elsif (br < 1 GBd) then
+ unit := "MBd";
+ value := to_real(br, 1 MBd);
+ else
+ unit := "GBd";
+ value := to_real(br, 1 GBd);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+ function to_string(mem : MEMORY; precision : NATURAL) return STRING is
+ variable unit : STRING(1 to 3) := (others => C_POC_NUL);
+ variable value : REAL;
+ begin
+ if (mem < 1 KiB) then
+ unit(1) := 'B';
+ value := to_real(mem, 1 Byte);
+ elsif (mem < 1 MiB) then
+ unit := "KiB";
+ value := to_real(mem, 1 KiB);
+ elsif (mem < 1 GiB) then
+ unit := "MiB";
+ value := to_real(mem, 1 MiB);
+ else --if (mem < 1 TiB) then
+ unit := "GiB";
+ value := to_real(mem, 1 GiB);
+-- else
+-- unit := "TiB";
+-- value := to_real(mem, 1 TiB);
+ end if;
+
+ return str_format(value, precision) & " " & str_trim(unit);
+ end function;
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/strings.vhdl b/testsuite/gna/bug019/PoC/src/common/strings.vhdl
new file mode 100644
index 000000000..2d6829cc4
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/strings.vhdl
@@ -0,0 +1,899 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: String related functions and types
+--
+-- Description:
+-- ------------------------------------
+-- For detailed documentation see below.
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use IEEE.math_real.all;
+
+library PoC;
+use PoC.config.all;
+use PoC.utils.all;
+--use PoC.FileIO.all;
+
+
+package strings is
+ -- default fill and string termination character for fixed size strings
+ -- ===========================================================================
+ constant C_POC_NUL : CHARACTER := ite((SYNTHESIS_TOOL /= SYNTHESIS_TOOL_ALTERA_QUARTUS2), NUL, '`');
+ -- character 0 causes Quartus to crash, if uses to pad STRINGs
+ -- characters < 32 (control characters) are not supported in Quartus
+ -- characters > 127 are not supported in VHDL files (strict ASCII files)
+ -- character 255 craches ISE log window (created by 'CHARACTER'val(255)')
+
+ -- Type declarations
+ -- ===========================================================================
+ subtype T_RAWCHAR is STD_LOGIC_VECTOR(7 downto 0);
+ type T_RAWSTRING is array (NATURAL range <>) of T_RAWCHAR;
+
+ -- testing area:
+ -- ===========================================================================
+ function to_IPStyle(str : STRING) return T_IPSTYLE;
+
+ -- to_char
+ function to_char(value : STD_LOGIC) return CHARACTER;
+ function to_char(value : NATURAL) return CHARACTER;
+ function to_char(rawchar : T_RAWCHAR) return CHARACTER;
+
+ -- chr_is* function
+ function chr_isDigit(chr : character) return boolean;
+ function chr_isLowerHexDigit(chr : character) return boolean;
+ function chr_isUpperHexDigit(chr : character) return boolean;
+ function chr_isHexDigit(chr : character) return boolean;
+ function chr_isLower(chr : character) return boolean;
+ function chr_isLowerAlpha(chr : character) return boolean;
+ function chr_isUpper(chr : character) return boolean;
+ function chr_isUpperAlpha(chr : character) return boolean;
+ function chr_isAlpha(chr : character) return boolean;
+
+ -- raw_format_* functions
+ function raw_format_bool_bin(value : BOOLEAN) return STRING;
+ function raw_format_bool_chr(value : BOOLEAN) return STRING;
+ function raw_format_bool_str(value : BOOLEAN) return STRING;
+ function raw_format_slv_bin(slv : STD_LOGIC_VECTOR) return STRING;
+ function raw_format_slv_oct(slv : STD_LOGIC_VECTOR) return STRING;
+ function raw_format_slv_dec(slv : STD_LOGIC_VECTOR) return STRING;
+ function raw_format_slv_hex(slv : STD_LOGIC_VECTOR) return STRING;
+ function raw_format_nat_bin(value : NATURAL) return STRING;
+ function raw_format_nat_oct(value : NATURAL) return STRING;
+ function raw_format_nat_dec(value : NATURAL) return STRING;
+ function raw_format_nat_hex(value : NATURAL) return STRING;
+
+ -- str_format_* functions
+ function str_format(value : REAL; precision : NATURAL := 3) return STRING;
+
+ -- to_string
+ function to_string(value : BOOLEAN) return STRING;
+ function to_string(value : INTEGER; base : POSITIVE := 10) return STRING;
+ function to_string(slv : STD_LOGIC_VECTOR; format : CHARACTER; length : NATURAL := 0; fill : CHARACTER := '0') return STRING;
+ function to_string(rawstring : T_RAWSTRING) return STRING;
+
+ -- to_slv
+ function to_slv(rawstring : T_RAWSTRING) return STD_LOGIC_VECTOR;
+
+ -- to_digit*
+ function to_digit_bin(chr : character) return integer;
+ function to_digit_oct(chr : character) return integer;
+ function to_digit_dec(chr : character) return integer;
+ function to_digit_hex(chr : character) return integer;
+ function to_digit(chr : character; base : character := 'd') return integer;
+
+ -- to_natural*
+ function to_natural_bin(str : STRING) return INTEGER;
+ function to_natural_oct(str : STRING) return INTEGER;
+ function to_natural_dec(str : STRING) return INTEGER;
+ function to_natural_hex(str : STRING) return INTEGER;
+ function to_natural(str : STRING; base : CHARACTER := 'd') return INTEGER;
+
+ -- to_raw*
+ function to_RawChar(char : character) return T_RAWCHAR;
+ function to_RawString(str : string) return T_RAWSTRING;
+
+ -- resize
+ function resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := C_POC_NUL) return STRING;
+-- function resize(rawstr : T_RAWSTRING; size : POSITIVE; FillChar : T_RAWCHAR := x"00") return T_RAWSTRING;
+
+ -- Character functions
+ function chr_toLower(chr : character) return character;
+ function chr_toUpper(chr : character) return character;
+
+ -- String functions
+ function str_length(str : STRING) return NATURAL;
+ function str_equal(str1 : STRING; str2 : STRING) return BOOLEAN;
+ function str_match(str1 : STRING; str2 : STRING) return BOOLEAN;
+ function str_imatch(str1 : STRING; str2 : STRING) return BOOLEAN;
+ function str_pos(str : STRING; chr : CHARACTER; start : NATURAL := 0) return INTEGER;
+ function str_pos(str : STRING; pattern : STRING; start : NATURAL := 0) return INTEGER;
+ function str_ipos(str : STRING; chr : CHARACTER; start : NATURAL := 0) return INTEGER;
+ function str_ipos(str : STRING; pattern : STRING; start : NATURAL := 0) return INTEGER;
+ function str_find(str : STRING; chr : CHARACTER) return BOOLEAN;
+ function str_find(str : STRING; pattern : STRING) return BOOLEAN;
+ function str_ifind(str : STRING; chr : CHARACTER) return BOOLEAN;
+ function str_ifind(str : STRING; pattern : STRING) return BOOLEAN;
+ function str_replace(str : STRING; pattern : STRING; replace : STRING) return STRING;
+ function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING;
+ function str_ltrim(str : STRING; char : CHARACTER := ' ') return STRING;
+ function str_rtrim(str : STRING; char : CHARACTER := ' ') return STRING;
+ function str_trim(str : STRING) return STRING;
+ function str_toLower(str : STRING) return STRING;
+ function str_toUpper(str : STRING) return STRING;
+
+end package;
+
+
+package body strings is
+
+ --
+ function to_IPStyle(str : STRING) return T_IPSTYLE is
+ begin
+ for i in T_IPSTYLE'pos(T_IPSTYLE'low) to T_IPSTYLE'pos(T_IPSTYLE'high) loop
+ if str_imatch(str, T_IPSTYLE'image(T_IPSTYLE'val(I))) then
+ return T_IPSTYLE'val(i);
+ end if;
+ end loop;
+
+ report "Unknown IPStyle: '" & str & "'" severity FAILURE;
+ end function;
+
+ -- to_char
+ -- ===========================================================================
+ function to_char(value : STD_LOGIC) return CHARACTER is
+ begin
+ case value IS
+ when 'U' => return 'U';
+ when 'X' => return 'X';
+ when '0' => return '0';
+ when '1' => return '1';
+ when 'Z' => return 'Z';
+ when 'W' => return 'W';
+ when 'L' => return 'L';
+ when 'H' => return 'H';
+ when '-' => return '-';
+ when others => return 'X';
+ end case;
+ end function;
+
+ -- TODO: rename to to_HexDigit(..) ?
+ function to_char(value : natural) return character is
+ constant HEX : string := "0123456789ABCDEF";
+ begin
+ return ite(value < 16, HEX(value+1), 'X');
+ end function;
+
+ function to_char(rawchar : T_RAWCHAR) return CHARACTER is
+ begin
+ return CHARACTER'val(to_integer(unsigned(rawchar)));
+ end function;
+
+ -- chr_is* function
+ function chr_isDigit(chr : character) return boolean is
+ begin
+ return (character'pos('0') <= character'pos(chr)) and (character'pos(chr) <= character'pos('9'));
+ end function;
+
+ function chr_isLowerHexDigit(chr : character) return boolean is
+ begin
+ return (character'pos('a') <= character'pos(chr)) and (character'pos(chr) <= character'pos('f'));
+ end function;
+
+ function chr_isUpperHexDigit(chr : character) return boolean is
+ begin
+ return (character'pos('A') <= character'pos(chr)) and (character'pos(chr) <= character'pos('F'));
+ end function;
+
+ function chr_isHexDigit(chr : character) return boolean is
+ begin
+ return chr_isDigit(chr) or chr_isLowerHexDigit(chr) or chr_isUpperHexDigit(chr);
+ end function;
+
+ function chr_isLower(chr : character) return boolean is
+ begin
+ return chr_isLowerAlpha(chr);
+ end function;
+
+ function chr_isLowerAlpha(chr : character) return boolean is
+ begin
+ return (character'pos('a') <= character'pos(chr)) and (character'pos(chr) <= character'pos('z'));
+ end function;
+
+ function chr_isUpper(chr : character) return boolean is
+ begin
+ return chr_isUpperAlpha(chr);
+ end function;
+
+ function chr_isUpperAlpha(chr : character) return boolean is
+ begin
+ return (character'pos('A') <= character'pos(chr)) and (character'pos(chr) <= character'pos('Z'));
+ end function;
+
+ function chr_isAlpha(chr : character) return boolean is
+ begin
+ return chr_isLowerAlpha(chr) or chr_isUpperAlpha(chr);
+ end function;
+
+ -- raw_format_* functions
+ -- ===========================================================================
+ function raw_format_bool_bin(value : BOOLEAN) return STRING is
+ begin
+ return ite(value, "1", "0");
+ end function;
+
+ function raw_format_bool_chr(value : BOOLEAN) return STRING is
+ begin
+ return ite(value, "T", "F");
+ end function;
+
+ function raw_format_bool_str(value : BOOLEAN) return STRING is
+ begin
+ return str_toUpper(boolean'image(value));
+ end function;
+
+ function raw_format_slv_bin(slv : STD_LOGIC_VECTOR) return STRING is
+ variable Value : STD_LOGIC_VECTOR(slv'length - 1 downto 0);
+ variable Result : STRING(1 to slv'length);
+ variable j : NATURAL;
+ begin
+ -- convert input slv to a downto ranged vector and normalize range to slv'low = 0
+ Value := movez(ite(slv'ascending, descend(slv), slv));
+
+ -- convert each bit to a character
+ J := 0;
+ for i in Result'reverse_range loop
+ Result(i) := to_char(Value(j));
+ j := j + 1;
+ end loop;
+
+ return Result;
+ end function;
+
+ function raw_format_slv_oct(slv : STD_LOGIC_VECTOR) return STRING is
+ variable Value : STD_LOGIC_VECTOR(slv'length - 1 downto 0);
+ variable Digit : STD_LOGIC_VECTOR(2 downto 0);
+ variable Result : STRING(1 to div_ceil(slv'length, 3));
+ variable j : NATURAL;
+ begin
+ -- convert input slv to a downto ranged vector; normalize range to slv'low = 0 and resize it to a multiple of 3
+ Value := resize(movez(ite(slv'ascending, descend(slv), slv)), (Result'length * 3));
+
+ -- convert 3 bit to a character
+ j := 0;
+ for i in Result'reverse_range loop
+ Digit := Value((j * 3) + 2 downto (j * 3));
+ Result(i) := to_char(to_integer(unsigned(Digit)));
+ j := j + 1;
+ end loop;
+
+ return Result;
+ end function;
+
+ function raw_format_slv_dec(slv : STD_LOGIC_VECTOR) return STRING is
+ variable Value : STD_LOGIC_VECTOR(slv'length - 1 downto 0);
+ variable Result : STRING(1 to div_ceil(slv'length, 3));
+
+ subtype TT_BCD is INTEGER range 0 to 31;
+ type TT_BCD_VECTOR is array(natural range <>) of TT_BCD;
+
+ variable Temp : TT_BCD_VECTOR(div_ceil(slv'length, 3) - 1 downto 0);
+ variable Carry : T_UINT_8;
+
+ variable Pos : NATURAL;
+ begin
+ Temp := (others => 0);
+ Pos := 0;
+
+ -- convert input slv to a downto ranged vector
+ Value := ite(slv'ascending, descend(slv), slv);
+
+ for i in Value'range loop
+ Carry := to_int(Value(i));
+ for j in Temp'reverse_range loop
+ Temp(j) := Temp(j) * 2 + Carry;
+ Carry := to_int(Temp(j) > 9);
+ Temp(j) := Temp(j) - to_int((Temp(j) > 9), 0, 10);
+ end loop;
+ end loop;
+
+ for i in Result'range loop
+ Result(i) := to_char(Temp(Temp'high - i + 1));
+ if ((Result(i) /= '0') and (Pos = 0)) then
+ Pos := i;
+ end if;
+ end loop;
+
+ -- trim leading zeros, except the last
+ return Result(imin(Pos, Result'high) to Result'high);
+ end function;
+
+ function raw_format_slv_hex(slv : STD_LOGIC_VECTOR) return STRING is
+ variable Value : STD_LOGIC_VECTOR(4*div_ceil(slv'length, 4) - 1 downto 0);
+ variable Digit : STD_LOGIC_VECTOR(3 downto 0);
+ variable Result : STRING(1 to div_ceil(slv'length, 4));
+ variable j : NATURAL;
+ begin
+ Value := resize(slv, Value'length);
+ j := 0;
+ for i in Result'reverse_range loop
+ Digit := Value((j * 4) + 3 downto (j * 4));
+ Result(i) := to_char(to_integer(unsigned(Digit)));
+ j := j + 1;
+ end loop;
+
+ return Result;
+ end function;
+
+ function raw_format_nat_bin(value : NATURAL) return STRING is
+ begin
+ return raw_format_slv_bin(to_slv(value, log2ceilnz(value+1)));
+ end function;
+
+ function raw_format_nat_oct(value : NATURAL) return STRING is
+ begin
+ return raw_format_slv_oct(to_slv(value, log2ceilnz(value+1)));
+ end function;
+
+ function raw_format_nat_dec(value : NATURAL) return STRING is
+ begin
+ return INTEGER'image(value);
+ end function;
+
+ function raw_format_nat_hex(value : NATURAL) return STRING is
+ begin
+ return raw_format_slv_hex(to_slv(value, log2ceilnz(value+1)));
+ end function;
+
+ -- str_format_* functions
+ -- ===========================================================================
+ function str_format(value : REAL; precision : NATURAL := 3) return STRING is
+ constant s : REAL := sign(value);
+ constant val : REAL := value * s;
+ constant int : INTEGER := integer(floor(val));
+ constant frac : INTEGER := integer(round((val - real(int)) * 10.0**precision));
+ constant frac_str : STRING := INTEGER'image(frac);
+ constant res : STRING := INTEGER'image(int) & "." & (1 to (precision - frac_str'length) => '0') & frac_str;
+ begin
+ return ite ((s < 0.0), "-" & res, res);
+ end function;
+
+ -- to_string
+ -- ===========================================================================
+ function to_string(value : boolean) return string is
+ begin
+ return raw_format_bool_str(value);
+ end function;
+
+ function to_string(value : INTEGER; base : POSITIVE := 10) return STRING is
+ constant absValue : NATURAL := abs(value);
+ constant len : POSITIVE := log10ceilnz(absValue);
+ variable power : POSITIVE;
+ variable Result : STRING(1 TO len);
+
+ begin
+ power := 1;
+
+ if (base = 10) then
+ return INTEGER'image(value);
+ else
+ for i in len downto 1 loop
+ Result(i) := to_char(absValue / power MOD base);
+ power := power * base;
+ end loop;
+
+ if (value < 0) then
+ return '-' & Result;
+ else
+ return Result;
+ end if;
+ end if;
+ end function;
+
+ -- TODO: rename to slv_format(..) ?
+ function to_string(slv : STD_LOGIC_VECTOR; format : CHARACTER; length : NATURAL := 0; fill : CHARACTER := '0') return STRING is
+ constant int : INTEGER := ite((slv'length <= 31), to_integer(unsigned(resize(slv, 31))), 0);
+ constant str : STRING := INTEGER'image(int);
+ constant bin_len : POSITIVE := slv'length;
+ constant dec_len : POSITIVE := str'length;--log10ceilnz(int);
+ constant hex_len : POSITIVE := ite(((bin_len MOD 4) = 0), (bin_len / 4), (bin_len / 4) + 1);
+ constant len : NATURAL := ite((format = 'b'), bin_len,
+ ite((format = 'd'), dec_len,
+ ite((format = 'h'), hex_len, 0)));
+ variable j : NATURAL;
+ variable Result : STRING(1 to ite((length = 0), len, imax(len, length)));
+ begin
+ j := 0;
+ Result := (others => fill);
+
+ if (format = 'b') then
+ for i in Result'reverse_range loop
+ Result(i) := to_char(slv(j));
+ j := j + 1;
+ end loop;
+ elsif (format = 'd') then
+-- if (slv'length < 32) then
+-- return INTEGER'image(int);
+-- else
+-- return raw_format_slv_dec(slv);
+-- end if;
+ Result(Result'length - str'length + 1 to Result'high) := str;
+ elsif (format = 'h') then
+ for i in Result'reverse_range loop
+ Result(i) := to_char(to_integer(unsigned(slv((j * 4) + 3 downto (j * 4)))));
+ j := j + 1;
+ end loop;
+ else
+ report "unknown format" severity FAILURE;
+ end if;
+
+ return Result;
+ end function;
+
+ function to_string(rawstring : T_RAWSTRING) return STRING is
+ variable str : STRING(1 to rawstring'length);
+ begin
+ for i in rawstring'low to rawstring'high loop
+ str(I - rawstring'low + 1) := to_char(rawstring(I));
+ end loop;
+
+ return str;
+ end function;
+
+ -- to_slv
+ -- ===========================================================================
+ function to_slv(rawstring : T_RAWSTRING) return STD_LOGIC_VECTOR is
+ variable result : STD_LOGIC_VECTOR((rawstring'length * 8) - 1 downto 0);
+ begin
+ for i in rawstring'range loop
+ result(((i - rawstring'low) * 8) + 7 downto (i - rawstring'low) * 8) := rawstring(i);
+ end loop;
+ return result;
+ end function;
+
+ -- to_*
+ -- ===========================================================================
+ function to_digit_bin(chr : character) return integer is
+ begin
+ case chr is
+ when '0' => return 0;
+ when '1' => return 1;
+ when others => return -1;
+ end case;
+ end function;
+
+ function to_digit_oct(chr : character) return integer is
+ variable dec : integer;
+ begin
+ dec := to_digit_dec(chr);
+ return ite((dec < 8), dec, -1);
+ end function;
+
+ function to_digit_dec(chr : character) return integer is
+ begin
+ if chr_isDigit(chr) then
+ return character'pos(chr) - character'pos('0');
+ else
+ return -1;
+ end if;
+ end function;
+
+ function to_digit_hex(chr : character) return integer is
+ begin
+ if chr_isDigit(chr) then return character'pos(chr) - character'pos('0');
+ elsif chr_isLowerHexDigit(chr) then return character'pos(chr) - character'pos('a') + 10;
+ elsif chr_isUpperHexDigit(chr) then return character'pos(chr) - character'pos('A') + 10;
+ else return -1;
+ end if;
+ end function;
+
+ function to_digit(chr : character; base : character := 'd') return integer is
+ begin
+ case base is
+ when 'b' => return to_digit_bin(chr);
+ when 'o' => return to_digit_oct(chr);
+ when 'd' => return to_digit_dec(chr);
+ when 'h' => return to_digit_hex(chr);
+ when others => report "Unknown base character: " & base & "." severity failure;
+ -- return statement is explicitly missing otherwise XST won't stop
+ end case;
+ end function;
+
+ function to_natural_bin(str : STRING) return INTEGER is
+ variable Result : NATURAL;
+ variable Digit : INTEGER;
+ begin
+ for i in str'range loop
+ Digit := to_digit_bin(str(I));
+ if (Digit /= -1) then
+ Result := Result * 2 + Digit;
+ else
+ return -1;
+ end if;
+ end loop;
+
+ return Result;
+ end function;
+
+ function to_natural_oct(str : STRING) return INTEGER is
+ variable Result : NATURAL;
+ variable Digit : INTEGER;
+ begin
+ for i in str'range loop
+ Digit := to_digit_oct(str(I));
+ if (Digit /= -1) then
+ Result := Result * 8 + Digit;
+ else
+ return -1;
+ end if;
+ end loop;
+
+ return Result;
+ end function;
+
+ function to_natural_dec(str : STRING) return INTEGER is
+ variable Result : NATURAL;
+ variable Digit : INTEGER;
+ begin
+ for i in str'range loop
+ Digit := to_digit_dec(str(I));
+ if (Digit /= -1) then
+ Result := Result * 10 + Digit;
+ else
+ return -1;
+ end if;
+ end loop;
+
+ return Result;
+-- return INTEGER'value(str); -- 'value(...) is not supported by Vivado Synth 2014.1
+ end function;
+
+ function to_natural_hex(str : STRING) return INTEGER is
+ variable Result : NATURAL;
+ variable Digit : INTEGER;
+ begin
+ for i in str'range loop
+ Digit := to_digit_hex(str(I));
+ if (Digit /= -1) then
+ Result := Result * 16 + Digit;
+ else
+ return -1;
+ end if;
+ end loop;
+
+ return Result;
+ end function;
+
+ function to_natural(str : STRING; base : CHARACTER := 'd') return INTEGER is
+ begin
+ case base is
+ when 'b' => return to_natural_bin(str);
+ when 'o' => return to_natural_oct(str);
+ when 'd' => return to_natural_dec(str);
+ when 'h' => return to_natural_hex(str);
+ when others => report "unknown base" severity ERROR;
+ end case;
+ end function;
+
+ -- to_raw*
+ -- ===========================================================================
+ function to_RawChar(char : character) return t_rawchar is
+ begin
+ return std_logic_vector(to_unsigned(character'pos(char), t_rawchar'length));
+ end function;
+
+ function to_RawString(str : STRING) return T_RAWSTRING is
+ variable rawstr : T_RAWSTRING(0 to str'length - 1);
+ begin
+ for i in str'low to str'high loop
+ rawstr(i - str'low) := to_RawChar(str(i));
+ end loop;
+ return rawstr;
+ end function;
+
+ -- resize
+ -- ===========================================================================
+ function resize(str : STRING; size : POSITIVE; FillChar : CHARACTER := C_POC_NUL) return STRING is
+ constant ConstNUL : STRING(1 to 1) := (others => C_POC_NUL);
+ variable Result : STRING(1 to size);
+ begin
+ Result := (others => FillChar);
+ if (str'length > 0) then
+ Result(1 to imin(size, imax(1, str'length))) := ite((str'length > 0), str(1 to imin(size, str'length)), ConstNUL);
+ end if;
+ return Result;
+ end function;
+
+-- function resize(str : T_RAWSTRING; size : POSITIVE; FillChar : T_RAWCHAR := x"00") return T_RAWSTRING is
+-- constant ConstNUL : T_RAWSTRING(1 to 1) := (others => x"00");
+-- variable Result : T_RAWSTRING(1 to size);
+-- function ifthenelse(cond : BOOLEAN; value1 : T_RAWSTRING; value2 : T_RAWSTRING) return T_RAWSTRING is
+-- begin
+-- if cond then
+-- return value1;
+-- else
+-- return value2;
+-- end if;
+-- end function;
+-- begin
+-- Result := (others => FillChar);
+-- if (str'length > 0) then
+-- Result(1 to imin(size, imax(1, str'length))) := ifthenelse((str'length > 0), str(1 to imin(size, str'length)), ConstNUL);
+-- end if;
+-- return Result;
+-- end function;
+
+
+ -- Character functions
+ -- ===========================================================================
+ function chr_toLower(chr : character) return character is
+ begin
+ if chr_isUpperAlpha(chr) then
+ return character'val(character'pos(chr) - character'pos('A') + character'pos('a'));
+ else
+ return chr;
+ end if;
+ end function;
+
+ function chr_toUpper(chr : character) return character is
+ begin
+ if chr_isLowerAlpha(chr) then
+ return character'val(character'pos(chr) - character'pos('a') + character'pos('A'));
+ else
+ return chr;
+ end if;
+ end function;
+
+ -- String functions
+ -- ===========================================================================
+ function str_length(str : STRING) return NATURAL is
+ begin
+ for i in str'range loop
+ if (str(i) = C_POC_NUL) then
+ return i - str'low;
+ end if;
+ end loop;
+ return str'length;
+ end function;
+
+ function str_equal(str1 : STRING; str2 : STRING) return BOOLEAN is
+ begin
+ if str1'length /= str2'length then
+ return FALSE;
+ else
+ return (str1 = str2);
+ end if;
+ end function;
+
+ function str_match(str1 : STRING; str2 : STRING) return BOOLEAN is
+ constant len : NATURAL := imin(str1'length, str2'length);
+ begin
+ -- if both strings are empty
+ if ((str1'length = 0 ) and (str2'length = 0)) then return TRUE; end if;
+ -- compare char by char
+ for i in str1'low to str1'low + len - 1 loop
+ if (str1(i) /= str2(str2'low + (i - str1'low))) then
+ return FALSE;
+ elsif ((str1(i) = C_POC_NUL) xor (str2(str2'low + (i - str1'low)) = C_POC_NUL)) then
+ return FALSE;
+ elsif ((str1(i) = C_POC_NUL) and (str2(str2'low + (i - str1'low)) = C_POC_NUL)) then
+ return TRUE;
+ end if;
+ end loop;
+ -- check special cases,
+ return (((str1'length = len) and (str2'length = len)) or -- both strings are fully consumed and equal
+ ((str1'length > len) and (str1(str1'low + len) = C_POC_NUL)) or -- str1 is longer, but str_length equals len
+ ((str2'length > len) and (str2(str2'low + len) = C_POC_NUL))); -- str2 is longer, but str_length equals len
+ end function;
+
+ function str_imatch(str1 : STRING; str2 : STRING) return BOOLEAN is
+ begin
+ return str_match(str_toLower(str1), str_toLower(str2));
+ end function;
+
+ function str_pos(str : STRING; chr : CHARACTER; start : NATURAL := 0) return INTEGER is
+ begin
+ for i in imax(str'low, start) to str'high loop
+ exit when (str(i) = C_POC_NUL);
+ if (str(i) = chr) then
+ return i;
+ end if;
+ end loop;
+ return -1;
+ end function;
+
+ function str_pos(str : STRING; pattern : STRING; start : NATURAL := 0) return INTEGER is
+ begin
+ for i in imax(str'low, start) to (str'high - pattern'length + 1) loop
+ exit when (str(i) = C_POC_NUL);
+ if (str(i to i + pattern'length - 1) = pattern) then
+ return i;
+ end if;
+ end loop;
+ return -1;
+ end function;
+
+ function str_ipos(str : STRING; chr : CHARACTER; start : NATURAL := 0) return INTEGER is
+ begin
+ return str_pos(str_toLower(str), chr_toLower(chr));
+ end function;
+
+ function str_ipos(str : STRING; pattern : STRING; start : NATURAL := 0) return INTEGER is
+ begin
+ return str_pos(str_toLower(str), str_toLower(pattern));
+ end function;
+
+-- function str_pos(str1 : STRING; str2 : STRING) return INTEGER is
+-- variable PrefixTable : T_INTVEC(0 to str2'length);
+-- variable j : INTEGER;
+-- begin
+-- -- construct prefix table for KMP algorithm
+-- j := -1;
+-- PrefixTable(0) := -1;
+-- for i in str2'range loop
+-- while ((j >= 0) and str2(j + 1) /= str2(i)) loop
+-- j := PrefixTable(j);
+-- end loop;
+--
+-- j := j + 1;
+-- PrefixTable(i - 1) := j + 1;
+-- end loop;
+--
+-- -- search pattern str2 in text str1
+-- j := 0;
+-- for i in str1'range loop
+-- while ((j >= 0) and str1(i) /= str2(j + 1)) loop
+-- j := PrefixTable(j);
+-- end loop;
+--
+-- j := j + 1;
+-- if ((j + 1) = str2'high) then
+-- return i - str2'length + 1;
+-- end if;
+-- end loop;
+--
+-- return -1;
+-- end function;
+
+ function str_find(str : STRING; chr : CHARACTER) return boolean is
+ begin
+ return (str_pos(str, chr) > 0);
+ end function;
+
+ function str_find(str : STRING; pattern : STRING) return boolean is
+ begin
+ return (str_pos(str, pattern) > 0);
+ end function;
+
+ function str_ifind(str : STRING; chr : CHARACTER) return boolean is
+ begin
+ return (str_ipos(str, chr) > 0);
+ end function;
+
+ function str_ifind(str : STRING; pattern : STRING) return boolean is
+ begin
+ return (str_ipos(str, pattern) > 0);
+ end function;
+
+ function str_replace(str : STRING; pattern : STRING; replace : STRING) return STRING is
+ variable pos : INTEGER;
+ begin
+ pos := str_pos(str, pattern);
+ if (pos > 0) then
+ if (pos = 1) then
+ return replace & str(pattern'length + 1 to str'length);
+ elsif (pos = str'length - pattern'length + 1) then
+ return str(1 to str'length - pattern'length) & replace;
+ else
+ return str(1 to pos - 1) & replace & str(pos + pattern'length to str'length);
+ end if;
+ else
+ return str;
+ end if;
+ end function;
+
+ -- examples:
+ -- 123456789ABC
+ -- input string: "Hello World."
+ -- low=1; high=12; length=12
+ --
+ -- str_substr("Hello World.", 0, 0) => "Hello World." - copy all
+ -- str_substr("Hello World.", 7, 0) => "World." - copy from pos 7 to end of string
+ -- str_substr("Hello World.", 7, 5) => "World" - copy from pos 7 for 5 characters
+ -- str_substr("Hello World.", 0, -7) => "Hello World." - copy all until character 8 from right boundary
+ function str_substr(str : STRING; start : INTEGER := 0; length : INTEGER := 0) return STRING is
+ variable StartOfString : positive;
+ variable EndOfString : positive;
+ begin
+ if (start < 0) then -- start is negative -> start substring at right string boundary
+ StartOfString := str'high + start + 1;
+ elsif (start = 0) then -- start is zero -> start substring at left string boundary
+ StartOfString := str'low;
+ else -- start is positive -> start substring at left string boundary + offset
+ StartOfString := start;
+ end if;
+
+ if (length < 0) then -- length is negative -> end substring at length'th character before right string boundary
+ EndOfString := str'high + length;
+ elsif (length = 0) then -- length is zero -> end substring at right string boundary
+ EndOfString := str'high;
+ else -- length is positive -> end substring at StartOfString + length
+ EndOfString := StartOfString + length - 1;
+ end if;
+
+ if (StartOfString < str'low) then report "StartOfString is out of str's range. (str=" & str & ")" severity error; end if;
+ if (EndOfString < str'high) then report "EndOfString is out of str's range. (str=" & str & ")" severity error; end if;
+
+ return str(StartOfString to EndOfString);
+ end function;
+
+ function str_ltrim(str : STRING; char : CHARACTER := ' ') return STRING is
+ begin
+ for i in str'range loop
+ if (str(i) /= char) then
+ return str(i to str'high);
+ end if;
+ end loop;
+ return "";
+ end function;
+
+ function str_rtrim(str : STRING; char : CHARACTER := ' ') return STRING is
+ begin
+ for i in str'reverse_range loop
+ if (str(i) /= char) then
+ return str(str'low to i);
+ end if;
+ end loop;
+ return "";
+ end function;
+
+ function str_trim(str : STRING) return STRING is
+ begin
+ return str(str'low to str'low + str_length(str) - 1);
+ end function;
+
+ function str_toLower(str : STRING) return STRING is
+ variable temp : STRING(str'range);
+ begin
+ for i in str'range loop
+ temp(I) := chr_toLower(str(I));
+ end loop;
+ return temp;
+ end function;
+
+ function str_toUpper(str : STRING) return STRING is
+ variable temp : STRING(str'range);
+ begin
+ for i in str'range loop
+ temp(I) := chr_toUpper(str(I));
+ end loop;
+ return temp;
+ end function;
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/utils.vhdl b/testsuite/gna/bug019/PoC/src/common/utils.vhdl
new file mode 100644
index 000000000..ec6058b22
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/utils.vhdl
@@ -0,0 +1,946 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Package: Common functions and types
+--
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Description:
+-- ------------------------------------
+-- For detailed documentation see below.
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.my_config.all;
+
+
+package utils is
+ -- PoC settings
+ -- ==========================================================================
+ constant POC_VERBOSE : BOOLEAN := MY_VERBOSE;
+
+ -- Environment
+ -- ==========================================================================
+ -- Distinguishes simulation from synthesis
+ constant SIMULATION : BOOLEAN; -- deferred constant declaration
+
+ -- Type declarations
+ -- ==========================================================================
+
+ --+ Vectors of primitive standard types +++++++++++++++++++++++++++++++++++++
+ type T_BOOLVEC is array(NATURAL range <>) of BOOLEAN;
+ type T_INTVEC is array(NATURAL range <>) of INTEGER;
+ type T_NATVEC is array(NATURAL range <>) of NATURAL;
+ type T_POSVEC is array(NATURAL range <>) of POSITIVE;
+ type T_REALVEC is array(NATURAL range <>) of REAL;
+
+ --+ Integer subranges sometimes useful for speeding up simulation ++++++++++
+ subtype T_INT_8 is INTEGER range -128 to 127;
+ subtype T_INT_16 is INTEGER range -32768 to 32767;
+ subtype T_UINT_8 is INTEGER range 0 to 255;
+ subtype T_UINT_16 is INTEGER range 0 to 65535;
+
+ --+ Enums ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ -- Intellectual Property (IP) type
+ type T_IPSTYLE is (IPSTYLE_HARD, IPSTYLE_SOFT);
+
+ -- Bit Order
+ type T_BIT_ORDER is (LSB_FIRST, MSB_FIRST);
+
+ -- Byte Order (Endian)
+ type T_BYTE_ORDER is (LITTLE_ENDIAN, BIG_ENDIAN);
+
+ -- rounding style
+ type T_ROUNDING_STYLE is (ROUND_TO_NEAREST, ROUND_TO_ZERO, ROUND_TO_INF, ROUND_UP, ROUND_DOWN);
+
+ type T_BCD is array(3 downto 0) of std_logic;
+ type T_BCD_VECTOR is array(NATURAL range <>) of T_BCD;
+ constant C_BCD_MINUS : T_BCD := "1010";
+ constant C_BCD_OFF : T_BCD := "1011";
+
+
+ -- Function declarations
+ -- ==========================================================================
+
+ --+ Division ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ -- Calculates: ceil(a / b)
+ function div_ceil(a : NATURAL; b : POSITIVE) return NATURAL;
+
+ --+ Power +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ -- is input a power of 2?
+ function is_pow2(int : NATURAL) return BOOLEAN;
+ -- round to next power of 2
+ function ceil_pow2(int : NATURAL) return POSITIVE;
+ -- round to previous power of 2
+ function floor_pow2(int : NATURAL) return NATURAL;
+
+ --+ Logarithm ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ -- Calculates: ceil(ld(arg))
+ function log2ceil(arg : positive) return natural;
+ -- Calculates: max(1, ceil(ld(arg)))
+ function log2ceilnz(arg : positive) return positive;
+ -- Calculates: ceil(lg(arg))
+ function log10ceil(arg : POSITIVE) return NATURAL;
+ -- Calculates: max(1, ceil(lg(arg)))
+ function log10ceilnz(arg : POSITIVE) return POSITIVE;
+
+ --+ if-then-else (ite) +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ function ite(cond : BOOLEAN; value1 : BOOLEAN; value2 : BOOLEAN) return BOOLEAN;
+ function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER;
+ function ite(cond : BOOLEAN; value1 : REAL; value2 : REAL) return REAL;
+ function ite(cond : BOOLEAN; value1 : STD_LOGIC; value2 : STD_LOGIC) return STD_LOGIC;
+ function ite(cond : BOOLEAN; value1 : STD_LOGIC_VECTOR; value2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
+ function ite(cond : BOOLEAN; value1 : BIT_VECTOR; value2 : BIT_VECTOR) return BIT_VECTOR;
+ function ite(cond : BOOLEAN; value1 : UNSIGNED; value2 : UNSIGNED) return UNSIGNED;
+ function ite(cond : BOOLEAN; value1 : CHARACTER; value2 : CHARACTER) return CHARACTER;
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING;
+
+ --+ Max / Min / Sum ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ function imin(arg1 : integer; arg2 : integer) return integer; -- Calculates: min(arg1, arg2) for integers
+ function rmin(arg1 : real; arg2 : real) return real; -- Calculates: min(arg1, arg2) for reals
+
+ function imin(vec : T_INTVEC) return INTEGER; -- Calculates: min(vec) for a integer vector
+ function imin(vec : T_NATVEC) return NATURAL; -- Calculates: min(vec) for a natural vector
+ function imin(vec : T_POSVEC) return POSITIVE; -- Calculates: min(vec) for a positive vector
+ function rmin(vec : T_REALVEC) return real; -- Calculates: min(vec) of real vector
+
+ function imax(arg1 : integer; arg2 : integer) return integer; -- Calculates: max(arg1, arg2) for integers
+ function rmax(arg1 : real; arg2 : real) return real; -- Calculates: max(arg1, arg2) for reals
+
+ function imax(vec : T_INTVEC) return INTEGER; -- Calculates: max(vec) for a integer vector
+ function imax(vec : T_NATVEC) return NATURAL; -- Calculates: max(vec) for a natural vector
+ function imax(vec : T_POSVEC) return POSITIVE; -- Calculates: max(vec) for a positive vector
+ function rmax(vec : T_REALVEC) return real; -- Calculates: max(vec) of real vector
+
+ function isum(vec : T_NATVEC) return NATURAL; -- Calculates: sum(vec) for a natural vector
+ function isum(vec : T_POSVEC) return POSITIVE; -- Calculates: sum(vec) for a positive vector
+ function isum(vec : T_INTVEC) return integer; -- Calculates: sum(vec) of integer vector
+ function rsum(vec : T_REALVEC) return real; -- Calculates: sum(vec) of real vector
+
+ --+ Conversions ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ -- to integer: to_int
+ function to_int(bool : BOOLEAN; zero : INTEGER := 0; one : INTEGER := 1) return INTEGER;
+ function to_int(sl : STD_LOGIC; zero : INTEGER := 0; one : INTEGER := 1) return INTEGER;
+
+ -- to std_logic: to_sl
+ function to_sl(Value : BOOLEAN) return STD_LOGIC;
+ function to_sl(Value : CHARACTER) return STD_LOGIC;
+
+ -- to std_logic_vector: to_slv
+ function to_slv(Value : NATURAL; Size : POSITIVE) return STD_LOGIC_VECTOR; -- short for std_logic_vector(to_unsigned(Value, Size))
+
+ -- TODO: comment
+ function to_index(slv : UNSIGNED; max : NATURAL := 0) return INTEGER;
+ function to_index(slv : STD_LOGIC_VECTOR; max : NATURAL := 0) return INTEGER;
+
+ -- is_*
+ function is_sl(c : CHARACTER) return BOOLEAN;
+
+ --+ Basic Vector Utilities +++++++++++++++++++++++++++++++++++++++++++++++++
+
+ -- Aggregate functions
+ function slv_or (vec : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function slv_nor (vec : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function slv_and (vec : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function slv_nand(vec : STD_LOGIC_VECTOR) return STD_LOGIC;
+ function slv_xor (vec : std_logic_vector) return std_logic;
+ -- NO slv_xnor! This operation would not be well-defined as
+ -- not xor(vec) /= vec_{n-1} xnor ... xnor vec_1 xnor vec_0 iff n is odd.
+
+ -- Reverses the elements of the passed Vector.
+ --
+ -- @synthesis supported
+ --
+ function reverse(vec : std_logic_vector) return std_logic_vector;
+ function reverse(vec : bit_vector) return bit_vector;
+ function reverse(vec : unsigned) return unsigned;
+
+ -- Resizes the vector to the specified length. The adjustment is make on
+ -- on the 'high end of the vector. The 'low index remains as in the argument.
+ -- If the result vector is larger, the extension uses the provided fill value
+ -- (default: '0').
+ -- Use the resize functions of the numeric_std package for value-preserving
+ -- resizes of the signed and unsigned data types.
+ --
+ -- @synthesis supported
+ --
+ function resize(vec : bit_vector; length : natural; fill : bit := '0')
+ return bit_vector;
+ function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0')
+ return std_logic_vector;
+
+ -- Shift the index range of a vector by the specified offset.
+ function move(vec : std_logic_vector; ofs : integer) return std_logic_vector;
+
+ -- Shift the index range of a vector making vec'low = 0.
+ function movez(vec : std_logic_vector) return std_logic_vector;
+
+ function ascend(vec : std_logic_vector) return std_logic_vector;
+ function descend(vec : std_logic_vector) return std_logic_vector;
+
+ -- Least-Significant Set Bit (lssb):
+ -- Computes a vector of the same length as the argument with
+ -- at most one bit set at the rightmost '1' found in arg.
+ --
+ -- @synthesis supported
+ --
+ function lssb(arg : std_logic_vector) return std_logic_vector;
+ function lssb(arg : bit_vector) return bit_vector;
+
+ -- Returns the index of the least-significant set bit.
+ --
+ -- @synthesis supported
+ --
+ function lssb_idx(arg : std_logic_vector) return integer;
+ function lssb_idx(arg : bit_vector) return integer;
+
+ -- Most-Significant Set Bit (mssb): computes a vector of the same length
+ -- with at most one bit set at the leftmost '1' found in arg.
+ function mssb(arg : std_logic_vector) return std_logic_vector;
+ function mssb(arg : bit_vector) return bit_vector;
+ function mssb_idx(arg : std_logic_vector) return integer;
+ function mssb_idx(arg : bit_vector) return integer;
+
+ -- Swap sub vectors in vector (endian reversal)
+ function swap(slv : STD_LOGIC_VECTOR; Size : POSITIVE) return STD_LOGIC_VECTOR;
+
+ -- generate bit masks
+ function genmask_high(Bits : NATURAL; MaskLength : POSITIVE) return STD_LOGIC_VECTOR;
+ function genmask_low(Bits : NATURAL; MaskLength : POSITIVE) return STD_LOGIC_VECTOR;
+
+ --+ Encodings ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ -- One-Hot-Code to Binary-Code.
+ function onehot2bin(onehot : std_logic_vector) return unsigned;
+
+ -- Converts Gray-Code into Binary-Code.
+ --
+ -- @synthesis supported
+ --
+ function gray2bin (gray_val : std_logic_vector) return std_logic_vector;
+
+ -- Binary-Code to One-Hot-Code
+ function bin2onehot(value : std_logic_vector) return std_logic_vector;
+
+ -- Binary-Code to Gray-Code
+ function bin2gray(value : std_logic_vector) return std_logic_vector;
+
+end package;
+
+
+package body utils is
+
+ -- Environment
+ -- ==========================================================================
+ function is_simulation return boolean is
+ variable ret : boolean;
+ begin
+ ret := false;
+ --synthesis translate_off
+ if Is_X('X') then ret := true; end if;
+ --synthesis translate_on
+ return ret;
+ end function;
+
+ -- deferred constant assignment
+ constant SIMULATION : BOOLEAN := is_simulation;
+
+ -- Divisions: div_*
+ function div_ceil(a : NATURAL; b : POSITIVE) return NATURAL is -- calculates: ceil(a / b)
+ begin
+ return (a + (b - 1)) / b;
+ end function;
+
+ -- Power functions: *_pow2
+ -- ==========================================================================
+ -- is input a power of 2?
+ function is_pow2(int : NATURAL) return BOOLEAN is
+ begin
+ return ceil_pow2(int) = int;
+ end function;
+
+ -- round to next power of 2
+ function ceil_pow2(int : NATURAL) return POSITIVE is
+ begin
+ return 2 ** log2ceil(int);
+ end function;
+
+ -- round to previous power of 2
+ function floor_pow2(int : NATURAL) return NATURAL is
+ variable temp : UNSIGNED(30 downto 0);
+ begin
+ temp := to_unsigned(int, 31);
+ for i in temp'range loop
+ if (temp(i) = '1') then
+ return 2 ** i;
+ end if;
+ end loop;
+ return 0;
+ end function;
+
+ -- Logarithms: log*ceil*
+ -- ==========================================================================
+ function log2ceil(arg : positive) return natural is
+ variable tmp : positive;
+ variable log : natural;
+ begin
+ if arg = 1 then return 0; end if;
+ tmp := 1;
+ log := 0;
+ while arg > tmp loop
+ tmp := tmp * 2;
+ log := log + 1;
+ end loop;
+ return log;
+ end function;
+
+ function log2ceilnz(arg : positive) return positive is
+ begin
+ return imax(1, log2ceil(arg));
+ end function;
+
+ function log10ceil(arg : positive) return natural is
+ variable tmp : positive;
+ variable log : natural;
+ begin
+ if arg = 1 then return 0; end if;
+ tmp := 1;
+ log := 0;
+ while arg > tmp loop
+ tmp := tmp * 10;
+ log := log + 1;
+ end loop;
+ return log;
+ end function;
+
+ function log10ceilnz(arg : positive) return positive is
+ begin
+ return imax(1, log10ceil(arg));
+ end function;
+
+ -- if-then-else (ite)
+ -- ==========================================================================
+ function ite(cond : BOOLEAN; value1 : BOOLEAN; value2 : BOOLEAN) return BOOLEAN is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : REAL; value2 : REAL) return REAL is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : STD_LOGIC; value2 : STD_LOGIC) return STD_LOGIC is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : STD_LOGIC_VECTOR; value2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : BIT_VECTOR; value2 : BIT_VECTOR) return BIT_VECTOR is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : UNSIGNED; value2 : UNSIGNED) return UNSIGNED is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : CHARACTER; value2 : CHARACTER) return CHARACTER is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is
+ begin
+ if cond then
+ return value1;
+ else
+ return value2;
+ end if;
+ end function;
+
+ -- *min / *max / *sum
+ -- ==========================================================================
+ function imin(arg1 : integer; arg2 : integer) return integer is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ function rmin(arg1 : real; arg2 : real) return real is
+ begin
+ if arg1 < arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ function imin(vec : T_INTVEC) return INTEGER is
+ variable Result : INTEGER;
+ begin
+ Result := INTEGER'high;
+ for i in vec'range loop
+ if (vec(I) < Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function imin(vec : T_NATVEC) return NATURAL is
+ variable Result : NATURAL;
+ begin
+ Result := NATURAL'high;
+ for i in vec'range loop
+ if (vec(I) < Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function imin(vec : T_POSVEC) return POSITIVE is
+ variable Result : POSITIVE;
+ begin
+ Result := POSITIVE'high;
+ for i in vec'range loop
+ if (vec(I) < Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function rmin(vec : T_REALVEC) return REAL is
+ variable Result : REAL;
+ begin
+ Result := REAL'high;
+ for i in vec'range loop
+ if vec(i) < Result then
+ Result := vec(i);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function imax(arg1 : integer; arg2 : integer) return integer is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ function rmax(arg1 : real; arg2 : real) return real is
+ begin
+ if arg1 > arg2 then return arg1; end if;
+ return arg2;
+ end function;
+
+ function imax(vec : T_INTVEC) return INTEGER is
+ variable Result : INTEGER;
+ begin
+ Result := INTEGER'low;
+ for i in vec'range loop
+ if (vec(I) > Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function imax(vec : T_NATVEC) return NATURAL is
+ variable Result : NATURAL;
+ begin
+ Result := NATURAL'low;
+ for i in vec'range loop
+ if (vec(I) > Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function imax(vec : T_POSVEC) return POSITIVE is
+ variable Result : POSITIVE;
+ begin
+ Result := POSITIVE'low;
+ for i in vec'range loop
+ if (vec(I) > Result) then
+ Result := vec(I);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function rmax(vec : T_REALVEC) return REAL is
+ variable Result : REAL;
+ begin
+ Result := REAL'low;
+ for i in vec'range loop
+ if vec(i) > Result then
+ Result := vec(i);
+ end if;
+ end loop;
+ return Result;
+ end function;
+
+ function isum(vec : T_INTVEC) return INTEGER is
+ variable Result : INTEGER;
+ begin
+ Result := 0;
+ for i in vec'range loop
+ Result := Result + vec(i);
+ end loop;
+ return Result;
+ end function;
+
+ function isum(vec : T_NATVEC) return NATURAL is
+ variable Result : NATURAL;
+ begin
+ Result := 0;
+ for i in vec'range loop
+ Result := Result + vec(I);
+ end loop;
+ return Result;
+ end function;
+
+ function isum(vec : T_POSVEC) return POSITIVE is
+ variable Result : POSITIVE;
+ begin
+ Result := 0;
+ for i in vec'range loop
+ Result := Result + vec(I);
+ end loop;
+ return Result;
+ end function;
+
+ function rsum(vec : T_REALVEC) return REAL is
+ variable Result : REAL;
+ begin
+ Result := 0.0;
+ for i in vec'range loop
+ Result := Result + vec(i);
+ end loop;
+ return Result;
+ end function;
+
+ -- Vector aggregate functions: slv_*
+ -- ==========================================================================
+ function slv_or(vec : STD_LOGIC_VECTOR) return STD_LOGIC is
+ variable Result : STD_LOGIC;
+ begin
+ Result := '0';
+ for i in vec'range loop
+ Result := Result or vec(i);
+ end loop;
+ return Result;
+ end function;
+
+ function slv_nor(vec : STD_LOGIC_VECTOR) return STD_LOGIC is
+ begin
+ return not slv_or(vec);
+ end function;
+
+ function slv_and(vec : STD_LOGIC_VECTOR) return STD_LOGIC is
+ variable Result : STD_LOGIC;
+ begin
+ Result := '1';
+ for i in vec'range loop
+ Result := Result and vec(i);
+ end loop;
+ return Result;
+ end function;
+
+ function slv_nand(vec : STD_LOGIC_VECTOR) return STD_LOGIC is
+ begin
+ return not slv_and(vec);
+ end function;
+
+ function slv_xor(vec : std_logic_vector) return std_logic is
+ variable res : std_logic;
+ begin
+ res := '0';
+ for i in vec'range loop
+ res := res xor vec(i);
+ end loop;
+ return res;
+ end slv_xor;
+
+ -- Convert to integer: to_int
+ function to_int(bool : BOOLEAN; zero : INTEGER := 0; one : INTEGER := 1) return INTEGER is
+ begin
+ return ite(bool, one, zero);
+ end function;
+
+ function to_int(sl : STD_LOGIC; zero : INTEGER := 0; one : INTEGER := 1) return INTEGER is
+ begin
+ if (sl = '1') then
+ return one;
+ end if;
+ return zero;
+ end function;
+
+ -- Convert to bit: to_sl
+ -- ==========================================================================
+ function to_sl(Value : BOOLEAN) return STD_LOGIC is
+ begin
+ return ite(Value, '1', '0');
+ end function;
+
+ function to_sl(Value : CHARACTER) return STD_LOGIC is
+ begin
+ case Value is
+ when 'U' => return 'U';
+ when '0' => return '0';
+ when '1' => return '1';
+ when 'Z' => return 'Z';
+ when 'W' => return 'W';
+ when 'L' => return 'L';
+ when 'H' => return 'H';
+ when '-' => return '-';
+ when OTHERS => return 'X';
+ end case;
+ end function;
+
+ -- Convert to vector: to_slv
+ -- ==========================================================================
+ -- short for std_logic_vector(to_unsigned(Value, Size))
+ -- the return value is guaranteed to have the range (Size-1 downto 0)
+ function to_slv(Value : NATURAL; Size : POSITIVE) return STD_LOGIC_VECTOR is
+ constant res : std_logic_vector(Size-1 downto 0) := std_logic_vector(to_unsigned(Value, Size));
+ begin
+ return res;
+ end function;
+
+ function to_index(slv : UNSIGNED; max : NATURAL := 0) return INTEGER is
+ variable res : integer;
+ begin
+ if (slv'length = 0) then return 0; end if;
+
+ res := to_integer(slv);
+ if SIMULATION and max > 0 then
+ res := imin(res, max);
+ end if;
+ return res;
+ end function;
+
+ function to_index(slv : STD_LOGIC_VECTOR; max : NATURAL := 0) return INTEGER is
+ begin
+ return to_index(unsigned(slv), max);
+ end function;
+
+ -- is_*
+ -- ==========================================================================
+ function is_sl(c : CHARACTER) return BOOLEAN is
+ begin
+ case c is
+ when 'U'|'X'|'0'|'1'|'Z'|'W'|'L'|'H'|'-' => return true;
+ when OTHERS => return false;
+ end case;
+ end function;
+
+
+ -- Reverse vector elements
+ function reverse(vec : std_logic_vector) return std_logic_vector is
+ variable res : std_logic_vector(vec'range);
+ begin
+ for i in vec'low to vec'high loop
+ res(vec'low + (vec'high-i)) := vec(i);
+ end loop;
+ return res;
+ end function;
+
+ function reverse(vec : bit_vector) return bit_vector is
+ variable res : bit_vector(vec'range);
+ begin
+ res := to_bitvector(reverse(to_stdlogicvector(vec)));
+ return res;
+ end reverse;
+
+ function reverse(vec : unsigned) return unsigned is
+ begin
+ return unsigned(reverse(std_logic_vector(vec)));
+ end function;
+
+
+ -- Swap sub vectors in vector
+ -- ==========================================================================
+ function swap(slv : STD_LOGIC_VECTOR; Size : POSITIVE) return STD_LOGIC_VECTOR IS
+ CONSTANT SegmentCount : NATURAL := slv'length / Size;
+ variable FromH : NATURAL;
+ variable FromL : NATURAL;
+ variable ToH : NATURAL;
+ variable ToL : NATURAL;
+ variable Result : STD_LOGIC_VECTOR(slv'length - 1 DOWNTO 0);
+ begin
+ for i in 0 TO SegmentCount - 1 loop
+ FromH := ((I + 1) * Size) - 1;
+ FromL := I * Size;
+ ToH := ((SegmentCount - I) * Size) - 1;
+ ToL := (SegmentCount - I - 1) * Size;
+ Result(ToH DOWNTO ToL) := slv(FromH DOWNTO FromL);
+ end loop;
+ return Result;
+ end function;
+
+ -- generate bit masks
+ -- ==========================================================================
+ function genmask_high(Bits : NATURAL; MaskLength : POSITIVE) return STD_LOGIC_VECTOR IS
+ begin
+ if (Bits = 0) then
+ return (MaskLength - 1 DOWNTO 0 => '0');
+ else
+ return (MaskLength - 1 DOWNTO MaskLength - Bits + 1 => '1') & (MaskLength - Bits DOWNTO 0 => '0');
+ end if;
+ end function;
+
+ function genmask_low(Bits : NATURAL; MaskLength : POSITIVE) return STD_LOGIC_VECTOR is
+ begin
+ if (Bits = 0) then
+ return (MaskLength - 1 DOWNTO 0 => '0');
+ else
+ return (MaskLength - 1 DOWNTO Bits => '0') & (Bits - 1 DOWNTO 0 => '1');
+ end if;
+ end function;
+
+ -- binary encoding conversion functions
+ -- ==========================================================================
+ -- One-Hot-Code to Binary-Code
+ function onehot2bin(onehot : std_logic_vector) return unsigned is
+ variable res : unsigned(log2ceilnz(onehot'high+1)-1 downto 0);
+ variable chk : natural;
+ begin
+ res := (others => '0');
+ chk := 0;
+ for i in onehot'range loop
+ if onehot(i) = '1' then
+ res := res or to_unsigned(i, res'length);
+ chk := chk + 1;
+ end if;
+ end loop;
+ if SIMULATION and chk /= 1 then
+ report "Broken 1-Hot-Code with "&integer'image(chk)&" bits set."
+ severity error;
+ end if;
+ return res;
+ end onehot2bin;
+
+ -- Gray-Code to Binary-Code
+ function gray2bin(gray_val : std_logic_vector) return std_logic_vector is
+ variable res : std_logic_vector(gray_val'range);
+ begin -- gray2bin
+ res(res'left) := gray_val(gray_val'left);
+ for i in res'left-1 downto res'right loop
+ res(i) := res(i+1) xor gray_val(i);
+ end loop;
+ return res;
+ end gray2bin;
+
+ -- Binary-Code to One-Hot-Code
+ function bin2onehot(value : std_logic_vector) return std_logic_vector is
+ variable result : std_logic_vector(2**value'length - 1 downto 0);
+ begin
+ result := (others => '0');
+ result(to_index(value)) := '1';
+ return result;
+ end function;
+
+ -- Binary-Code to Gray-Code
+ function bin2gray(value : std_logic_vector) return std_logic_vector is
+ variable result : std_logic_vector(value'range);
+ begin
+ result(result'left) := value(value'left);
+ for i in (result'left - 1) downto result'right loop
+ result(i) := value(i) xor value(i + 1);
+ end loop;
+ return result;
+ end function;
+
+ -- bit searching / bit indices
+ -- ==========================================================================
+ -- Least-Significant Set Bit (lssb): computes a vector of the same length with at most one bit set at the rightmost '1' found in arg.
+ function lssb(arg : std_logic_vector) return std_logic_vector is
+ variable res : std_logic_vector(arg'range);
+ begin
+ res := arg and std_logic_vector(unsigned(not arg)+1);
+ return res;
+ end function;
+
+ function lssb(arg : bit_vector) return bit_vector is
+ variable res : bit_vector(arg'range);
+ begin
+ res := to_bitvector(lssb(to_stdlogicvector(arg)));
+ return res;
+ end lssb;
+
+ -- Most-Significant Set Bit (mssb): computes a vector of the same length with at most one bit set at the leftmost '1' found in arg.
+ function mssb(arg : std_logic_vector) return std_logic_vector is
+ begin
+ return reverse(lssb(reverse(arg)));
+ end function;
+
+ function mssb(arg : bit_vector) return bit_vector is
+ begin
+ return reverse(lssb(reverse(arg)));
+ end mssb;
+
+ -- Index of lssb
+ function lssb_idx(arg : std_logic_vector) return integer is
+ begin
+ return to_integer(onehot2bin(lssb(arg)));
+ end function;
+
+ function lssb_idx(arg : bit_vector) return integer is
+ variable slv : std_logic_vector(arg'range);
+ begin
+ slv := to_stdlogicvector(arg);
+ return lssb_idx(slv);
+ end lssb_idx;
+
+ -- Index of mssb
+ function mssb_idx(arg : std_logic_vector) return integer is
+ begin
+ return to_integer(onehot2bin(mssb(arg)));
+ end function;
+
+ function mssb_idx(arg : bit_vector) return integer is
+ variable slv : std_logic_vector(arg'range);
+ begin
+ slv := to_stdlogicvector(arg);
+ return mssb_idx(slv);
+ end mssb_idx;
+
+ function resize(vec : bit_vector; length : natural; fill : bit := '0') return bit_vector is
+ constant high2b : natural := vec'low+length-1;
+ constant highcp : natural := imin(vec'high, high2b);
+ variable res_up : bit_vector(vec'low to high2b);
+ variable res_dn : bit_vector(high2b downto vec'low);
+ begin
+ if vec'ascending then
+ res_up := (others => fill);
+ res_up(vec'low to highcp) := vec(vec'low to highcp);
+ return res_up;
+ else
+ res_dn := (others => fill);
+ res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
+ return res_dn;
+ end if;
+ end resize;
+
+ function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0') return std_logic_vector is
+ constant high2b : natural := vec'low+length-1;
+ constant highcp : natural := imin(vec'high, high2b);
+ variable res_up : std_logic_vector(vec'low to high2b);
+ variable res_dn : std_logic_vector(high2b downto vec'low);
+ begin
+ if vec'ascending then
+ res_up := (others => fill);
+ res_up(vec'low to highcp) := vec(vec'low to highcp);
+ return res_up;
+ else
+ res_dn := (others => fill);
+ res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
+ return res_dn;
+ end if;
+ end resize;
+
+ -- Move vector boundaries
+ -- ==========================================================================
+ function move(vec : std_logic_vector; ofs : integer) return std_logic_vector is
+ variable res_up : std_logic_vector(vec'low +ofs to vec'high+ofs);
+ variable res_dn : std_logic_vector(vec'high+ofs downto vec'low +ofs);
+ begin
+ if vec'ascending then
+ res_up := vec;
+ return res_up;
+ else
+ res_dn := vec;
+ return res_dn;
+ end if;
+ end move;
+
+ function movez(vec : std_logic_vector) return std_logic_vector is
+ begin
+ return move(vec, -vec'low);
+ end movez;
+
+ function ascend(vec : std_logic_vector) return std_logic_vector is
+ variable res : std_logic_vector(vec'low to vec'high);
+ begin
+ res := vec;
+ return res;
+ end ascend;
+
+ function descend(vec : std_logic_vector) return std_logic_vector is
+ variable res : std_logic_vector(vec'high downto vec'low);
+ begin
+ res := vec;
+ return res;
+ end descend;
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/common/vectors.vhdl b/testsuite/gna/bug019/PoC/src/common/vectors.vhdl
new file mode 100644
index 000000000..f96d0e081
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/common/vectors.vhdl
@@ -0,0 +1,764 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Package: Common functions and types
+--
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Description:
+-- ------------------------------------
+-- For detailed documentation see below.
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2014 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.strings.all;
+
+
+package vectors is
+ -- ==========================================================================
+ -- Type declarations
+ -- ==========================================================================
+ -- STD_LOGIC_VECTORs
+ subtype T_SLV_2 is STD_LOGIC_VECTOR(1 downto 0);
+ subtype T_SLV_3 is STD_LOGIC_VECTOR(2 downto 0);
+ subtype T_SLV_4 is STD_LOGIC_VECTOR(3 downto 0);
+ subtype T_SLV_8 is STD_LOGIC_VECTOR(7 downto 0);
+ subtype T_SLV_12 is STD_LOGIC_VECTOR(11 downto 0);
+ subtype T_SLV_16 is STD_LOGIC_VECTOR(15 downto 0);
+ subtype T_SLV_24 is STD_LOGIC_VECTOR(23 downto 0);
+ subtype T_SLV_32 is STD_LOGIC_VECTOR(31 downto 0);
+ subtype T_SLV_48 is STD_LOGIC_VECTOR(47 downto 0);
+ subtype T_SLV_64 is STD_LOGIC_VECTOR(63 downto 0);
+ subtype T_SLV_96 is STD_LOGIC_VECTOR(95 downto 0);
+ subtype T_SLV_128 is STD_LOGIC_VECTOR(127 downto 0);
+ subtype T_SLV_256 is STD_LOGIC_VECTOR(255 downto 0);
+ subtype T_SLV_512 is STD_LOGIC_VECTOR(511 downto 0);
+
+ -- STD_LOGIC_VECTOR_VECTORs
+ -- type T_SLVV is array(NATURAL range <>) of STD_LOGIC_VECTOR; -- VHDL 2008 syntax - not yet supported by Xilinx
+ type T_SLVV_2 is array(NATURAL range <>) of T_SLV_2;
+ type T_SLVV_3 is array(NATURAL range <>) of T_SLV_3;
+ type T_SLVV_4 is array(NATURAL range <>) of T_SLV_4;
+ type T_SLVV_8 is array(NATURAL range <>) of T_SLV_8;
+ type T_SLVV_12 is array(NATURAL range <>) of T_SLV_12;
+ type T_SLVV_16 is array(NATURAL range <>) of T_SLV_16;
+ type T_SLVV_24 is array(NATURAL range <>) of T_SLV_24;
+ type T_SLVV_32 is array(NATURAL range <>) of T_SLV_32;
+ type T_SLVV_48 is array(NATURAL range <>) of T_SLV_48;
+ type T_SLVV_64 is array(NATURAL range <>) of T_SLV_64;
+ type T_SLVV_128 is array(NATURAL range <>) of T_SLV_128;
+ type T_SLVV_256 is array(NATURAL range <>) of T_SLV_256;
+ type T_SLVV_512 is array(NATURAL range <>) of T_SLV_512;
+
+ -- STD_LOGIC_MATRIXs
+ type T_SLM is array(NATURAL range <>, NATURAL range <>) of STD_LOGIC;
+ -- ATTENTION:
+ -- 1. you MUST initialize your matrix signal with 'Z' to get correct simulation results (iSIM, vSIM, ghdl/gtkwave)
+ -- Example: signal myMatrix : T_SLM(3 downto 0, 7 downto 0) := (others => (others => 'Z'));
+ -- 2. Xilinx iSIM work-around: DON'T use myMatrix'range(n) for n >= 2
+ -- because: myMatrix'range(2) returns always myMatrix'range(1); tested with ISE/iSIM 14.2
+ -- USAGE NOTES:
+ -- dimmension 1 => rows - e.g. Words
+ -- dimmension 2 => columns - e.g. Bits/Bytes in a word
+
+
+ -- ==========================================================================
+ -- Function declarations
+ -- ==========================================================================
+ -- slicing boundary calulations
+ function low (lenvec : T_POSVEC; index : NATURAL) return NATURAL;
+ function high(lenvec : T_POSVEC; index : NATURAL) return NATURAL;
+
+ -- Assign procedures: assign_*
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL); -- assign vector to complete row
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL; Position : NATURAL); -- assign short vector to row starting at position
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL; High : NATURAL; Low : NATURAL); -- assign short vector to row in range high:low
+ procedure assign_col(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant ColIndex : NATURAL); -- assign vector to complete column
+ -- ATTENTION: see T_SLM definition for further details and work-arounds
+
+ -- Matrix to matrix conversion: slm_slice*
+ function slm_slice(slm : T_SLM; RowIndex : NATURAL; ColIndex : NATURAL; Height : NATURAL; Width : NATURAL) return T_SLM; -- get submatrix in boundingbox RowIndex,ColIndex,Height,Width
+ function slm_slice_cols(slm : T_SLM; High : NATURAL; Low : NATURAL) return T_SLM; -- get submatrix / all columns in ColIndex range high:low
+
+ -- Matrix to vector conversion: get_*
+ function get_col(slm : T_SLM; ColIndex : NATURAL) return STD_LOGIC_VECTOR; -- get a matrix column
+ function get_row(slm : T_SLM; RowIndex : NATURAL) return STD_LOGIC_VECTOR; -- get a matrix row
+ function get_row(slm : T_SLM; RowIndex : NATURAL; Length : POSITIVE) return STD_LOGIC_VECTOR; -- get a matrix row of defined length [length - 1 downto 0]
+ function get_row(slm : T_SLM; RowIndex : NATURAL; High : NATURAL; Low : NATURAL) return STD_LOGIC_VECTOR; -- get a sub vector of a matrix row at high:low
+
+ -- Convert to vector: to_slv
+ function to_slv(slvv : T_SLVV_8) return STD_LOGIC_VECTOR; -- convert vector-vector to flatten vector
+
+ -- Convert flat vector to avector-vector: to_slvv_*
+ function to_slvv_4(slv : STD_LOGIC_VECTOR) return T_SLVV_4; --
+ function to_slvv_8(slv : STD_LOGIC_VECTOR) return T_SLVV_8; --
+ function to_slvv_12(slv : STD_LOGIC_VECTOR) return T_SLVV_12; --
+ function to_slvv_16(slv : STD_LOGIC_VECTOR) return T_SLVV_16; --
+ function to_slvv_32(slv : STD_LOGIC_VECTOR) return T_SLVV_32; --
+ function to_slvv_64(slv : STD_LOGIC_VECTOR) return T_SLVV_64; --
+ function to_slvv_128(slv : STD_LOGIC_VECTOR) return T_SLVV_128; --
+ function to_slvv_256(slv : STD_LOGIC_VECTOR) return T_SLVV_256; --
+ function to_slvv_512(slv : STD_LOGIC_VECTOR) return T_SLVV_512; --
+
+ -- Convert matrix to avector-vector: to_slvv_*
+ function to_slvv_4(slm : T_SLM) return T_SLVV_4; --
+ function to_slvv_8(slm : T_SLM) return T_SLVV_8; --
+ function to_slvv_12(slm : T_SLM) return T_SLVV_12; --
+ function to_slvv_16(slm : T_SLM) return T_SLVV_16; --
+ function to_slvv_32(slm : T_SLM) return T_SLVV_32; --
+ function to_slvv_64(slm : T_SLM) return T_SLVV_64; --
+ function to_slvv_128(slm : T_SLM) return T_SLVV_128; --
+ function to_slvv_256(slm : T_SLM) return T_SLVV_256; --
+ function to_slvv_512(slm : T_SLM) return T_SLVV_512; --
+
+ -- Convert vector-vector to matrix: to_slm
+ function to_slm(slvv : T_SLVV_4) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_8) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_12) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_16) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_32) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_48) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_64) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_128) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_256) return T_SLM; -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_512) return T_SLM; -- create matrix from vector-vector
+
+ -- Change vector direction
+ function dir(slvv : T_SLVV_8) return T_SLVV_8;
+
+ -- Reverse vector elements
+ function rev(slvv : T_SLVV_4) return T_SLVV_4;
+ function rev(slvv : T_SLVV_8) return T_SLVV_8;
+ function rev(slvv : T_SLVV_12) return T_SLVV_12;
+ function rev(slvv : T_SLVV_16) return T_SLVV_16;
+ function rev(slvv : T_SLVV_32) return T_SLVV_32;
+ function rev(slvv : T_SLVV_64) return T_SLVV_64;
+ function rev(slvv : T_SLVV_128) return T_SLVV_128;
+ function rev(slvv : T_SLVV_256) return T_SLVV_256;
+ function rev(slvv : T_SLVV_512) return T_SLVV_512;
+
+ -- TODO:
+ function resize(slm : T_SLM; size : POSITIVE) return T_SLM;
+
+ -- to_string
+ function to_string(slvv : T_SLVV_8; sep : CHARACTER := ':') return STRING;
+end package vectors;
+
+
+package body vectors is
+ -- slicing boundary calulations
+ -- ==========================================================================
+ function low(lenvec : T_POSVEC; index : NATURAL) return NATURAL is
+ variable pos : NATURAL := 0;
+ begin
+ for i in lenvec'low to index - 1 loop
+ pos := pos + lenvec(i);
+ end loop;
+ return pos;
+ end function;
+
+ function high(lenvec : T_POSVEC; index : NATURAL) return NATURAL is
+ variable pos : NATURAL := 0;
+ begin
+ for i in lenvec'low to index loop
+ pos := pos + lenvec(i);
+ end loop;
+ return pos - 1;
+ end function;
+
+ -- Assign procedures: assign_*
+ -- ==========================================================================
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL) is
+ variable temp : STD_LOGIC_VECTOR(slm'high(2) downto slm'low(2)); -- Xilinx iSIM work-around, because 'range(2) evaluates to 'range(1); tested with ISE/iSIM 14.2
+ begin
+ temp := slv;
+ for i in temp'range loop
+ slm(RowIndex, i) <= temp(i);
+ end loop;
+ end procedure;
+
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL; Position : NATURAL) is
+ variable temp : STD_LOGIC_VECTOR(Position + slv'length - 1 downto Position);
+ begin
+ temp := slv;
+ for i in temp'range loop
+ slm(RowIndex, i) <= temp(i);
+ end loop;
+ end procedure;
+
+ procedure assign_row(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant RowIndex : NATURAL; High : NATURAL; Low : NATURAL) is
+ variable temp : STD_LOGIC_VECTOR(High downto Low);
+ begin
+ temp := slv;
+ for i in temp'range loop
+ slm(RowIndex, i) <= temp(i);
+ end loop;
+ end procedure;
+
+ procedure assign_col(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant ColIndex : NATURAL) is
+ variable temp : STD_LOGIC_VECTOR(slm'range(1));
+ begin
+ temp := slv;
+ for i in temp'range loop
+ slm(i, ColIndex) <= temp(i);
+ end loop;
+ end procedure;
+
+ -- Matrix to matrix conversion: slm_slice*
+ -- ==========================================================================
+ function slm_slice(slm : T_SLM; RowIndex : NATURAL; ColIndex : NATURAL; Height : NATURAL; Width : NATURAL) return T_SLM is
+ variable Result : T_SLM(Height - 1 downto 0, Width - 1 downto 0) := (others => (others => '0'));
+ begin
+ for i in 0 to Height - 1 loop
+ for j in 0 to Width - 1 loop
+ Result(i, j) := slm(RowIndex + i, ColIndex + j);
+ end loop;
+ end loop;
+ return Result;
+ end function;
+
+ function slm_slice_cols(slm : T_SLM; High : NATURAL; Low : NATURAL) return T_SLM is
+ variable Result : T_SLM(slm'range(1), High - Low downto 0) := (others => (others => '0'));
+ begin
+ for i in slm'range(1) loop
+ for j in 0 to High - Low loop
+ Result(i, j) := slm(i, low + j);
+ end loop;
+ end loop;
+ return Result;
+ end function;
+
+ -- Matrix to vector conversion: get_*
+ -- ==========================================================================
+ -- get a matrix column
+ function get_col(slm : T_SLM; ColIndex : NATURAL) return STD_LOGIC_VECTOR is
+ variable slv : STD_LOGIC_VECTOR(slm'range(1));
+ begin
+ for i in slm'range(1) loop
+ slv(i) := slm(i, ColIndex);
+ end loop;
+ return slv;
+ end function;
+
+ -- get a matrix row
+ function get_row(slm : T_SLM; RowIndex : NATURAL) return STD_LOGIC_VECTOR is
+ variable slv : STD_LOGIC_VECTOR(slm'high(2) downto slm'low(2)); -- Xilinx iSIM work-around, because 'range(2) = 'range(1); tested with ISE/iSIM 14.2
+ begin
+ for i in slv'range loop
+ slv(i) := slm(RowIndex, i);
+ end loop;
+ return slv;
+ end function;
+
+ -- get a matrix row of defined length [length - 1 downto 0]
+ function get_row(slm : T_SLM; RowIndex : NATURAL; Length : POSITIVE) return STD_LOGIC_VECTOR is
+ begin
+ return get_row(slm, RowIndex, (Length - 1), 0);
+ end function;
+
+ -- get a sub vector of a matrix row at high:low
+ function get_row(slm : T_SLM; RowIndex : NATURAL; High : NATURAL; Low : NATURAL) return STD_LOGIC_VECTOR is
+ variable slv : STD_LOGIC_VECTOR(High downto Low); -- Xilinx iSIM work-around, because 'range(2) = 'range(1); tested with ISE/iSIM 14.2
+ begin
+ for i in slv'range loop
+ slv(i) := slm(RowIndex, i);
+ end loop;
+ return slv;
+ end function;
+
+ -- Convert to vector: to_slv
+ -- ==========================================================================
+ -- convert vector-vector to flatten vector
+ function to_slv(slvv : T_SLVV_8) return STD_LOGIC_VECTOR is
+ variable slv : STD_LOGIC_VECTOR((slvv'length * 8) - 1 downto 0);
+ begin
+ for i in slvv'range loop
+ slv((i * 8) + 7 downto (i * 8)) := slvv(i);
+ end loop;
+ return slv;
+ end function;
+
+ -- Convert flat vector to a vector-vector: to_slvv_*
+ -- ==========================================================================
+ -- create vector-vector from vector (4 bit)
+ function to_slvv_4(slv : STD_LOGIC_VECTOR) return T_SLVV_4 is
+ variable Result : T_SLVV_4((slv'length / 4) - 1 downto 0);
+ begin
+ if ((slv'length mod 4) /= 0) then report "to_slvv_4: width mismatch - slv'length is no multiple of 4 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 4) + 3 downto (i * 4));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (8 bit)
+ function to_slvv_8(slv : STD_LOGIC_VECTOR) return T_SLVV_8 is
+ variable Result : T_SLVV_8((slv'length / 8) - 1 downto 0);
+ begin
+ if ((slv'length mod 8) /= 0) then report "to_slvv_8: width mismatch - slv'length is no multiple of 8 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 8) + 7 downto (i * 8));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (12 bit)
+ function to_slvv_12(slv : STD_LOGIC_VECTOR) return T_SLVV_12 is
+ variable Result : T_SLVV_12((slv'length / 12) - 1 downto 0);
+ begin
+ if ((slv'length mod 12) /= 0) then report "to_slvv_12: width mismatch - slv'length is no multiple of 12 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 12) + 11 downto (i * 12));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (16 bit)
+ function to_slvv_16(slv : STD_LOGIC_VECTOR) return T_SLVV_16 is
+ variable Result : T_SLVV_16((slv'length / 16) - 1 downto 0);
+ begin
+ if ((slv'length mod 16) /= 0) then report "to_slvv_16: width mismatch - slv'length is no multiple of 16 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 16) + 15 downto (i * 16));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (32 bit)
+ function to_slvv_32(slv : STD_LOGIC_VECTOR) return T_SLVV_32 is
+ variable Result : T_SLVV_32((slv'length / 32) - 1 downto 0);
+ begin
+ if ((slv'length mod 32) /= 0) then report "to_slvv_32: width mismatch - slv'length is no multiple of 32 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 32) + 31 downto (i * 32));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (64 bit)
+ function to_slvv_64(slv : STD_LOGIC_VECTOR) return T_SLVV_64 is
+ variable Result : T_SLVV_64((slv'length / 64) - 1 downto 0);
+ begin
+ if ((slv'length mod 64) /= 0) then report "to_slvv_64: width mismatch - slv'length is no multiple of 64 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 64) + 63 downto (i * 64));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (128 bit)
+ function to_slvv_128(slv : STD_LOGIC_VECTOR) return T_SLVV_128 is
+ variable Result : T_SLVV_128((slv'length / 128) - 1 downto 0);
+ begin
+ if ((slv'length mod 128) /= 0) then report "to_slvv_128: width mismatch - slv'length is no multiple of 128 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 128) + 127 downto (i * 128));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (256 bit)
+ function to_slvv_256(slv : STD_LOGIC_VECTOR) return T_SLVV_256 is
+ variable Result : T_SLVV_256((slv'length / 256) - 1 downto 0);
+ begin
+ if ((slv'length mod 256) /= 0) then report "to_slvv_256: width mismatch - slv'length is no multiple of 256 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 256) + 255 downto (i * 256));
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from vector (512 bit)
+ function to_slvv_512(slv : STD_LOGIC_VECTOR) return T_SLVV_512 is
+ variable Result : T_SLVV_512((slv'length / 512) - 1 downto 0);
+ begin
+ if ((slv'length mod 512) /= 0) then report "to_slvv_512: width mismatch - slv'length is no multiple of 512 (slv'length=" & INTEGER'image(slv'length) & ")" severity FAILURE; end if;
+
+ for i in Result'range loop
+ Result(i) := slv((i * 512) + 511 downto (i * 512));
+ end loop;
+ return Result;
+ end function;
+
+ -- Convert matrix to avector-vector: to_slvv_*
+ -- ==========================================================================
+ -- create vector-vector from matrix (4 bit)
+ function to_slvv_4(slm : T_SLM) return T_SLVV_4 is
+ variable Result : T_SLVV_4(slm'range(1));
+ begin
+ if (slm'length(2) /= 4) then report "to_slvv_4: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (8 bit)
+ function to_slvv_8(slm : T_SLM) return T_SLVV_8 is
+ variable Result : T_SLVV_8(slm'range(1));
+ begin
+ if (slm'length(2) /= 8) then report "to_slvv_8: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (12 bit)
+ function to_slvv_12(slm : T_SLM) return T_SLVV_12 is
+ variable Result : T_SLVV_12(slm'range(1));
+ begin
+ if (slm'length(2) /= 12) then report "to_slvv_12: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (16 bit)
+ function to_slvv_16(slm : T_SLM) return T_SLVV_16 is
+ variable Result : T_SLVV_16(slm'range(1));
+ begin
+ if (slm'length(2) /= 16) then report "to_slvv_16: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (32 bit)
+ function to_slvv_32(slm : T_SLM) return T_SLVV_32 is
+ variable Result : T_SLVV_32(slm'range(1));
+ begin
+ if (slm'length(2) /= 32) then report "to_slvv_32: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (64 bit)
+ function to_slvv_64(slm : T_SLM) return T_SLVV_64 is
+ variable Result : T_SLVV_64(slm'range(1));
+ begin
+ if (slm'length(2) /= 64) then report "to_slvv_64: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (128 bit)
+ function to_slvv_128(slm : T_SLM) return T_SLVV_128 is
+ variable Result : T_SLVV_128(slm'range(1));
+ begin
+ if (slm'length(2) /= 128) then report "to_slvv_128: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (256 bit)
+ function to_slvv_256(slm : T_SLM) return T_SLVV_256 is
+ variable Result : T_SLVV_256(slm'range);
+ begin
+ if (slm'length(2) /= 256) then report "to_slvv_256: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- create vector-vector from matrix (512 bit)
+ function to_slvv_512(slm : T_SLM) return T_SLVV_512 is
+ variable Result : T_SLVV_512(slm'range(1));
+ begin
+ if (slm'length(2) /= 512) then report "to_slvv_512: type mismatch - slm'length(2)=" & INTEGER'image(slm'length(2)) severity FAILURE; end if;
+
+ for i in slm'range(1) loop
+ Result(i) := get_row(slm, i);
+ end loop;
+ return Result;
+ end function;
+
+ -- Convert vector-vector to matrix: to_slm
+ -- ==========================================================================
+ -- create matrix from vector-vector
+ function to_slm(slvv : T_SLVV_4) return T_SLM is
+ variable slm : T_SLM(slvv'range, 3 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_4'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_8) return T_SLM is
+-- variable test : STD_LOGIC_VECTOR(T_SLV_8'range);
+-- variable slm : T_SLM(slvv'range, test'range); -- BUG: iSIM 14.5 cascaded 'range accesses let iSIM break down
+-- variable slm : T_SLM(slvv'range, T_SLV_8'range); -- BUG: iSIM 14.5 allocates 9 bits in dimmension 2
+ variable slm : T_SLM(slvv'range, 7 downto 0);
+ begin
+-- report "slvv: slvv.length=" & INTEGER'image(slvv'length) & " slm.dim0.length=" & INTEGER'image(slm'length(1)) & " slm.dim1.length=" & INTEGER'image(slm'length(2)) severity NOTE;
+-- report "T_SLV_8: .length=" & INTEGER'image(T_SLV_8'length) & " .high=" & INTEGER'image(T_SLV_8'high) & " .low=" & INTEGER'image(T_SLV_8'low) severity NOTE;
+-- report "test: test.length=" & INTEGER'image(test'length) & " .high=" & INTEGER'image(test'high) & " .low=" & INTEGER'image(test'low) severity NOTE;
+ for i in slvv'range loop
+ for j in T_SLV_8'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_12) return T_SLM is
+ variable slm : T_SLM(slvv'range, 11 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_12'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_16) return T_SLM is
+ variable slm : T_SLM(slvv'range, 15 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_16'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_32) return T_SLM is
+ variable slm : T_SLM(slvv'range, 31 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_32'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_48) return T_SLM is
+ variable slm : T_SLM(slvv'range, 47 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_48'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_64) return T_SLM is
+ variable slm : T_SLM(slvv'range, 63 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_64'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_128) return T_SLM is
+ variable slm : T_SLM(slvv'range, 127 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_128'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_256) return T_SLM is
+ variable slm : T_SLM(slvv'range, 255 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_256'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ function to_slm(slvv : T_SLVV_512) return T_SLM is
+ variable slm : T_SLM(slvv'range, 511 downto 0);
+ begin
+ for i in slvv'range loop
+ for j in T_SLV_512'range loop
+ slm(i, j) := slvv(i)(j);
+ end loop;
+ end loop;
+ return slm;
+ end function;
+
+ -- Change vector direction
+ -- ==========================================================================
+ function dir(slvv : T_SLVV_8) return T_SLVV_8 is
+ variable Result : T_SLVV_8(slvv'reverse_range);
+ begin
+ Result := slvv;
+ return Result;
+ end function;
+
+ -- Reverse vector elements
+ function rev(slvv : T_SLVV_4) return T_SLVV_4 is
+ variable Result : T_SLVV_4(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_8) return T_SLVV_8 is
+ variable Result : T_SLVV_8(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_12) return T_SLVV_12 is
+ variable Result : T_SLVV_12(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_16) return T_SLVV_16 is
+ variable Result : T_SLVV_16(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_32) return T_SLVV_32 is
+ variable Result : T_SLVV_32(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_64) return T_SLVV_64 is
+ variable Result : T_SLVV_64(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_128) return T_SLVV_128 is
+ variable Result : T_SLVV_128(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_256) return T_SLVV_256 is
+ variable Result : T_SLVV_256(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ function rev(slvv : T_SLVV_512) return T_SLVV_512 is
+ variable Result : T_SLVV_512(slvv'range);
+ begin
+ for i in slvv'low to slvv'high loop
+ Result(slvv'high - i) := slvv(i);
+ end loop;
+ return Result;
+ end function;
+
+ -- Resize functions
+ -- ==========================================================================
+ -- Resizes the vector to the specified length. Input vectors larger than the specified size are truncated from the left side. Smaller input
+ -- vectors are extended on the left by the provided fill value (default: '0'). Use the resize functions of the numeric_std package for
+ -- value-preserving resizes of the signed and unsigned data types.
+ function resize(slm : T_SLM; size : POSITIVE) return T_SLM is
+ variable Result : T_SLM(size - 1 downto 0, slm'high(2) downto slm'low(2)) := (others => (others => '0'));
+ begin
+ for i in slm'range(1) loop
+ for j in slm'high(2) downto slm'low(2) loop
+ Result(i, j) := slm(i, j);
+ end loop;
+ end loop;
+ return Result;
+ end function;
+
+ function to_string(slvv : T_SLVV_8; sep : CHARACTER := ':') return STRING is
+ constant hex_len : POSITIVE := ite((sep = C_POC_NUL), (slvv'length * 2), (slvv'length * 3) - 1);
+ variable Result : STRING(1 to hex_len) := (others => sep);
+ variable pos : POSITIVE := 1;
+ begin
+ for i in slvv'range loop
+ Result(pos to pos + 1) := to_string(slvv(i), 'h');
+ pos := pos + ite((sep = C_POC_NUL), 2, 3);
+ end loop;
+ return Result;
+ end function;
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl
new file mode 100644
index 000000000..b5c3e9da7
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/io/uart/uart.pkg.vhdl
@@ -0,0 +1,155 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Component declarations for PoC.io.uart
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- License:
+-- ============================================================================
+-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.physical.all;
+
+
+package uart is
+ type T_IO_UART_FLOWCONTROL_KIND is (
+ UART_FLOWCONTROL_NONE,
+ UART_FLOWCONTROL_XON_XOFF,
+ UART_FLOWCONTROL_RTS_CTS,
+ UART_FLOWCONTROL_RTR_CTS
+ );
+
+ constant C_IO_UART_TYPICAL_BAUDRATES : T_BAUDVEC := (
+ 0 => 300 Bd, 1 => 600 Bd, 2 => 1200 Bd, 3 => 1800 Bd, 4 => 2400 Bd,
+ 5 => 4000 Bd, 6 => 4800 Bd, 7 => 7200 Bd, 8 => 9600 Bd, 9 => 14400 Bd,
+ 10 => 16000 Bd, 11 => 19200 Bd, 12 => 28800 Bd, 13 => 38400 BD, 14 => 51200 Bd,
+ 15 => 56000 Bd, 16 => 57600 Bd, 17 => 64000 Bd, 18 => 76800 Bd, 19 => 115200 Bd,
+ 20 => 128000 Bd, 21 => 153600 Bd, 22 => 230400 Bd, 23 => 250000 Bd, 24 => 256000 BD,
+ 25 => 460800 Bd, 26 => 500000 Bd, 27 => 576000 Bd, 28 => 921600 Bd
+ );
+
+ function io_UART_IsTypicalBaudRate(br : BAUD) return BOOLEAN;
+
+ -- Bit clock generator
+ component uart_bclk is
+ generic (
+ CLOCK_FREQ : FREQ := 100 MHz;
+ BAUDRATE : BAUD := 115200 Bd
+ );
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk_r : out std_logic;
+ bclk_x8_r : out std_logic
+ );
+ end component;
+
+ -- Transmitter
+ component uart_tx is
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk_r : in std_logic;
+ stb : in std_logic;
+ din : in std_logic_vector(7 downto 0);
+ rdy : out std_logic;
+ txd : out std_logic
+ );
+ end component;
+
+ -- Receiver
+ component uart_rx is
+ generic (
+ OUT_REGS : boolean
+ );
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk_x8_r : in std_logic;
+ rxd : in std_logic;
+ dos : out std_logic;
+ dout : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ -- Wrappers
+ -- ===========================================================================
+ -- UART with FIFOs and optional flow control
+ component uart_fifo is
+ generic (
+ CLOCK_FREQ : FREQ := 100 MHz;
+ BAUDRATE : BAUD := 115200 Bd;
+ FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE;
+ TX_MIN_DEPTH : POSITIVE := 16;
+ TX_ESTATE_BITS : NATURAL := 1;
+ RX_MIN_DEPTH : POSITIVE := 16;
+ RX_FSTATE_BITS : NATURAL := 1;
+ RX_OUT_REGS : BOOLEAN := FALSE;
+
+ SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q
+ SWFC_XON_TRIGGER : real := 0.0625;
+ SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S
+ SWFC_XOFF_TRIGGER : real := 0.75
+ );
+ port (
+ Clock : in std_logic;
+ Reset : in std_logic;
+
+ -- FIFO interface
+ TX_put : in STD_LOGIC;
+ TX_Data : in STD_LOGIC_VECTOR(7 downto 0);
+ TX_Full : out STD_LOGIC;
+ TX_EmptyState : out STD_LOGIC_VECTOR(TX_ESTATE_BITS - 1 downto 0);
+
+ RX_Valid : out STD_LOGIC;
+ RX_Data : out STD_LOGIC_VECTOR(7 downto 0);
+ RX_got : in STD_LOGIC;
+ RX_FullState : out STD_LOGIC_VECTOR(RX_FSTATE_BITS - 1 downto 0);
+ RX_Overflow : out std_logic;
+
+ -- External Pins
+ UART_RX : in std_logic;
+ UART_TX : out std_logic
+ );
+ end component;
+end package;
+
+
+package body uart is
+ function io_UART_IsTypicalBaudRate(br : BAUD) return BOOLEAN is
+ begin
+ for i in C_IO_UART_TYPICAL_BAUDRATES'range loop
+ next when (br /= C_IO_UART_TYPICAL_BAUDRATES(i));
+ return TRUE;
+ end loop;
+ return FALSE;
+ end function;
+end package body;
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl
new file mode 100644
index 000000000..da2678520
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_bclk.vhdl
@@ -0,0 +1,108 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Martin Zabel
+-- Patrick Lehmann
+--
+-- Module: UART bit clock / baud rate generator
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- old comments:
+-- UART BAUD rate generator
+-- bclk_r = bit clock is rising
+-- bclk_x8_r = bit clock times 8 is rising
+--
+--
+-- License:
+-- ============================================================================
+-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.strings.all;
+use PoC.physical.all;
+use PoC.components.all;
+use PoC.uart.all;
+
+
+entity uart_bclk is
+ generic (
+ CLOCK_FREQ : FREQ := 100 MHz;
+ BAUDRATE : BAUD := 115200 Bd
+ );
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk : out std_logic;
+ bclk_x8 : out std_logic
+ );
+end entity;
+
+
+architecture rtl of uart_bclk is
+ constant UART_OVERSAMPLING_RATE : POSITIVE := 8;
+ constant TIME_UNIT_INTERVAL : TIME := 1 sec / (to_real(BAUDRATE, 1 Bd) * real(UART_OVERSAMPLING_RATE));
+ constant BAUDRATE_COUNTER_MAX : POSITIVE := TimingToCycles(TIME_UNIT_INTERVAL, CLOCK_FREQ);
+ constant BAUDRATE_COUNTER_BITS : POSITIVE := log2ceilnz(BAUDRATE_COUNTER_MAX + 1);
+
+ -- registers
+ signal x8_cnt : unsigned(BAUDRATE_COUNTER_BITS - 1 downto 0) := (others => '0');
+ signal x1_cnt : unsigned(2 downto 0) := (others => '0');
+
+ -- control signals
+ signal x8_cnt_done : std_logic;
+ signal x1_cnt_done : std_logic;
+
+ signal bclk_r : STD_LOGIC := '0';
+ signal bclk_x8_r : STD_LOGIC := '0';
+begin
+ assert FALSE -- LF works in QuartusII
+ report "uart_bclk:" & LF &
+ " CLOCK_FREQ=" & to_string(CLOCK_FREQ, 3) & LF &
+ " BAUDRATE=" & to_string(BAUDRATE, 3) & LF &
+ " COUNTER_MAX=" & INTEGER'image(BAUDRATE_COUNTER_MAX) & LF &
+ " COUNTER_BITS=" & INTEGER'image(BAUDRATE_COUNTER_BITS)
+ severity NOTE;
+
+ assert io_UART_IsTypicalBaudRate(BAUDRATE)
+ report "The baudrate " & to_string(BAUDRATE, 3) & " is not known to be a typical baudrate!"
+ severity WARNING;
+
+ x8_cnt <= upcounter_next(cnt => x8_cnt, rst => (rst or x8_cnt_done)) when rising_edge(clk);
+ x8_cnt_done <= upcounter_equal(cnt => x8_cnt, value => BAUDRATE_COUNTER_MAX - 1);
+
+ x1_cnt <= upcounter_next(cnt => x1_cnt, rst => rst, en => x8_cnt_done) when rising_edge(clk);
+ x1_cnt_done <= comp_allzero(x1_cnt);
+
+ -- outputs
+ -- ---------------------------------------------------------------------------
+ -- only x8_cnt_done is pulsed for one clock cycle!
+ bclk_r <= (x1_cnt_done and x8_cnt_done) when rising_edge(clk);
+ bclk_x8_r <= x8_cnt_done when rising_edge(clk);
+
+ bclk <= bclk_r;
+ bclk_x8 <= bclk_x8_r;
+end;
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl
new file mode 100644
index 000000000..e1c1c9e9e
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_fifo.vhdl
@@ -0,0 +1,320 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Martin Zabel
+-- Patrick Lehmann
+--
+-- Module: UART Wrapper with Embedded FIFOs and Optional Flow Control
+--
+-- Description:
+-- ------------------------------------
+-- Small FIFOs are included in this module, if larger or asynchronous
+-- transmit / receive FIFOs are required, then they must be connected
+-- externally.
+--
+-- old comments:
+-- UART BAUD rate generator
+-- bclk = bit clock is rising
+-- bclk_x8 = bit clock times 8 is rising
+--
+--
+-- License:
+-- ============================================================================
+-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+library PoC;
+use PoC.vectors.all;
+use PoC.physical.all;
+use PoC.components.all;
+use PoC.uart.all;
+
+
+entity uart_fifo is
+ generic (
+ CLOCK_FREQ : FREQ := 100 MHz;
+ BAUDRATE : BAUD := 115200 Bd;
+ FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE;
+ TX_MIN_DEPTH : POSITIVE := 16;
+ TX_ESTATE_BITS : NATURAL := 1;
+ RX_MIN_DEPTH : POSITIVE := 16;
+ RX_FSTATE_BITS : NATURAL := 1;
+ RX_OUT_REGS : BOOLEAN := FALSE;
+ ADD_INPUT_SYNCHRONIZERS : BOOLEAN := TRUE;
+
+ SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q
+ SWFC_XON_TRIGGER : real := 0.0625;
+ SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S
+ SWFC_XOFF_TRIGGER : real := 0.75
+ );
+ port (
+ Clock : in std_logic;
+ Reset : in std_logic;
+
+ -- FIFO interface
+ TX_put : in STD_LOGIC;
+ TX_Data : in STD_LOGIC_VECTOR(7 downto 0);
+ TX_Full : out STD_LOGIC;
+ TX_EmptyState : out STD_LOGIC_VECTOR(TX_ESTATE_BITS - 1 downto 0);
+
+ RX_Valid : out STD_LOGIC;
+ RX_Data : out STD_LOGIC_VECTOR(7 downto 0);
+ RX_got : in STD_LOGIC;
+ RX_FullState : out STD_LOGIC_VECTOR(RX_FSTATE_BITS - 1 downto 0);
+ RX_Overflow : out std_logic;
+
+ -- External pins
+ UART_TX : out std_logic;
+ UART_RX : in std_logic
+ );
+end entity;
+
+
+architecture rtl of uart_fifo is
+
+ signal FC_TX_Strobe : STD_LOGIC;
+ signal FC_TX_Data : T_SLV_8;
+ signal FC_TX_got : STD_LOGIC;
+ signal FC_RX_put : STD_LOGIC;
+ signal FC_RX_Data : T_SLV_8;
+
+ signal TXFIFO_Valid : STD_LOGIC;
+ signal TXFIFO_Data : T_SLV_8;
+
+ signal RXFIFO_Full : STD_LOGIC;
+
+ signal TXUART_Ready : STD_LOGIC;
+ signal RXUART_Strobe : STD_LOGIC;
+ signal RXUART_Data : T_SLV_8;
+
+ signal BitClock : STD_LOGIC;
+ signal BitClock_x8 : STD_LOGIC;
+
+ signal UART_RX_sync : STD_LOGIC;
+
+begin
+ assert FALSE report "uart_fifo: BAUDRATE=: " & to_string(BAUDRATE, 3) severity NOTE;
+
+ -- ===========================================================================
+ -- Transmit and Receive FIFOs
+ -- ===========================================================================
+ TXFIFO : entity PoC.fifo_cc_got
+ generic map (
+ D_BITS => 8, -- Data Width
+ MIN_DEPTH => TX_MIN_DEPTH, -- Minimum FIFO Depth
+ DATA_REG => TRUE, -- Store Data Content in Registers
+ STATE_REG => FALSE, -- Registered Full/Empty Indicators
+ OUTPUT_REG => FALSE, -- Registered FIFO Output
+ ESTATE_WR_BITS => TX_ESTATE_BITS, -- Empty State Bits
+ FSTATE_RD_BITS => 0 -- Full State Bits
+ )
+ port map (
+ rst => Reset,
+ clk => Clock,
+ put => TX_put,
+ din => TX_Data,
+ full => TX_Full,
+ estate_wr => TX_EmptyState,
+
+ valid => TXFIFO_Valid,
+ dout => TXFIFO_Data,
+ got => FC_TX_got,
+ fstate_rd => open
+ );
+
+ RXFIFO : entity PoC.fifo_cc_got
+ generic map (
+ D_BITS => 8, -- Data Width
+ MIN_DEPTH => RX_MIN_DEPTH, -- Minimum FIFO Depth
+ DATA_REG => TRUE, -- Store Data Content in Registers
+ STATE_REG => FALSE, -- Registered Full/Empty Indicators
+ OUTPUT_REG => FALSE, -- Registered FIFO Output
+ ESTATE_WR_BITS => 0, -- Empty State Bits
+ FSTATE_RD_BITS => RX_FSTATE_BITS -- Full State Bits
+ )
+ port map (
+ rst => Reset,
+ clk => Clock,
+ put => FC_RX_put,
+ din => FC_RX_Data,
+ full => RXFIFO_Full,
+ estate_wr => open,
+
+ valid => RX_Valid,
+ dout => RX_Data,
+ got => RX_got,
+ fstate_rd => RX_FullState
+ );
+
+ genNOFC : if (FLOWCONTROL = UART_FLOWCONTROL_NONE) generate
+ signal Overflow_r : std_logic := '0';
+ begin
+
+ FC_TX_Strobe <= TXFIFO_Valid and TXUART_Ready;
+ FC_TX_Data <= TXFIFO_Data;
+ FC_TX_got <= TXFIFO_Valid and TXUART_Ready;
+
+ FC_RX_put <= RXUART_Strobe;
+ FC_RX_Data <= RXUART_Data;
+
+ Overflow_r <= ffrs(q => Overflow_r, rst => Reset, set => (RXUART_Strobe and RXFIFO_Full)) when rising_edge(Clock);
+
+ RX_Overflow <= Overflow_r;
+ end generate;
+ -- ===========================================================================
+ -- Software Flow Control
+ -- ===========================================================================
+ genSWFC : if (FLOWCONTROL = UART_FLOWCONTROL_XON_XOFF) generate
+ constant XON : std_logic_vector(7 downto 0) := x"11"; -- ^Q
+ constant XOFF : std_logic_vector(7 downto 0) := x"13"; -- ^S
+
+ constant XON_TRIG : integer := integer(SWFC_XON_TRIGGER * real(2**RX_FSTATE_BITS));
+ constant XOFF_TRIG : integer := integer(SWFC_XOFF_TRIGGER * real(2**RX_FSTATE_BITS));
+
+ signal send_xoff : std_logic;
+ signal send_xon : std_logic;
+
+ signal set_xoff_transmitted : std_logic;
+ signal clr_xoff_transmitted : std_logic;
+ signal discard_user : std_logic;
+
+ signal set_overflow : std_logic;
+
+ -- registers
+ signal xoff_transmitted : std_logic;
+
+ begin
+-- -- send XOFF only once when fill state goes above trigger level
+-- send_xoff <= (not xoff_transmitted) when (rf_fs >= XOFF_TRIG) else '0';
+-- set_xoff_transmitted <= tx_rdy when (rf_fs >= XOFF_TRIG) else '0';
+--
+-- -- send XON only once when receive FIFO is almost empty
+-- send_xon <= xoff_transmitted when (rf_fs = XON_TRIG) else '0';
+-- clr_xoff_transmitted <= tx_rdy when (rf_fs = XON_TRIG) else '0';
+--
+-- -- discard any user supplied XON/XOFF
+-- discard_user <= '1' when (tf_dout = SWFC_XON_CHAR) or (tf_dout = SWFC_XOFF_CHAR) else '0';
+--
+-- -- tx / tf control
+-- tx_din <= SWFC_XOFF_CHAR when (send_xoff = '1') else
+-- SWFC_XON_CHAR when (send_xon = '1') else
+-- tf_dout;
+--
+-- tx_stb <= send_xoff or send_xon or (tf_valid and (not discard_user));
+-- tf_got <= (send_xoff nor send_xon) and
+-- tf_valid and tx_rdy; -- always check tf_valid
+--
+-- -- rx / rf control
+-- rf_put <= (not rf_full) and rx_dos; -- always check rf_full
+-- rf_din <= rx_dout;
+--
+-- set_overflow <= rf_full and rx_dos;
+--
+-- -- registers
+-- process (Clock)
+-- begin -- process
+-- if rising_edge(Clock) then
+-- if (rst or set_xoff_transmitted) = '1' then
+-- -- send a XON after reset
+-- xoff_transmitted <= '1';
+-- elsif clr_xoff_transmitted = '1' then
+-- xoff_transmitted <= '0';
+-- end if;
+--
+-- if rst = '1' then
+-- overflow <= '0';
+-- elsif set_overflow = '1' then
+-- overflow <= '1';
+-- end if;
+-- end if;
+-- end process;
+ end generate;
+ -- ===========================================================================
+ -- Hardware Flow Control
+ -- ===========================================================================
+ genHWFC1 : if (FLOWCONTROL = UART_FLOWCONTROL_RTS_CTS) generate
+
+ begin
+
+ end generate;
+ -- ===========================================================================
+ -- Hardware Flow Control
+ -- ===========================================================================
+ genHWFC2 : if (FLOWCONTROL = UART_FLOWCONTROL_RTR_CTS) generate
+
+ begin
+
+ end generate;
+
+ -- ===========================================================================
+ -- BitClock, Transmitter, Receiver
+ -- ===========================================================================
+ genNoSync : if (ADD_INPUT_SYNCHRONIZERS = FALSE) generate
+ UART_RX_sync <= UART_RX;
+ end generate;
+ genSync: if (ADD_INPUT_SYNCHRONIZERS = TRUE) generate
+ sync_i : entity PoC.sync_Bits
+ port map (
+ Clock => Clock, -- Clock to be synchronized to
+ Input(0) => UART_RX, -- Data to be synchronized
+ Output(0) => UART_RX_sync -- synchronised data
+ );
+ end generate;
+ -- ===========================================================================
+ -- BitClock, Transmitter, Receiver
+ -- ===========================================================================
+ bclk : entity PoC.uart_bclk
+ generic map (
+ CLOCK_FREQ => CLOCK_FREQ,
+ BAUDRATE => BAUDRATE
+ )
+ port map (
+ clk => Clock,
+ rst => Reset,
+ bclk => BitClock,
+ bclk_x8 => BitClock_x8
+ );
+
+ TX : entity PoC.uart_tx
+ port map (
+ clk => Clock,
+ rst => Reset,
+ bclk => BitClock,
+ stb => FC_TX_Strobe,
+ din => FC_TX_Data,
+ rdy => TXUART_Ready,
+ txd => UART_TX
+ );
+
+ RX : entity PoC.uart_rx
+ generic map (
+ OUT_REGS => RX_OUT_REGS
+ )
+ port map (
+ clk => Clock,
+ rst => Reset,
+ bclk_x8 => BitClock_x8,
+ dos => RXUART_Strobe,
+ dout => RXUART_Data,
+ rxd => UART_RX_sync
+ );
+end;
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl
new file mode 100644
index 000000000..01383bade
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_rx.vhdl
@@ -0,0 +1,174 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Martin Zabel
+-- Patrick Lehmann
+--
+-- Module: UART Receiver
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- old comments:
+-- Serial configuration: 8 data bits, 1 stop bit, no parity
+--
+-- bclk_x8 = bit clock (defined by BAUD rate) times 8
+-- dos = data out strobe, signals that dout is valid, active high for one
+-- cycle
+-- dout = data out = received byte
+--
+-- OUT_REGS:
+-- If disabled, then dos is a combinatorial output. Further merging of logic is
+-- possible but timing constraints might fail. If enabled, 9 more registers are
+-- required. But now, dout toggles only after receiving of full byte.
+--
+--
+-- License:
+-- ============================================================================
+-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.components.all;
+
+
+entity uart_rx is
+ generic (
+ OUT_REGS : boolean
+ );
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk_x8 : in std_logic;
+ rxd : in std_logic;
+ dos : out std_logic;
+ dout : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+
+architecture rtl of uart_rx is
+ type states is (IDLE, RDATA);
+ signal state : states := IDLE;
+ signal next_state : states;
+
+ -- registers
+ signal rxd_reg1 : std_logic := '1';
+ signal rxd_reg2 : std_logic := '1';
+ signal sr : std_logic_vector(7 downto 0) := (others => '0'); -- data only
+ signal bclk_cnt : unsigned(2 downto 0) := to_unsigned(4, 3);
+ signal shift_cnt : unsigned(3 downto 0) := (others => '0');
+
+ -- control signals
+ signal rxd_falling : std_logic;
+ signal bclk_rising : std_logic;
+ signal start_bclk : std_logic;
+ signal shift_sr : std_logic;
+ signal shift_done : std_logic;
+ signal put_data : std_logic;
+
+begin
+
+ rxd_falling <= (not rxd_reg1) and rxd_reg2;
+ bclk_rising <= bclk_x8 when (comp_allone(bclk_cnt) = '1') else '0';
+
+ -- shift_cnt count from 0 to 9 (1 start bit + 8 data bits)
+ shift_cnt <= upcounter_next(cnt => shift_cnt, rst => start_bclk, en => shift_sr) when rising_edge(clk);
+ shift_done <= upcounter_equal(cnt => shift_cnt, value => 9);
+
+ bclk_cnt <= upcounter_next(cnt => bclk_cnt, rst => start_bclk, en => bclk_x8, init => 4) when rising_edge(clk);
+
+ process (state, rxd_falling, bclk_x8, bclk_rising, shift_done)
+ begin
+ next_state <= state;
+ start_bclk <= '0';
+ shift_sr <= '0';
+ put_data <= '0';
+
+ case state is
+ when IDLE =>
+ -- wait for start bit
+ if (rxd_falling and bclk_x8) = '1' then
+ next_state <= RDATA;
+ start_bclk <= '1'; -- = rst_shift_cnt
+ end if;
+
+ when RDATA =>
+ if bclk_rising = '1' then
+ -- bit clock keeps running
+ if shift_done = '1' then
+ -- stop bit reached
+ put_data <= '1';
+ next_state <= IDLE;
+
+ else
+ -- TODO: check start bit?
+ shift_sr <= '1';
+ end if;
+ end if;
+
+ when others => null;
+ end case;
+ end process;
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ state <= IDLE;
+ else
+ state <= next_state;
+ end if;
+
+ rxd_reg1 <= rxd;
+
+ if bclk_x8 = '1' then
+ -- align to bclk_x8, so when we can easily check for
+ -- the falling edge of the start bit
+ rxd_reg2 <= rxd_reg1;
+ end if;
+
+ if shift_sr = '1' then
+ -- shift into MSB
+ sr <= rxd_reg2 & sr(sr'left downto 1);
+ end if;
+ end if;
+ end process;
+
+ -- output
+ gOutRegs: if OUT_REGS = true generate
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ dos <= put_data and rxd_reg2; -- check stop bit
+ dout <= sr;
+ end if;
+ end process;
+ end generate gOutRegs;
+
+ gNoOutRegs: if OUT_REGS = false generate
+ dos <= put_data and rxd_reg2; -- check stop bit
+ dout <= sr;
+ end generate gNoOutRegs;
+
+end;
diff --git a/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl b/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl
new file mode 100644
index 000000000..fe329faf9
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/src/io/uart/uart_tx.vhdl
@@ -0,0 +1,140 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Authors: Martin Zabel
+-- Patrick Lehmann
+--
+-- Module: UART Transmitter
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- old comments:
+-- Serial configuration: 8 data bits, 1 stop bit, no parity
+--
+-- bclk = bit clk is rising
+-- stb = strobe, i.e. transmit byte @ din
+-- rdy = ready
+--
+--
+-- License:
+-- ============================================================================
+-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.components.all;
+
+
+entity uart_tx is
+ port (
+ clk : in std_logic;
+ rst : in std_logic;
+ bclk : in std_logic;
+ stb : in std_logic;
+ din : in std_logic_vector(7 downto 0);
+ rdy : out std_logic;
+ txd : out std_logic
+ );
+end entity;
+
+
+architecture rtl of uart_tx is
+ type states is (IDLE, TDATA);
+ signal state : states := IDLE;
+ signal next_state : states;
+
+ -- register
+ signal sr : std_logic_vector(9 downto 1) := (others => '0');
+ signal sr0 : std_logic := '1'; -- current bit to transmit
+ signal shift_cnt : unsigned(3 downto 0) := (others => '0');
+ signal shift_done : STD_LOGIC;
+
+ -- control signals
+ signal start_tx : std_logic;
+ signal shift_sr : std_logic;
+
+begin
+
+ process (state, stb, bclk, shift_done)
+ begin
+ next_state <= state;
+ start_tx <= '0';
+ shift_sr <= '0';
+
+ case state is
+ when IDLE =>
+ if stb = '1' then
+ -- start_tx triggers register initialization
+ start_tx <= '1';
+ next_state <= TDATA;
+ end if;
+
+ when TDATA =>
+ if bclk = '1' then
+ -- also shift stop bit into sr0!
+ shift_sr <= '1';
+
+ if (shift_done = '1') then
+ -- condition is true at beginning of sending the stop-bit
+ -- synchronization to the bitclk ensures that stop-bit is
+ -- transmitted fully
+ next_state <= IDLE;
+ end if;
+ end if;
+ when others => null;
+ end case;
+ end process;
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ state <= IDLE;
+ else
+ state <= next_state;
+ end if;
+
+ if start_tx = '1' then
+ -- data, start bit
+ sr <= din & '0';
+ elsif shift_sr = '1' then
+ sr <= '1' & sr(sr'left downto sr'right+1);
+ end if;
+
+ if rst = '1' then
+ sr0 <= '1'; -- idle
+ elsif shift_sr = '1' then
+ sr0 <= sr(1);
+ end if;
+ end if;
+ end process;
+
+ shift_cnt <= upcounter_next(cnt => shift_cnt, rst => start_tx, en => shift_sr) when rising_edge(clk);
+ shift_done <= upcounter_equal(cnt => shift_cnt, value => 9);
+
+ -- outputs
+ txd <= sr0;
+ rdy <= '1' when state = IDLE else '0';
+
+end;
diff --git a/testsuite/gna/bug019/PoC/tb/.gitignore b/testsuite/gna/bug019/PoC/tb/.gitignore
new file mode 100644
index 000000000..4095aa175
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/.gitignore
@@ -0,0 +1,2 @@
+*-obj93.cf
+*_tb
diff --git a/testsuite/gna/bug019/PoC/tb/common/config_tb.vhdl b/testsuite/gna/bug019/PoC/tb/common/config_tb.vhdl
new file mode 100644
index 000000000..1c0ab5919
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/config_tb.vhdl
@@ -0,0 +1,76 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Testbench: Tests global constants, functions and settings
+--
+-- Authors: Thomas B. Preusser
+-- Patrick Lehmann
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2014 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+entity config_tb is
+end config_tb;
+
+
+library PoC;
+use PoC.config.all;
+use PoC.utils.all;
+use PoC.simulation.all;
+
+
+architecture tb of config_tb is
+ signal SimQuiet : BOOLEAN := true;
+begin
+ process
+ begin
+ if (SimQuiet = FALSE) then
+ report "is simulation?: " & boolean'image(SIMULATION) severity note;
+ report "Vendor: " & vendor_t'image(VENDOR) severity note;
+ report "Device: " & device_t'image(DEVICE) severity note;
+ report "Device Number: " & integer'image(DEVICE_NUMBER) severity note;
+ report "Device Subtype: " & T_DEVICE_SUBTYPE'image(DEVICE_SUBTYPE) severity note;
+ report "Device Series: " & integer'image(DEVICE_SERIES) severity note;
+ report "--------------------------------------------------" severity note;
+ report "LUT fan-in: " & integer'image(LUT_FANIN) severity note;
+ report "Transceiver: " & T_TRANSCEIVER'image(TRANSCEIVER_TYPE) severity note;
+ end if;
+
+ tbAssert((SIMULATION = TRUE), "SIMULATION=" & BOOLEAN'image(SIMULATION) & " Expected=TRUE");
+ tbAssert((VENDOR = VENDOR_XILINX), "VENDOR= " & VENDOR_T'image(VENDOR) & " Expected=VENDOR_XILINX");
+ tbAssert((DEVICE = DEVICE_KINTEX7), "DEVICE=" & DEVICE_T'image(DEVICE) & " Expected=DEVICE_KINTEX7");
+ tbAssert((DEVICE_FAMILY = DEVICE_FAMILY_KINTEX), "DEVICE_FAMILY=" & T_DEVICE_FAMILY'image(DEVICE_FAMILY) & " Expected=DEVICE_FAMILY_KINTEX");
+ tbAssert((DEVICE_NUMBER = 325), "DEVICE_NUMBER=" & INTEGER'image(DEVICE_NUMBER) & " Expected=325");
+ tbAssert((DEVICE_SUBTYPE = DEVICE_SUBTYPE_T), "DEVICE_SUBTYPE=" & T_DEVICE_SUBTYPE'image(DEVICE_SUBTYPE) & " Expected=DEVICE_SUBTYPE_T");
+ tbAssert((DEVICE_SERIES = 7), "DEVICE_SERIES=" & INTEGER'image(DEVICE_SERIES) & " Expected=7");
+ tbAssert((LUT_FANIN = 6), "LUT_FANIN=" & INTEGER'image(LUT_FANIN) & " Expected=6");
+ tbAssert((TRANSCEIVER_TYPE = TRANSCEIVER_GTXE2), "TRANSCEIVER_TYPE=" & T_TRANSCEIVER'image(TRANSCEIVER_TYPE) & " Expected=TRANSCEIVER_GTXE2");
+
+ -- simulation completed
+
+ -- Report overall simulation result
+ tbPrintResult;
+ wait;
+ end process;
+end;
diff --git a/testsuite/gna/bug019/PoC/tb/common/my_config_ML505.vhdl b/testsuite/gna/bug019/PoC/tb/common/my_config_ML505.vhdl
new file mode 100644
index 000000000..dd4634b2b
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/my_config_ML505.vhdl
@@ -0,0 +1,48 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Project specific configuration.
+--
+-- Description:
+-- ------------------------------------
+-- This file was created from template <PoCRoot>/src/common/my_config.template.vhdl.
+--
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library PoC;
+
+
+package my_config is
+ -- Change these lines to setup configuration.
+ constant MY_BOARD : string := "ML505"; -- ML505 - Xilinx Virtex 5 reference design board: XC5VLX50T
+ constant MY_DEVICE : string := "None"; -- infer from MY_BOARD
+
+ -- For internal use only
+ constant MY_VERBOSE : boolean := FALSE;
+end package;
+
+package body my_config is
+end package body;
diff --git a/testsuite/gna/bug019/PoC/tb/common/my_config_ML605.vhdl b/testsuite/gna/bug019/PoC/tb/common/my_config_ML605.vhdl
new file mode 100644
index 000000000..90bb0ac0e
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/my_config_ML605.vhdl
@@ -0,0 +1,50 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Thomas B. Preusser
+-- Martin Zabel
+-- Patrick Lehmann
+--
+-- Package: Project specific configuration.
+--
+-- Description:
+-- ------------------------------------
+-- This file was created from template <PoCRoot>/src/common/my_config.template.vhdl.
+--
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library PoC;
+
+
+package my_config is
+ -- Change these lines to setup configuration.
+ constant MY_BOARD : string := "ML605"; -- ML605 - Xilinx Virtex 6 reference design board: XC6VLX240T
+ constant MY_DEVICE : string := "None"; -- infer from MY_BOARD
+
+ -- For internal use only
+ constant MY_VERBOSE : boolean := FALSE;
+end package;
+
+
+package body my_config is
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/tb/common/my_project.vhdl b/testsuite/gna/bug019/PoC/tb/common/my_project.vhdl
new file mode 100644
index 000000000..84d03a84d
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/my_project.vhdl
@@ -0,0 +1,52 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Patrick Lehmann
+--
+-- Package: Project specific configuration.
+--
+-- Description:
+-- ------------------------------------
+-- This is a template file.
+--
+-- TODO
+--
+-- USAGE:
+-- 1) Copy this file into your project's source directory and rename it to
+-- "my_project.vhdl".
+-- 2) Add file to library "poc" in your synthesis tool.
+-- 3) Change setup appropriately.
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library PoC;
+
+
+package my_project is
+ -- Change these lines to setup configuration.
+ constant MY_PROJECT_DIR : string := ".";
+ constant MY_OPERATING_SYSTEM : string := "LINUX"; -- e.g. "WINDOWS", "LINUX"
+end package;
+
+
+package body my_project is
+
+end package body;
diff --git a/testsuite/gna/bug019/PoC/tb/common/simulation.v08.vhdl b/testsuite/gna/bug019/PoC/tb/common/simulation.v08.vhdl
new file mode 100644
index 000000000..227158aae
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/simulation.v08.vhdl
@@ -0,0 +1,363 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Patrick Lehmann
+-- Thomas B. Preusser
+--
+-- Package: Simulation constants, functions and utilities.
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+library PoC;
+use PoC.vectors.all;
+use PoC.strings.all;
+use PoC.physical.all;
+
+
+package simulation is
+ -- predefined constants to ease testvector concatenation
+ constant U8 : T_SLV_8 := (others => 'U');
+ constant U16 : T_SLV_16 := (others => 'U');
+ constant U24 : T_SLV_24 := (others => 'U');
+ constant U32 : T_SLV_32 := (others => 'U');
+
+ constant D8 : T_SLV_8 := (others => '-');
+ constant D16 : T_SLV_16 := (others => '-');
+ constant D24 : T_SLV_24 := (others => '-');
+ constant D32 : T_SLV_32 := (others => '-');
+
+ -- Testbench Status Management
+ -- ===========================================================================
+
+ -- VHDL'08: Provide a protected tSimStatus type that may be used for
+ -- other purposes as well. For compatibility with the VHDL'93
+ -- implementation, the plain procedure implementation is also
+ -- provided on top of a package private instance of this type.
+
+ type T_TB_STATUS is protected
+ -- The status is changed to failed. If a message is provided, it is
+ -- reported as an error.
+ procedure simFail(msg : in string := "");
+
+ -- If the passed condition has evaluated false, the status is marked
+ -- as failed. In this case, the optional message will be reported as
+ -- an error if provided.
+ procedure simAssert(cond : in boolean; msg : in string := "");
+
+ -- Prints the final status. Unless simFail() or simAssert() with a
+ -- false condition have been called before, a successful completion
+ -- will be indicated, a failure otherwise.
+ procedure simReport;
+ end protected;
+
+ type T_SIM_STATUS is protected
+ procedure stop;
+ impure function isStopped return BOOLEAN;
+ end protected;
+
+ -- The testbench is marked as failed. If a message is provided, it is
+ -- reported as an error.
+ procedure tbFail(msg : in string := "");
+
+ -- If the passed condition has evaluated false, the testbench is marked
+ -- as failed. In this case, the optional message will be reported as an
+ -- error if one was provided.
+ procedure tbAssert(cond : in boolean; msg : in string := "");
+
+ -- Prints out the overall testbench result as defined by the automated
+ -- testbench process. Unless tbFail() or tbAssert() with a false condition
+ -- have been called before, a successful completion will be reported, a
+ -- failure otherwise.
+ procedure tbPrintResult;
+
+ -- clock generation
+ -- ===========================================================================
+ subtype T_DutyCycle is REAL range 0.0 to 1.0;
+
+ procedure simStop;
+ impure function simIsStopped return BOOLEAN;
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Frequency : in FREQ; constant DutyCycle : T_DutyCycle := 0.5);
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Period : in TIME; constant DutyCycle : T_DutyCycle := 0.5);
+
+ -- waveform generation
+ -- ===========================================================================
+ type T_SIM_WAVEFORM_TUPLE_SL is record
+ Delay : TIME;
+ Value : STD_LOGIC;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_8 is record
+ Delay : TIME;
+ Value : T_SLV_8;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_16 is record
+ Delay : TIME;
+ Value : T_SLV_16;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_24 is record
+ Delay : TIME;
+ Value : T_SLV_24;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_32 is record
+ Delay : TIME;
+ Value : T_SLV_32;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_48 is record
+ Delay : TIME;
+ Value : T_SLV_48;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_64 is record
+ Delay : TIME;
+ Value : T_SLV_64;
+ end record;
+
+ type T_SIM_WAVEFORM_SL is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SL;
+ type T_SIM_WAVEFORM_SLV_8 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_8;
+ type T_SIM_WAVEFORM_SLV_16 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_16;
+ type T_SIM_WAVEFORM_SLV_24 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_24;
+ type T_SIM_WAVEFORM_SLV_32 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_32;
+ type T_SIM_WAVEFORM_SLV_48 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_48;
+ type T_SIM_WAVEFORM_SLV_64 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_64;
+
+ procedure simGenerateWaveform(signal Wave : out BOOLEAN; Waveform: T_TIMEVEC; InitialValue : BOOLEAN);
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_TIMEVEC; InitialValue : STD_LOGIC := '0');
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_SIM_WAVEFORM_SL; InitialValue : STD_LOGIC := '0');
+ procedure simGenerateWaveform(signal Wave : out T_SLV_8; Waveform: T_SIM_WAVEFORM_SLV_8; InitialValue : T_SLV_8);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_16; Waveform: T_SIM_WAVEFORM_SLV_16; InitialValue : T_SLV_16);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_24; Waveform: T_SIM_WAVEFORM_SLV_24; InitialValue : T_SLV_24);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_32; Waveform: T_SIM_WAVEFORM_SLV_32; InitialValue : T_SLV_32);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_48; Waveform: T_SIM_WAVEFORM_SLV_48; InitialValue : T_SLV_48);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_64; Waveform: T_SIM_WAVEFORM_SLV_64; InitialValue : T_SLV_64);
+
+ function simGenerateWaveform_Reset(constant Pause : TIME := 0 ns; ResetPulse : TIME := 10 ns) return T_TIMEVEC;
+
+end;
+
+
+use std.TextIO.all;
+
+package body simulation is
+ -- Testbench Status Management
+ -- ===========================================================================
+ type T_TB_STATUS is protected body
+ -- Internal state variable to log a failure condition for final reporting.
+ -- Once de-asserted, this variable will never return to a value of true.
+ variable pass : boolean := true;
+
+ procedure simFail(msg : in string := "") is
+ begin
+ if msg'length > 0 then
+ report msg severity error;
+ end if;
+ pass := false;
+ end;
+
+ procedure simAssert(cond : in boolean; msg : in string := "") is
+ begin
+ if not cond then
+ simFail(msg);
+ end if;
+ end;
+
+ procedure simReport is
+ variable l : line;
+ begin
+ write(l, string'("SIMULATION RESULT = "));
+ if pass then
+ write(l, string'("PASSED"));
+ else
+ write(l, string'("FAILED"));
+ end if;
+ writeline(output, l);
+ end;
+ end protected body;
+
+ type T_SIM_STATUS is protected body
+ variable stopped : BOOLEAN := FALSE;
+
+ procedure stop is
+ begin
+ stopped := TRUE;
+ end procedure;
+
+ impure function isStopped return BOOLEAN is
+ begin
+ return stopped;
+ end function;
+ end protected body;
+
+ -- The default global tSimStatus object.
+ shared variable tbStatus : T_TB_STATUS;
+ shared variable simStatus : T_SIM_STATUS;
+
+ -- legacy procedures
+ -- ===========================================================================
+ procedure tbFail(msg : in string := "") is
+ begin
+ tbStatus.simFail(msg);
+ end;
+
+ procedure tbAssert(cond : in boolean; msg : in string := "") is
+ begin
+ tbStatus.simAssert(cond, msg);
+ end;
+
+ procedure tbPrintResult is
+ begin
+ tbStatus.simReport;
+ end procedure;
+
+ -- clock generation
+ -- ===========================================================================
+ procedure simStop is
+ begin
+ simStatus.stop;
+ end procedure;
+
+ impure function simIsStopped return BOOLEAN is
+ begin
+ return simStatus.isStopped;
+ end function;
+
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Frequency : in FREQ; constant DutyCycle : T_DutyCycle := 0.5) is
+ constant Period : TIME := to_time(Frequency);
+ begin
+ simGenerateClock(Clock, Period, DutyCycle);
+ end procedure;
+
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Period : in TIME; constant DutyCycle : T_DutyCycle := 0.5) is
+ constant TIME_HIGH : TIME := Period * DutyCycle;
+ constant TIME_LOW : TIME := Period - TIME_HIGH;
+ begin
+ Clock <= '0';
+
+ while (not simStatus.isStopped) loop
+ wait for TIME_LOW;
+ Clock <= '1';
+ wait for TIME_HIGH;
+ Clock <= '0';
+ end loop;
+ end procedure;
+
+ -- waveform generation
+ -- ===========================================================================
+ procedure simGenerateWaveform(signal Wave : out BOOLEAN; Waveform : T_TIMEVEC; InitialValue : BOOLEAN) is
+ variable State : BOOLEAN := InitialValue;
+ begin
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_TIMEVEC; InitialValue : STD_LOGIC := '0') is
+ variable State : STD_LOGIC := InitialValue;
+ begin
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_SIM_WAVEFORM_SL; InitialValue : STD_LOGIC := '0') is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_8; Waveform: T_SIM_WAVEFORM_SLV_8; InitialValue : T_SLV_8) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_16; Waveform: T_SIM_WAVEFORM_SLV_16; InitialValue : T_SLV_16) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_24; Waveform: T_SIM_WAVEFORM_SLV_24; InitialValue : T_SLV_24) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_32; Waveform: T_SIM_WAVEFORM_SLV_32; InitialValue : T_SLV_32) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_48; Waveform: T_SIM_WAVEFORM_SLV_48; InitialValue : T_SLV_48) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_64; Waveform: T_SIM_WAVEFORM_SLV_64; InitialValue : T_SLV_64) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ function simGenerateWaveform_Reset(constant Pause : TIME := 0 ns; ResetPulse : TIME := 10 ns) return T_TIMEVEC is
+ begin
+ return (0 => Pause, 1 => ResetPulse);
+ end function;
+end package body;
diff --git a/testsuite/gna/bug019/PoC/tb/common/simulation.v93.vhdl b/testsuite/gna/bug019/PoC/tb/common/simulation.v93.vhdl
new file mode 100644
index 000000000..22e6009f6
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/simulation.v93.vhdl
@@ -0,0 +1,308 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Testbench: Simulation constants, functions and utilities.
+--
+-- Authors: Patrick Lehmann
+-- Thomas B. Preusser
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2014 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+library PoC;
+use PoC.vectors.all;
+use PoC.strings.all;
+use PoC.physical.all;
+
+
+package simulation is
+ -- predefined constants to ease testvector concatenation
+ constant U8 : T_SLV_8 := (others => 'U');
+ constant U16 : T_SLV_16 := (others => 'U');
+ constant U24 : T_SLV_24 := (others => 'U');
+ constant U32 : T_SLV_32 := (others => 'U');
+
+ constant D8 : T_SLV_8 := (others => '-');
+ constant D16 : T_SLV_16 := (others => '-');
+ constant D24 : T_SLV_24 := (others => '-');
+ constant D32 : T_SLV_32 := (others => '-');
+
+ -- Testbench Status Management
+ -- ===========================================================================
+ -- The testbench is marked as failed. If a message is provided, it is
+ -- reported as an error.
+ procedure tbFail(msg : in string := "");
+
+ -- If the passed condition has evaluated false, the testbench is marked
+ -- as failed. In this case, the optional message will be reported as an
+ -- error if one was provided.
+ procedure tbAssert(cond : in boolean; msg : in string := "");
+
+ -- Prints out the overall testbench result as defined by the automated
+ -- testbench process. Unless tbFail() or tbAssert() with a false condition
+ -- have been called before, a successful completion will be reported, a
+ -- failure otherwise.
+ procedure tbPrintResult;
+
+ -- clock generation
+ -- ===========================================================================
+ subtype T_DutyCycle is REAL range 0.0 to 1.0;
+
+ procedure simStop;
+ impure function simIsStopped return BOOLEAN;
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Frequency : in FREQ; constant DutyCycle : T_DutyCycle := 0.5);
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Period : in TIME; constant DutyCycle : T_DutyCycle := 0.5);
+
+ -- waveform generation
+ -- ===========================================================================
+ type T_SIM_WAVEFORM_TUPLE_SL is record
+ Delay : TIME;
+ Value : STD_LOGIC;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_8 is record
+ Delay : TIME;
+ Value : T_SLV_8;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_16 is record
+ Delay : TIME;
+ Value : T_SLV_16;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_24 is record
+ Delay : TIME;
+ Value : T_SLV_24;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_32 is record
+ Delay : TIME;
+ Value : T_SLV_32;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_48 is record
+ Delay : TIME;
+ Value : T_SLV_48;
+ end record;
+
+ type T_SIM_WAVEFORM_TUPLE_SLV_64 is record
+ Delay : TIME;
+ Value : T_SLV_64;
+ end record;
+
+ type T_SIM_WAVEFORM_SL is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SL;
+ type T_SIM_WAVEFORM_SLV_8 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_8;
+ type T_SIM_WAVEFORM_SLV_16 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_16;
+ type T_SIM_WAVEFORM_SLV_24 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_24;
+ type T_SIM_WAVEFORM_SLV_32 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_32;
+ type T_SIM_WAVEFORM_SLV_48 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_48;
+ type T_SIM_WAVEFORM_SLV_64 is array(NATURAL range <>) of T_SIM_WAVEFORM_TUPLE_SLV_64;
+
+ procedure simGenerateWaveform(signal Wave : out BOOLEAN; Waveform: T_TIMEVEC; InitialValue : BOOLEAN);
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_TIMEVEC; InitialValue : STD_LOGIC := '0');
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_SIM_WAVEFORM_SL; InitialValue : STD_LOGIC := '0');
+ procedure simGenerateWaveform(signal Wave : out T_SLV_8; Waveform: T_SIM_WAVEFORM_SLV_8; InitialValue : T_SLV_8);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_16; Waveform: T_SIM_WAVEFORM_SLV_16; InitialValue : T_SLV_16);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_24; Waveform: T_SIM_WAVEFORM_SLV_24; InitialValue : T_SLV_24);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_32; Waveform: T_SIM_WAVEFORM_SLV_32; InitialValue : T_SLV_32);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_48; Waveform: T_SIM_WAVEFORM_SLV_48; InitialValue : T_SLV_48);
+ procedure simGenerateWaveform(signal Wave : out T_SLV_64; Waveform: T_SIM_WAVEFORM_SLV_64; InitialValue : T_SLV_64);
+
+ function simGenerateWaveform_Reset(constant Pause : TIME := 0 ns; ResetPulse : TIME := 10 ns) return T_TIMEVEC;
+
+ -- TODO: integrate VCD simulation functions and procedures from sim_value_change_dump.vhdl here
+
+ -- checksum functions
+ -- ===========================================================================
+ -- TODO: move checksum functions here
+end;
+
+
+use std.TextIO.all;
+
+package body simulation is
+
+ -- Testbench Status Management
+ -- ===========================================================================
+ -- Internal state variable to log a failure condition for final reporting.
+ -- Once de-asserted, this variable will never return to a value of true.
+ shared variable pass : boolean := true;
+ shared variable simStopped : BOOLEAN := FALSE;
+
+ procedure tbFail(msg : in string := "") is
+ begin
+ if (str_length(msg) > 0) then
+ report str_trim(msg) severity error;
+ end if;
+ pass := false;
+ end;
+
+ procedure tbAssert(cond : in boolean; msg : in string := "") is
+ begin
+ if not cond then
+ tbFail(msg);
+ end if;
+ end;
+
+ procedure tbPrintResult is
+ variable l : line;
+ begin
+ write(l, string'("SIMULATION RESULT = "));
+ if pass then
+ write(l, string'("PASSED"));
+ else
+ write(l, string'("FAILED"));
+ end if;
+ writeline(output, l);
+ end procedure;
+
+ -- clock generation
+ procedure simStop is
+ begin
+ simStopped := TRUE;
+ end procedure;
+
+ impure function simIsStopped return BOOLEAN is
+ begin
+ return simStopped;
+ end function;
+
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Frequency : in FREQ; constant DutyCycle : T_DutyCycle := 0.5) is
+ constant Period : TIME := to_time(Frequency);
+ begin
+ simGenerateClock(Clock, Period, DutyCycle);
+ end procedure;
+
+ procedure simGenerateClock(signal Clock : out STD_LOGIC; constant Period : in TIME; constant DutyCycle : T_DutyCycle := 0.5) is
+ constant TIME_HIGH : TIME := Period * DutyCycle;
+ constant TIME_LOW : TIME := Period - TIME_HIGH;
+ begin
+ Clock <= '0';
+
+ while (not simStopped) loop
+ wait for TIME_LOW;
+ Clock <= '1';
+ wait for TIME_HIGH;
+ Clock <= '0';
+ end loop;
+ end procedure;
+
+ -- waveform generation
+ procedure simGenerateWaveform(signal Wave : out BOOLEAN; Waveform : T_TIMEVEC; InitialValue : BOOLEAN) is
+ variable State : BOOLEAN := InitialValue;
+ begin
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_TIMEVEC; InitialValue : STD_LOGIC := '0') is
+ variable State : STD_LOGIC := InitialValue;
+ begin
+ Wave <= State;
+ for i in Waveform'range loop
+ wait for Waveform(i);
+ State := not State;
+ Wave <= State;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out STD_LOGIC; Waveform: T_SIM_WAVEFORM_SL; InitialValue : STD_LOGIC := '0') is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_8; Waveform: T_SIM_WAVEFORM_SLV_8; InitialValue : T_SLV_8) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_16; Waveform: T_SIM_WAVEFORM_SLV_16; InitialValue : T_SLV_16) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_24; Waveform: T_SIM_WAVEFORM_SLV_24; InitialValue : T_SLV_24) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_32; Waveform: T_SIM_WAVEFORM_SLV_32; InitialValue : T_SLV_32) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_48; Waveform: T_SIM_WAVEFORM_SLV_48; InitialValue : T_SLV_48) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ procedure simGenerateWaveform(signal Wave : out T_SLV_64; Waveform: T_SIM_WAVEFORM_SLV_64; InitialValue : T_SLV_64) is
+ begin
+ Wave <= InitialValue;
+ for i in Waveform'range loop
+ wait for Waveform(i).Delay;
+ Wave <= Waveform(i).Value;
+ end loop;
+ end procedure;
+
+ function simGenerateWaveform_Reset(constant Pause : TIME := 0 ns; ResetPulse : TIME := 10 ns) return T_TIMEVEC is
+ begin
+ return (0 => Pause, 1 => ResetPulse);
+ end function;
+
+ -- checksum functions
+ -- ===========================================================================
+ -- TODO: move checksum functions here
+end package body;
diff --git a/testsuite/gna/bug019/PoC/tb/common/strings_tb.vhdl b/testsuite/gna/bug019/PoC/tb/common/strings_tb.vhdl
new file mode 100644
index 000000000..30e3b5c77
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/common/strings_tb.vhdl
@@ -0,0 +1,123 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Testbench: Tests global constants, functions and settings
+--
+-- Authors: Patrick Lehmann
+--
+-- Description:
+-- ------------------------------------
+-- TODO
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- =============================================================================
+
+entity strings_tb is
+end strings_tb;
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.config.all;
+use PoC.utils.all;
+use PoC.strings.all;
+use PoC.simulation.all;
+
+
+architecture tb of strings_tb is
+ constant raw_format_slv_dec_result0 : STRING := raw_format_slv_dec(STD_LOGIC_VECTOR'(x"12"));
+ constant raw_format_slv_dec_result1 : STRING := raw_format_slv_dec(x"3456");
+ constant raw_format_slv_dec_result2 : STRING := raw_format_slv_dec(x"12345678");
+ constant raw_format_slv_dec_result3 : STRING := raw_format_slv_dec(x"A1B2C3D4E5F607A8");
+
+ constant str_length_result0 : INTEGER := str_length("");
+ constant str_length_result1 : INTEGER := str_length((1 to 3 => C_POC_NUL));
+ constant str_length_result2 : INTEGER := str_length("Hello");
+ constant str_length_result3 : INTEGER := str_length("Hello" & (1 to 3 => C_POC_NUL));
+
+ constant str_match_result0 : BOOLEAN := str_match("", "");
+ constant str_match_result1 : BOOLEAN := str_match("", (1 to 3 => C_POC_NUL));
+ constant str_match_result2 : BOOLEAN := str_match("Hello", "hello");
+ constant str_match_result3 : BOOLEAN := str_match("Hello", "Hello");
+ constant str_match_result4 : BOOLEAN := str_match("Hello World", "Hello");
+ constant str_match_result5 : BOOLEAN := str_match("Hello", "Hello World");
+ constant str_match_result6 : BOOLEAN := str_match("Hello", "Hello" & (1 to 3 => C_POC_NUL));
+
+ constant str_imatch_result0 : BOOLEAN := str_imatch("", "");
+ constant str_imatch_result1 : BOOLEAN := str_imatch("", (1 to 3 => C_POC_NUL));
+ constant str_imatch_result2 : BOOLEAN := str_imatch("Hello", "hello");
+ constant str_imatch_result3 : BOOLEAN := str_imatch("Hello", "Hello");
+ constant str_imatch_result4 : BOOLEAN := str_imatch("Hello World", "Hello");
+ constant str_imatch_result5 : BOOLEAN := str_imatch("Hello", "Hello World");
+ constant str_imatch_result6 : BOOLEAN := str_imatch("Hello", "Hello" & (1 to 3 => C_POC_NUL));
+begin
+ process
+ begin
+ -- raw_format_slv_dec tests
+ tbAssert((raw_format_slv_dec_result0 = "18"), "raw_format_slv_dec(0x12)=" & raw_format_slv_dec_result0 & " Expected='18'");
+ tbAssert((raw_format_slv_dec_result1 = "13398"), "raw_format_slv_dec(0x3456)=" & raw_format_slv_dec_result1 & " Expected='13398'");
+ tbAssert((raw_format_slv_dec_result2 = "305419896"), "raw_format_slv_dec(0x12345678)=" & raw_format_slv_dec_result2 & " Expected='305419896'");
+ tbAssert((raw_format_slv_dec_result3 = "11651590505119483816"), "raw_format_slv_dec(0xA1b2c3d4e5f607a8)=" & raw_format_slv_dec_result3 & " Expected='11651590505119483816'");
+
+ -- str_length tests
+ tbAssert((str_length_result0 = 0), "str_length('')=" & INTEGER'image(str_length_result0) & " Expected=0");
+ tbAssert((str_length_result1 = 0), "str_length('\0\0\0')=" & INTEGER'image(str_length_result1) & " Expected=0");
+ tbAssert((str_length_result2 = 5), "str_length('Hello')=" & INTEGER'image(str_length_result2) & " Expected=5");
+ tbAssert((str_length_result3 = 5), "str_length('Hello\0\0\0')=" & INTEGER'image(str_length_result3) & " Expected=5");
+
+ -- str_match tests
+ tbAssert((str_match_result0 = TRUE), "str_match('', '')=" & BOOLEAN'image(str_match_result0) & " Expected=TRUE");
+ tbAssert((str_match_result1 = TRUE), "str_match('', '\0\0\0')=" & BOOLEAN'image(str_match_result1) & " Expected=TRUE");
+ tbAssert((str_match_result2 = FALSE), "str_match('Hello', 'hello')=" & BOOLEAN'image(str_match_result2) & " Expected=FALSE");
+ tbAssert((str_match_result3 = TRUE), "str_match('Hello', 'Hello')=" & BOOLEAN'image(str_match_result3) & " Expected=TRUE");
+ tbAssert((str_match_result4 = FALSE), "str_match('Hello World', 'Hello')=" & BOOLEAN'image(str_match_result4) & " Expected=FALSE");
+ tbAssert((str_match_result5 = FALSE), "str_match('Hello', 'Hello World')=" & BOOLEAN'image(str_match_result5) & " Expected=FALSE");
+ tbAssert((str_match_result6 = TRUE), "str_match('Hello', 'Hello\0\0\0')=" & BOOLEAN'image(str_match_result6) & " Expected=TRUE");
+
+ -- str_imatch tests
+ tbAssert((str_imatch_result0 = TRUE), "str_imatch('', '')=" & BOOLEAN'image(str_imatch_result0) & " Expected=TRUE");
+ tbAssert((str_imatch_result1 = TRUE), "str_imatch('', '\0\0\0')=" & BOOLEAN'image(str_imatch_result1) & " Expected=TRUE");
+ tbAssert((str_imatch_result2 = TRUE), "str_imatch('Hello', 'hello')=" & BOOLEAN'image(str_imatch_result2) & " Expected=TRUE");
+ tbAssert((str_imatch_result3 = TRUE), "str_imatch('Hello', 'Hello')=" & BOOLEAN'image(str_imatch_result3) & " Expected=TRUE");
+ tbAssert((str_imatch_result4 = FALSE), "str_imatch('Hello World', 'Hello')=" & BOOLEAN'image(str_imatch_result4) & " Expected=FALSE");
+ tbAssert((str_imatch_result5 = FALSE), "str_imatch('Hello', 'Hello World')=" & BOOLEAN'image(str_imatch_result5) & " Expected=FALSE");
+ tbAssert((str_imatch_result6 = TRUE), "str_imatch('Hello', 'Hello\0\0\0')=" & BOOLEAN'image(str_imatch_result6) & " Expected=TRUE");
+
+ -- str_pos tests
+ -- str_ipos tests
+ -- str_find tests
+ -- str_ifind tests
+ -- str_replace tests
+ -- str_substr tests
+ -- str_ltrim tests
+ -- str_rtrim tests
+ -- str_trim tests
+ -- str_toLower tests
+ -- str_toUpper tests
+
+ -- simulation completed
+
+ -- Report overall simulation result
+ tbPrintResult;
+ wait;
+ end process;
+end;
diff --git a/testsuite/gna/bug019/PoC/tb/io/uart/uart_rx_tb.vhdl b/testsuite/gna/bug019/PoC/tb/io/uart/uart_rx_tb.vhdl
new file mode 100644
index 000000000..166f74ede
--- /dev/null
+++ b/testsuite/gna/bug019/PoC/tb/io/uart/uart_rx_tb.vhdl
@@ -0,0 +1,141 @@
+-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- ============================================================================
+-- Module: uart_rx_tb
+--
+-- Authors: Patrick Lehmann
+--
+-- Description:
+-- ------------------------------------
+-- Testbench for arith_counter_bcd
+--
+-- License:
+-- ============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- 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.
+-- ============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.vectors.all;
+use PoC.strings.all;
+use PoC.physical.all;
+use PoC.simulation.all;
+use PoC.uart.all;
+
+
+entity uart_rx_tb is
+end entity;
+
+
+architecture tb of uart_rx_tb is
+ constant CLOCK_FREQ : FREQ := 100 MHz;
+ constant BAUDRATE : BAUD := 4.2 MBd;
+
+ signal Clock : STD_LOGIC;
+ signal Reset : STD_LOGIC;
+
+ signal BitClock : STD_LOGIC;
+ signal BitClock_x8 : STD_LOGIC;
+
+ signal UART_RX : STD_LOGIC;
+
+ signal RX_Strobe : STD_LOGIC;
+ signal RX_Data : T_SLV_8;
+
+ function simGenerateWaveform_UART_Word(Data : T_SLV_8; Baudrate : BAUD := 115.200 kBd) return T_SIM_WAVEFORM_SL is
+ constant BIT_TIME : TIME := to_time(to_freq(Baudrate));
+ variable Result : T_SIM_WAVEFORM_SL(0 to 9) := (others => (Delay => BIT_TIME, Value => '-'));
+ begin
+ Result(0).Value := '0';
+ for i in Data'range loop
+ Result(i + 1).Value := Data(i);
+ end loop;
+ Result(9).Value := '1';
+ return Result;
+ end function;
+
+ function simGenerateWaveform_UART_Stream(Data : T_SLVV_8; Baudrate : BAUD := 115.200 kBd) return T_SIM_WAVEFORM_SL is
+ variable Result : T_SIM_WAVEFORM_SL(0 to (Data'length * 10) - 1);
+ begin
+ for i in Data'range loop
+ Result(i * 10 to ((i + 1) * 10) - 1) := simGenerateWaveform_UART_Word(Data(i), BAUDRATE);
+ end loop;
+ return Result;
+ end function;
+
+ constant DATA_STREAM : T_SLVV_8 := (x"12", x"45", x"FE", x"C4", x"02");
+
+begin
+ simGenerateClock(Clock, CLOCK_FREQ);
+ simGenerateWaveform(Reset, simGenerateWaveform_Reset(Pause => 50 ns));
+ p1f: if true generate
+ simGenerateWaveform(UART_RX, simGenerateWaveform_UART_Stream(DATA_STREAM, BAUDRATE), '1');
+ end generate;
+ p1t: if false generate
+ process
+ constant wf : T_SIM_WAVEFORM_SL := simGenerateWaveform_UART_Stream(DATA_STREAM, BAUDRATE);
+ begin
+ simGenerateWaveform(UART_RX, wf, '1');
+ end process;
+ end generate;
+
+ bclk : entity PoC.uart_bclk
+ generic map (
+ CLOCK_FREQ => CLOCK_FREQ,
+ BAUDRATE => BAUDRATE
+ )
+ port map (
+ clk => Clock,
+ rst => Reset,
+ bclk => BitClock,
+ bclk_x8 => BitClock_x8
+ );
+
+ RX : entity PoC.uart_rx
+ generic map (
+ OUT_REGS => FALSE
+ )
+ port map (
+ clk => Clock,
+ rst => Reset,
+ bclk_x8 => BitClock_x8,
+ dos => RX_Strobe,
+ dout => RX_Data,
+ rxd => UART_RX
+ );
+
+ process
+ begin
+ for i in DATA_STREAM'range loop
+ wait until rising_edge(Clock) and (RX_Strobe = '1');
+ report TIME'image(NOW) severity NOTE;
+ tbAssert((RX_Data = DATA_STREAM(i)), "Data Byte " & INTEGER'image(i) & " received: " & to_string(RX_Data, 'h') & " expected: " & to_string(DATA_STREAM(i), 'h'));
+ end loop;
+
+ wait for 1 us;
+ simStop;
+
+ tbPrintResult;
+ wait;
+ end process;
+
+end architecture;
diff --git a/testsuite/gna/bug019/repro.vhdl b/testsuite/gna/bug019/repro.vhdl
new file mode 100644
index 000000000..6005bd551
--- /dev/null
+++ b/testsuite/gna/bug019/repro.vhdl
@@ -0,0 +1,43 @@
+entity repro is
+end repro ;
+
+architecture arch of repro is
+ function get_str (l : natural) return string is
+ variable res : string (1 to l);
+ begin
+ for i in res'range loop
+ res (i) := character'val (96 + i);
+ end loop;
+ return res;
+ end get_str;
+
+ procedure check2 (msg : string) is
+ begin
+ report msg;
+ assert msg (1 to 10) = "abcdefghij" severity failure;
+ end check2;
+
+ procedure check1 (msg : string) is
+ begin
+ report "before check";
+ wait for 1 ns;
+ check2 (msg);
+ report "after check";
+ wait for 1 ns;
+ end check1;
+begin
+ process
+ begin
+ check1 (get_str (24));
+ wait;
+ end process;
+
+ process
+ begin
+ for i in 10 to 20 loop
+ report get_str (i);
+ wait for 1 ns;
+ end loop;
+ wait;
+ end process;
+end arch;
diff --git a/testsuite/gna/bug019/repro1.vhdl b/testsuite/gna/bug019/repro1.vhdl
new file mode 100644
index 000000000..0e939f84f
--- /dev/null
+++ b/testsuite/gna/bug019/repro1.vhdl
@@ -0,0 +1,51 @@
+entity repro1 is
+end repro1;
+
+architecture arch of repro1 is
+ type wf_el is record
+ t : time;
+ v : bit;
+ end record;
+
+ type wf_arr is array (natural range <>) of wf_el;
+
+ function get_wf (bv : bit_vector; p : time) return wf_arr is
+ variable res : wf_arr (bv'range);
+ variable t : time;
+ begin
+ t := 0 ns;
+ for i in bv'range loop
+ res (i) := (t => t, v => bv (i));
+ t := t + p;
+ end loop;
+ return res;
+ end get_wf;
+
+ procedure play_wf (signal s : out bit; wf : wf_arr; init : bit) is
+ begin
+ s <= init;
+ for i in wf'range loop
+ wait for wf (i).t;
+ s <= wf (i).v;
+ end loop;
+ wait;
+ end play_wf;
+
+ function get_str (l : natural; c : character) return string is
+ begin
+ return string'(1 to l => c);
+ end get_str;
+
+ signal o : bit;
+begin
+ play_wf (o, get_wf (b"0110100", 2 ns), '1');
+
+ process
+ begin
+ for i in 1 to 8 loop
+ report get_str (32 + 4 * i, character'val (64 + i));
+ wait for 2 ns;
+ end loop;
+ wait;
+ end process;
+end arch;
diff --git a/testsuite/gna/bug019/testsuite.sh b/testsuite/gna/bug019/testsuite.sh
new file mode 100755
index 000000000..020a4556a
--- /dev/null
+++ b/testsuite/gna/bug019/testsuite.sh
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+. ../../testenv.sh
+
+GHDL_FLAGS="--syn-binding -g"
+
+analyze --work=poc PoC/tb/common/my_config_ML505.vhdl
+analyze --work=poc PoC/tb/common/my_project.vhdl
+analyze --work=poc PoC/src/common/utils.vhdl
+analyze --work=poc PoC/src/common/config.vhdl
+analyze --work=poc PoC/src/common/strings.vhdl
+analyze --work=poc PoC/src/common/vectors.vhdl
+#analyze --work=poc PoC/src/common/board.vhdl
+analyze --work=poc PoC/src/common/physical.vhdl
+analyze --work=poc PoC/src/common/components.vhdl
+analyze --work=poc PoC/tb/common/simulation.v93.vhdl
+analyze --work=poc PoC/src/io/uart/uart.pkg.vhdl
+analyze --work=poc PoC/src/io/uart/uart_bclk.vhdl
+analyze --work=poc PoC/src/io/uart/uart_rx.vhdl
+analyze --work=test PoC/tb/io/uart/uart_rx_tb.vhdl
+elab_simulate --syn-binding --work=test uart_rx_tb --stop-time=15us
+
+clean poc
+clean test
+echo "Test successful"