diff options
author | Tristan Gingold | 2015-09-10 20:24:33 +0200 |
---|---|---|
committer | Tristan Gingold | 2015-09-10 20:24:33 +0200 |
commit | a67ae38eeedd5d0ca5a75b8174aed201e5c801ad (patch) | |
tree | 9e24b723ab5c8d0d46041433bb3154ffed4527b4 /testsuite/gna/bug019 | |
parent | 0e257fe7341a44f097ea282c0cbabda42f4ecc41 (diff) | |
download | ghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.tar.gz ghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.tar.bz2 ghdl-a67ae38eeedd5d0ca5a75b8174aed201e5c801ad.zip |
Add bug019 testcase.
Diffstat (limited to 'testsuite/gna/bug019')
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 0000000..2c619f6 --- /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 0000000..1252edc --- /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 0000000..6253628 --- /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 0000000..dda3cb0 --- /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 0000000..d0657e9 --- /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 0000000..58103ad --- /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 0000000..6c88d79 --- /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 0000000..a38604c --- /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 0000000..2d6829c --- /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 0000000..ec6058b --- /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 0000000..f96d0e0 --- /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 0000000..b5c3e9d --- /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 0000000..da26785 --- /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 0000000..e1c1c9e --- /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 0000000..01383ba --- /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 0000000..fe329fa --- /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 0000000..4095aa1 --- /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 0000000..1c0ab59 --- /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 0000000..dd4634b --- /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 0000000..90bb0ac --- /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 0000000..84d03a8 --- /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 0000000..227158a --- /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 0000000..22e6009 --- /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 0000000..30e3b5c --- /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 0000000..166f74e --- /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 0000000..6005bd5 --- /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 0000000..0e939f8 --- /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 0000000..020a455 --- /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" |