-- 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-2016 Technische Universitaet Dresden - Germany,
-- Chair of 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 [docs]config_private is
-- TODO:
-- ===========================================================================
subtype T_BOARD_STRING is string(1 to 16);
subtype T_BOARD_CONFIG_STRING is string(1 to 64);
subtype T_DEVICE_STRING is string(1 to 32);
-- 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_STRING; -- (NONE, SW, HW_CTS_RTS, HW_RTR_RTS)
BaudRate : T_BOARD_CONFIG_STRING; -- e.g. "115.2 kBd"
BaudRate_Max : T_BOARD_CONFIG_STRING;
end record;
-- Data structures to describe Ethernet
type T_BOARD_ETHERNET_DESC is record
IPStyle : T_BOARD_CONFIG_STRING;
RS_DataInterface : T_BOARD_CONFIG_STRING;
PHY_Device : T_BOARD_CONFIG_STRING;
PHY_DeviceAddress : std_logic_vector(7 downto 0);
PHY_DataInterface : T_BOARD_CONFIG_STRING;
PHY_ManagementInterface : T_BOARD_CONFIG_STRING;
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
BoardName : T_BOARD_CONFIG_STRING;
FPGADevice : T_BOARD_CONFIG_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 (natural range <>) of T_BOARD_INFO;
constant C_POC_NUL : character;
constant C_BOARD_STRING_EMPTY : T_BOARD_STRING;
constant C_BOARD_CONFIG_STRING_EMPTY : T_BOARD_CONFIG_STRING;
constant C_DEVICE_STRING_EMPTY : T_DEVICE_STRING;
constant C_BOARD_INFO_LIST : T_BOARD_INFO_VECTOR;
function [docs]conf(str : string) return T_BOARD_CONFIG_STRING;
end package;
package body config_private is
constant C_POC_NUL : character := '~';
constant C_BOARD_STRING_EMPTY : T_BOARD_STRING := (others => C_POC_NUL);
constant C_BOARD_CONFIG_STRING_EMPTY : T_BOARD_CONFIG_STRING := (others => C_POC_NUL);
constant C_DEVICE_STRING_EMPTY : T_DEVICE_STRING := (others => C_POC_NUL);
function conf(str : string) return T_BOARD_CONFIG_STRING is
constant ConstNUL : string(1 to 1) := (others => C_POC_NUL);
variable Result : string(1 to T_BOARD_CONFIG_STRING'length);
begin
Result := (others => C_POC_NUL);
if (str'length > 0) then
Result(1 to bound(T_BOARD_CONFIG_STRING'length, 1, str'length)) := ite((str'length > 0), str(1 to imin(T_BOARD_CONFIG_STRING'length, str'length)), ConstNUL);
end if;
return Result;
end function;
constant C_BOARD_ETHERNET_DESC_EMPTY : T_BOARD_ETHERNET_DESC := (
IPStyle => C_BOARD_CONFIG_STRING_EMPTY,
RS_DataInterface => C_BOARD_CONFIG_STRING_EMPTY,
PHY_Device => C_BOARD_CONFIG_STRING_EMPTY,
PHY_DeviceAddress => x"00",
PHY_DataInterface => C_BOARD_CONFIG_STRING_EMPTY,
PHY_ManagementInterface => C_BOARD_CONFIG_STRING_EMPTY
);
-- 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 := conf(FlowControl);
Result.BaudRate := conf(BaudRate);
Result.BaudRate_Max := ite((BaudRate_Max = ""), conf(BaudRate), conf(BaudRate_Max));
return Result;
end function;
-- IsDTE FlowControl BaudRate
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_DCE_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 := conf(IPStyle);
Result.RS_DataInterface := conf(RS_DataInt);
Result.PHY_Device := conf(PHY_Device);
Result.PHY_DeviceAddress := PHY_DevAddress;
Result.PHY_DataInterface := conf(PHY_DataInt);
Result.PHY_ManagementInterface := conf(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_SOFT_MII_LAN8720A : T_BOARD_ETHERNET_DESC := brd_CreateEthernet("SOFT", "MII", "SMSC_LAN8720A", x"01", "MII", "MDIO");
constant C_BOARD_ETH_NONE : T_BOARD_ETHERNET_DESC_VECTOR(T_BOARD_ETHERNET_DESC_INDEX) := (others => C_BOARD_ETH_EMPTY);
-- Board Descriptions
-- ===========================================================================
constant C_BOARD_INFO_LIST : T_BOARD_INFO_VECTOR := (
(
BoardName => conf("GENERIC"),
FPGADevice => conf("GENERIC"), -- GENERIC
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY
),
EthernetCount => 1
),
-- Altera boards
-- =========================================================================
(
BoardName => conf("DE0"),
FPGADevice => conf("EP3C16F484"), -- EP3C16F484
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("S2GXAV"),
FPGADevice => conf("EP2SGX90FF1508C3"), -- EP2SGX90FF1508C3
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("DE4"),
FPGADevice => conf("EP4SGX230KF40C2"), -- EP4SGX230KF40C2
UART => C_BOARD_UART_DCE_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
),(
BoardName => conf("DE5"),
FPGADevice => conf("EP5SGXEA7N2F45C2"), -- EP5SGXEA7N2F45C2
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),
-- Lattice boards
-- =========================================================================
(
BoardName => conf("ECP5 Versa"),
FPGADevice => conf("LFE5UM-45F-6BG381C"), -- LFE5UM-45F-6BG381C
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),
-- Microsemi boards
-- =========================================================================
(
BoardName => conf("SF2Plus"),
FPGADevice => conf("M2S010FG484"), -- M2S010FG484
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("Everest"),
FPGADevice => conf("MPF300T-1FCG1152"), -- MPF300T-1FCG1152
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),
-- Xilinx boards
-- =========================================================================
(
BoardName => conf("S3SK200"),
FPGADevice => conf("XC3S200-4FT256"), -- XC3S200-4FT256
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("S3SK1000"),
FPGADevice => conf("XC3S1000-4FT256"), -- XC2S1000-4FT256
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("S3ESK500"),
FPGADevice => conf("XC3S500E-4FG320"), -- XC3S500E-4FG320
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("S3ESK1600"),
FPGADevice => conf("XC3S1600E-4FG320"), -- XC3S1600E-4FG320
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("ATLYS"),
FPGADevice => conf("XC6SLX45-3CSG324"), -- XC6SLX45-3CSG324
UART => C_BOARD_UART_DCE_460800_NONE,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("ZC706"),
FPGADevice => conf("XC7Z045-2FFG900"), -- XC7Z045-2FFG900C
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("ZedBoard"),
FPGADevice => conf("XC7Z020-1CLG484"), -- XC7Z020-1CLG484
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),(
BoardName => conf("AC701"),
FPGADevice => conf("XC7A200T-2FBG676C"), -- XC7A200T-2FBG676C
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => (
0 => C_BOARD_ETH_SOFT_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("Nexys4"),
FPGADevice => conf("XC7A100T-1CG324C"), -- XC7A100T-1CG324C
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => (
0 => C_BOARD_ETH_SOFT_MII_LAN8720A,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("Nexys4DDR"),
FPGADevice => conf("XC7A100T-1CG324C"), -- XC7A100T-1CG324C
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => (
0 => C_BOARD_ETH_SOFT_MII_LAN8720A,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("KC705"),
FPGADevice => conf("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
),(
BoardName => conf("ML505"),
FPGADevice => conf("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
),(
BoardName => conf("ML506"),
FPGADevice => conf("XC5VSX50T-1FFG1136"), -- XC5VSX50T-1FFG1136
UART => C_BOARD_UART_DCE_115200_NONE,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("ML507"),
FPGADevice => conf("XC5VFX70T-1FFG1136"), -- XC5VFX70T-1FFG1136
UART => C_BOARD_UART_DCE_115200_NONE,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("XUPV5"),
FPGADevice => conf("XC5VLX110T-1FF1136"), -- XC5VLX110T-1FF1136
UART => C_BOARD_UART_DCE_115200_NONE,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("ML605"),
FPGADevice => conf("XC6VLX240T-1FF1156"), -- XC6VLX240T-1FF1156
UART => C_BOARD_UART_EMPTY,
Ethernet => (
0 => C_BOARD_ETH_HARD_GMII_88E1111,
others => C_BOARD_ETH_EMPTY),
EthernetCount => 1
),(
BoardName => conf("VC707"),
FPGADevice => conf("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
),(
BoardName => conf("VC709"),
FPGADevice => conf("XC7VX690T-2FFG1761C"), -- XC7VX690T-2FFG1761C
UART => C_BOARD_UART_DTE_921600_NONE,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
),
-- Custom Board (MUST BE LAST ONE)
-- =========================================================================
(
BoardName => conf("Custom"),
FPGADevice => conf("Device is unknown for a custom board"),
UART => C_BOARD_UART_EMPTY,
Ethernet => C_BOARD_ETH_NONE,
EthernetCount => 0
)
);
end package body;
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.config_private.all;
use PoC.utils.all;
package [docs]config is
constant PROJECT_DIR : string := MY_PROJECT_DIR;
constant OPERATING_SYSTEM : string := MY_OPERATING_SYSTEM;
constant POC_VERBOSE : boolean := MY_VERBOSE;
-- List of known FPGA / Chip vendors
-- ---------------------------------------------------------------------------
type T_VENDOR is (
VENDOR_UNKNOWN,
VENDOR_GENERIC,
VENDOR_ALTERA,
VENDOR_LATTICE,
VENDOR_MICROSEMI,
VENDOR_XILINX
);
-- List of known synthesis tool chains
-- ---------------------------------------------------------------------------
type T_SYNTHESIS_TOOL is (
SYNTHESIS_TOOL_UNKNOWN,
SYNTHESIS_TOOL_GENERIC,
SYNTHESIS_TOOL_ALTERA_QUARTUS2,
SYNTHESIS_TOOL_LATTICE_LSE,
SYNTHESIS_TOOL_SYNOPSIS,
SYNTHESIS_TOOL_XILINX_XST,
SYNTHESIS_TOOL_XILINX_VIVADO
);
-- List of known device families
-- ---------------------------------------------------------------------------
type T_DEVICE_FAMILY is (
DEVICE_FAMILY_UNKNOWN,
DEVICE_FAMILY_GENERIC,
-- Altera
DEVICE_FAMILY_ARRIA,
DEVICE_FAMILY_CYCLONE,
DEVICE_FAMILY_STRATIX,
-- Lattice
DEVICE_FAMILY_ICE,
DEVICE_FAMILY_MACHXO,
DEVICE_FAMILY_ECP,
-- Microsemi
DEVICE_FAMILY_SMARTFUSION,
DEVICE_FAMILY_POLARFIRE,
-- Xilinx
DEVICE_FAMILY_SPARTAN,
DEVICE_FAMILY_ZYNQ,
DEVICE_FAMILY_ARTIX,
DEVICE_FAMILY_KINTEX,
DEVICE_FAMILY_VIRTEX
);
type T_DEVICE_SERIES is (
DEVICE_SERIES_UNKNOWN,
DEVICE_SERIES_GENERIC,
-- Xilinx FPGA series
DEVICE_SERIES_7_SERIES,
DEVICE_SERIES_ULTRASCALE,
DEVICE_SERIES_ULTRASCALE_PLUS
);
-- List of known devices
-- ---------------------------------------------------------------------------
type T_DEVICE is (
DEVICE_UNKNOWN,
DEVICE_GENERIC,
-- Altera
DEVICE_MAX2, DEVICE_MAX10, -- Altera.Max
DEVICE_ARRIA1, DEVICE_ARRIA2, DEVICE_ARRIA5, DEVICE_ARRIA10, -- Altera.Arria
DEVICE_CYCLONE1, DEVICE_CYCLONE2, DEVICE_CYCLONE3, DEVICE_CYCLONE4, -- Altera.Cyclone
DEVICE_CYCLONE5, --
DEVICE_STRATIX1, DEVICE_STRATIX2, DEVICE_STRATIX3, DEVICE_STRATIX4, -- Altera.Stratix
DEVICE_STRATIX5, DEVICE_STRATIX10, --
-- Lattice
DEVICE_ICE40, DEVICE_ICE65, DEVICE_ICE5, -- Lattice.iCE
DEVICE_MACHXO, DEVICE_MACHXO2, -- Lattice.MachXO
DEVICE_ECP3, DEVICE_ECP4, DEVICE_ECP5, -- Lattice.ECP
-- Microsemi
DEVICE_SMARTFUSION2, -- Microsemi.SmartFusion
DEVICE_POLARFIRE, -- Microsemi.PolarFire
-- Xilinx
DEVICE_SPARTAN3, DEVICE_SPARTAN6, -- Xilinx.Spartan
DEVICE_ZYNQ7, DEVICE_ZYNQ_ULTRA_PLUS, -- Xilinx.Zynq
DEVICE_ARTIX7, -- Xilinx.Artix
DEVICE_KINTEX7, DEVICE_KINTEX_ULTRA, DEVICE_KINTEX_ULTRA_PLUS, -- Xilinx.Kintex
DEVICE_VIRTEX4, DEVICE_VIRTEX5, DEVICE_VIRTEX6, DEVICE_VIRTEX7, -- Xilinx.Virtex
DEVICE_VIRTEX_ULTRA, DEVICE_VIRTEX_ULTRA_PLUS --
);
-- List of known device subtypes
-- ---------------------------------------------------------------------------
type T_DEVICE_SUBTYPE is (
DEVICE_SUBTYPE_NONE,
DEVICE_SUBTYPE_GENERIC,
-- Altera
DEVICE_SUBTYPE_E,
DEVICE_SUBTYPE_GS,
DEVICE_SUBTYPE_GX,
DEVICE_SUBTYPE_GT,
-- Lattice
DEVICE_SUBTYPE_U,
DEVICE_SUBTYPE_UM,
-- Microsemi
-- 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
);
-- List of known transceiver (sub-)types
-- ---------------------------------------------------------------------------
type T_TRANSCEIVER is (
TRANSCEIVER_NONE,
TRANSCEIVER_GENERIC,
-- TODO: add more? Altera transceivers
-- Altera transceivers
TRANSCEIVER_GXB, -- Altera GXB transceiver
--Lattice transceivers
TRANSCEIVER_MGT, -- Lattice transceiver
-- Xilinx transceivers
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, TRANSCEIVER_GTHE3, TRANSCEIVER_GTHE4, -- Xilinx GTH transceivers
TRANSCEIVER_GTZ, -- Xilinx GTZ transceivers
TRANSCEIVER_GTY -- Xilinx GTY transceivers
);
-- Properties of an FPGA architecture
-- ===========================================================================
type T_DEVICE_INFO is record
Vendor : T_VENDOR;
Device : T_DEVICE;
DevFamily : T_DEVICE_FAMILY;
DevGeneration : natural;
DevNumber : natural;
DevSubType : T_DEVICE_SUBTYPE;
DevSeries : T_DEVICE_SERIES;
TransceiverType : T_TRANSCEIVER;
LUT_FanIn : positive;
end record;
-- Functions extracting board and PCB properties from "MY_BOARD"
-- which is declared in package "my_config".
-- ===========================================================================
function [docs]BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY) return natural;
function [docs]BOARD_INFO(BoardConfig : string := C_BOARD_STRING_EMPTY) return T_BOARD_INFO;
function [docs]BOARD_NAME(BoardConfig : string := C_BOARD_STRING_EMPTY) return string;
function [docs]BOARD_DEVICE(BoardConfig : string := C_BOARD_STRING_EMPTY) return string;
function [docs]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 [docs]VENDOR(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_VENDOR;
function [docs]SYNTHESIS_TOOL(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_SYNTHESIS_TOOL;
function [docs]DEVICE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE;
function [docs]DEVICE_FAMILY(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_FAMILY;
function [docs]DEVICE_SUBTYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_SUBTYPE;
function [docs]DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_SERIES;
function [docs]DEVICE_GENERATION(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural;
function [docs]DEVICE_NUMBER(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural;
function [docs]TRANSCEIVER_TYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_TRANSCEIVER;
function [docs]LUT_FANIN(DeviceString : string := C_DEVICE_STRING_EMPTY) return positive;
function [docs]DEVICE_INFO(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_INFO;
-- Convert T_DEVICE to string representation as required by "altera_mf" library
-- ===========================================================================
function [docs]getAlteraDeviceName (device : T_DEVICE) return string;
-- force FSM to predefined encoding in debug mode
-- ===========================================================================
function [docs]getFSMEncoding_gray(debug : boolean) return string;
end package;
package body config 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;
-- 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
for i in str'range loop
if str(i) = C_POC_NUL then
return str(str'low to i-1);
end if;
end loop;
return str;
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 0 to len-1 loop
chr1 := str1(str1'low + i);
chr2 := str2(str2'low + i);
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,
if ((str1'length = len) and (str2'length = len)) then -- both strings are fully consumed and equal
return TRUE;
elsif (str1'length > len) then
return (str1(str1'low + len) = C_POC_NUL); -- str1 is longer, but str_length equals len
else
return (str2(str2'low + len) = C_POC_NUL); -- str2 is longer, but str_length equals len
end if;
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;
-- private functions required by board description
-- ModelSim requires that this functions is defined before it is used below.
-- ===========================================================================
function getLocalDeviceString(DeviceString : string) return string is
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 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 not str_imatch(DeviceString, "None") then
Result(1 to bound(T_DEVICE_STRING'length, 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 not str_imatch(MY_DEVICE, "None") then
Result(1 to bound(T_DEVICE_STRING'length, 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 bound(T_DEVICE_STRING'length, 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;
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 not chr_isDigit(str(i)) then
return 0;
end if;
Result := (Result * 10) + (character'pos(str(i)) - character'pos('0'));
end loop;
return Result;
end function;
-- Public functions
-- ===========================================================================
-- TODO: comment
function BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY) return natural is
constant MY_BRD : T_BOARD_CONFIG_STRING := ite((BoardConfig /= C_BOARD_STRING_EMPTY), conf(BoardConfig), conf(MY_BOARD));
constant BOARD_NAME : string := str_trim(MY_BRD);
begin
if POC_VERBOSE then report "PoC configuration: Used board is '" & BOARD_NAME & "'" severity NOTE; end if;
for i in C_BOARD_INFO_LIST'range loop
if str_imatch(BOARD_NAME, C_BOARD_INFO_LIST(i).BoardName) then
return i;
end if;
end loop;
report "Unknown board name in MY_BOARD = " & MY_BRD & "." severity failure;
return C_BOARD_INFO_LIST'high;
end function;
function BOARD_INFO(BoardConfig : string := C_BOARD_STRING_EMPTY) return T_BOARD_INFO is
constant BRD : natural := BOARD(BoardConfig);
begin
return C_BOARD_INFO_LIST(BRD);
end function;
-- TODO: comment
function BOARD_NAME(BoardConfig : string := C_BOARD_STRING_EMPTY) return string is
constant BRD : natural := BOARD(BoardConfig);
begin
return str_trim(C_BOARD_INFO_LIST(BRD).BoardName);
end function;
-- TODO: comment
function BOARD_DEVICE(BoardConfig : string := C_BOARD_STRING_EMPTY) return string is
constant BRD : natural := 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 : natural := 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_STR2 : string(1 to 2) := MY_DEV(1 to 2); -- TODO: test if alias declarations also work out on all platforms
constant VEN_STR3 : string(1 to 3) := MY_DEV(1 to 3); -- TODO: test if alias declarations also work out on all platforms
begin
case VEN_STR2 is
when "GE" => return VENDOR_GENERIC;
when "EP" => return VENDOR_ALTERA;
when "XC" => return VENDOR_XILINX;
when others => null;
end case;
case VEN_STR3 is
when "MPF" => return VENDOR_MICROSEMI; -- PolarFire devices
when "iCE" => return VENDOR_LATTICE; -- iCE devices
when "LCM" => return VENDOR_LATTICE; -- MachXO device
when "LFE" => return VENDOR_LATTICE; -- ECP devices
when others => report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
return VENDOR_UNKNOWN;
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_GENERIC =>
return SYNTHESIS_TOOL_GENERIC;
when VENDOR_ALTERA =>
return SYNTHESIS_TOOL_ALTERA_QUARTUS2;
when VENDOR_LATTICE =>
return SYNTHESIS_TOOL_LATTICE_LSE;
--return SYNTHESIS_TOOL_SYNOPSIS;
when VENDOR_MICROSEMI =>
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;
when others =>
return SYNTHESIS_TOOL_UNKNOWN;
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); -- TODO: test if alias declarations also work out on all platforms
begin
case VEN is
when VENDOR_GENERIC =>
if (MY_DEV(1 to 7) = "GENERIC") then return DEVICE_GENERIC;
else report "Unknown Generic device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
end if;
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_LATTICE =>
if (MY_DEV(1 to 6) = "LCMX02") then return DEVICE_MACHXO2;
elsif (MY_DEV(1 to 5) = "LCMX0") then return DEVICE_MACHXO;
elsif (MY_DEV(1 to 5) = "iCE40") then return DEVICE_ICE40;
elsif (MY_DEV(1 to 5) = "iCE65") then return DEVICE_ICE65;
elsif (MY_DEV(1 to 4) = "iCE5") then return DEVICE_ICE5;
elsif (MY_DEV(1 to 4) = "LFE3") then return DEVICE_ECP3;
elsif (MY_DEV(1 to 4) = "LFE4") then return DEVICE_ECP4;
elsif (MY_DEV(1 to 4) = "LFE5") then return DEVICE_ECP5;
else report "Unknown Lattice device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
end if;
when VENDOR_MICROSEMI =>
report "Unknown Microsemi device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
when VENDOR_XILINX =>
case DEV_STR is
when "7A" => return DEVICE_ARTIX7;
when "7K" => return DEVICE_KINTEX7;
when "KU" => return DEVICE_KINTEX_ULTRA;
when "3S" => return DEVICE_SPARTAN3;
when "6S" => return DEVICE_SPARTAN6;
when "4V" => return DEVICE_VIRTEX4;
when "5V" => return DEVICE_VIRTEX5;
when "6V" => return DEVICE_VIRTEX6;
when "7V" => return DEVICE_VIRTEX7;
when "VU" => return DEVICE_VIRTEX_ULTRA;
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;
end case;
return DEVICE_UNKNOWN;
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_GENERIC =>
return DEVICE_FAMILY_GENERIC;
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_LATTICE =>
case FAM_CHAR is
--when 'M' => return DEVICE_FAMILY_MACHXO;
when 'E' => return DEVICE_FAMILY_ECP;
when others => report "Unknown Lattice 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;
end case;
return DEVICE_FAMILY_UNKNOWN;
end function;
-- some devices share some common features: e.g. XADC, BlockRAM, ...
function DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_SERIES is
constant MY_DEV : string(1 to 32) := getLocalDeviceString(DeviceString);
constant DEV : T_DEVICE := DEVICE(DeviceString);
begin
case DEV is
when DEVICE_GENERIC =>
return DEVICE_SERIES_GENERIC;
-- all Xilinx ****7 devices
when DEVICE_ARTIX7 | DEVICE_KINTEX7 | DEVICE_VIRTEX7 | DEVICE_ZYNQ7 =>
return DEVICE_SERIES_7_SERIES;
-- all Xilinx ****UltraScale devices
when DEVICE_KINTEX_ULTRA | DEVICE_VIRTEX_ULTRA =>
return DEVICE_SERIES_ULTRASCALE;
-- all Xilinx ****UltraScale+ devices
when DEVICE_KINTEX_ULTRA_PLUS | DEVICE_VIRTEX_ULTRA_PLUS | DEVICE_ZYNQ_ULTRA_PLUS =>
return DEVICE_SERIES_ULTRASCALE_PLUS;
when others =>
return DEVICE_SERIES_UNKNOWN;
end case;
end function;
function DEVICE_GENERATION(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural is
constant SERIES : T_DEVICE_SERIES := DEVICE_SERIES(DeviceString);
begin
if SERIES = DEVICE_SERIES_7_SERIES then
return 7;
else
return 0;
end if;
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_GENERIC => return 0;
when VENDOR_ALTERA => return extractFirstNumber(MY_DEV(5 to MY_DEV'high));
when VENDOR_LATTICE => return extractFirstNumber(MY_DEV(6 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 0;
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); -- WORKAROUND: for GHDL
begin
case DEV is
when DEVICE_GENERIC => return DEVICE_SUBTYPE_GENERIC;
-- TODO: extract Arria GX subtype
when DEVICE_ARRIA1 =>
report "TODO: parse Arria device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
-- TODO: extract ArriaII GX,GZ subtype
when DEVICE_ARRIA2 =>
report "TODO: parse ArriaII device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
-- TODO: extract ArriaV GX, GT, SX, GZ subtype
when DEVICE_ARRIA5 =>
report "TODO: parse ArriaV device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
-- TODO: extract Arria10 GX, GT, SX subtype
when DEVICE_ARRIA10 =>
report "TODO: parse Arria10 device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
-- Altera Cyclon I, II, III, IV, V devices have no subtype
when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 | DEVICE_CYCLONE4 |
DEVICE_CYCLONE5 => return DEVICE_SUBTYPE_NONE;
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 IV subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
end if;
-- TODO: extract StratixV subtype
when DEVICE_STRATIX5 =>
report "TODO: parse Stratix V device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
when DEVICE_ECP5 =>
if (DEV_SUB_STR(1) = 'U') then return DEVICE_SUBTYPE_U;
elsif DEV_SUB_STR = "UM" then return DEVICE_SUBTYPE_UM;
else report "Unknown Lattice ECP5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
end if;
when DEVICE_SPARTAN3 =>
report "TODO: parse Spartan3 / Spartan3E / Spartan3AN device subtype." severity failure;
return DEVICE_SUBTYPE_NONE;
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_VIRTEX4 =>
report "Unkown Virtex 4" severity failure;
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_KINTEX_ULTRA => return DEVICE_SUBTYPE_NONE;
when DEVICE_KINTEX_ULTRA_PLUS => return DEVICE_SUBTYPE_NONE;
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 DEVICE_VIRTEX_ULTRA => return DEVICE_SUBTYPE_NONE;
when DEVICE_VIRTEX_ULTRA_PLUS => return DEVICE_SUBTYPE_NONE;
when DEVICE_ZYNQ7 => return DEVICE_SUBTYPE_NONE;
when DEVICE_ZYNQ_ULTRA_PLUS => return DEVICE_SUBTYPE_NONE;
when others => report "Device sub-type is unknown for the given device." severity failure;
end case;
return DEVICE_SUBTYPE_NONE;
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);
constant SERIES : T_DEVICE_SERIES := DEVICE_SERIES(DeviceString);
begin
case SERIES is
when DEVICE_SERIES_GENERIC => return 6;
when DEVICE_SERIES_7_SERIES | DEVICE_SERIES_ULTRASCALE |
DEVICE_SERIES_ULTRASCALE_PLUS => return 6;
when others => null;
end case;
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_ECP5 => return 4;
when DEVICE_SPARTAN3 => return 4;
when DEVICE_SPARTAN6 => return 6;
when DEVICE_VIRTEX4 | DEVICE_VIRTEX5 | DEVICE_VIRTEX6 => return 6;
when others => report "LUT fan-in is unknown for the given device, using default (4)." severity failure;
return 4;
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_GENERIC => return TRANSCEIVER_GENERIC;
when DEVICE_MAX2 | DEVICE_MAX10 => return TRANSCEIVER_NONE; -- Altera MAX II, 10 devices have no transceivers
when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 => return TRANSCEIVER_NONE; -- Altera Cyclon I, II, III devices have no transceivers
when DEVICE_STRATIX2 => return TRANSCEIVER_GXB;
when DEVICE_STRATIX4 => return TRANSCEIVER_GXB;
--when DEVICE_STRATIX5 => return TRANSCEIVER_GXB;
when DEVICE_ECP5 => return TRANSCEIVER_MGT;
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_VIRTEX4 =>
report "Unknown Virtex-4" severity failure;
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_ZYNQ7 =>
case DEV_NUM is
when 10 | 20 => return TRANSCEIVER_NONE;
when 15 => return TRANSCEIVER_GTPE2;
when others => return TRANSCEIVER_GTXE2;
end case;
when others => report "Unknown device." severity failure;
end case;
return TRANSCEIVER_NONE;
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.DevSubType := DEVICE_SUBTYPE(DeviceString);
Result.DevSeries := DEVICE_SERIES(DeviceString);
Result.DevGeneration := DEVICE_GENERATION(DeviceString);
Result.DevNumber := DEVICE_NUMBER(DeviceString);
Result.TransceiverType := TRANSCEIVER_TYPE(DeviceString);
Result.LUT_FanIn := LUT_FANIN(DeviceString);
return Result;
end function;
-- Convert T_DEVICE to string representation as required by "altera_mf" library
function getAlteraDeviceName (device : T_DEVICE) return string is
begin
case device is
when DEVICE_ARRIA1 => return "Arria";
when DEVICE_ARRIA2 => return "Arria II";
when DEVICE_ARRIA5 => return "Arria V";
when DEVICE_ARRIA10 => return "Arria 10";
when DEVICE_CYCLONE1 => return "Cyclone";
when DEVICE_CYCLONE2 => return "Cyclone II";
when DEVICE_CYCLONE3 => return "Cyclone III";
when DEVICE_CYCLONE4 => return "Cyclone IV";
when DEVICE_CYCLONE5 => return "Cyclone V";
when DEVICE_STRATIX1 => return "Stratix";
when DEVICE_STRATIX2 => return "Stratix II";
when DEVICE_STRATIX3 => return "Stratix III";
when DEVICE_STRATIX4 => return "Stratix IV";
when DEVICE_STRATIX5 => return "Stratix V";
when DEVICE_STRATIX10 => return "Stratix 10";
when others =>
report "Unknown Altera device." severity failure;
return "";
end case;
end function;
-- force FSM to predefined encoding in debug mode
function getFSMEncoding_gray(debug : boolean) return string is
begin
if debug then
return "gray";
else
case VENDOR is
when VENDOR_ALTERA => return "default";
--when VENDOR_LATTICE => return "default";
when VENDOR_XILINX => return "auto";
when others => report "Unknown vendor." severity failure;
return "";
end case;
end if;
end function;
end package body;