-- 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;