1-- EMACS settings: -*-  tab-width: 2; indent-tabs-mode: t -*-
2-- vim: tabstop=2:shiftwidth=2:noexpandtab
3-- kate: tab-width 2; replace-tabs off; indent-width 2;
4--
5-- ============================================================================
6-- Authors:					Thomas B. Preusser
7--									Martin Zabel
8--									Patrick Lehmann
9--
10-- Package:					Global configuration settings.
11--
12-- Description:
13-- ------------------------------------
14--		This file evaluates the settings declared in the project specific package my_config.
15--		See also template file my_config.vhdl.template.
16--
17-- License:
18-- ============================================================================
19-- Copyright 2007-2015 Technische Universitaet Dresden - Germany,
20--										 Chair for VLSI-Design, Diagnostics and Architecture
21--
22-- Licensed under the Apache License, Version 2.0 (the "License");
23-- you may not use this file except in compliance with the License.
24-- You may obtain a copy of the License at
25--
26--		http://www.apache.org/licenses/LICENSE-2.0
27--
28-- Unless required by applicable law or agreed to in writing, software
29-- distributed under the License is distributed on an "AS IS" BASIS,
30-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31-- See the License for the specific language governing permissions and
32-- limitations under the License.
33-- ============================================================================
34
35library	IEEE;
36use			IEEE.std_logic_1164.all;
37use			IEEE.numeric_std.all;
38
39library PoC;
40use			PoC.utils.all;
41
42package config_private is
43	-- TODO:
44	-- ===========================================================================
45	subtype T_BOARD_STRING					is STRING(1 to 16);
46	subtype T_BOARD_CONFIG_STRING		is STRING(1 to 64);
47	subtype T_DEVICE_STRING					is STRING(1 to 32);
48
49	-- Data structures to describe UART / RS232
50	type T_BOARD_UART_DESC is record
51		IsDTE											: BOOLEAN;									-- Data terminal Equipment (e.g. PC, Printer)
52		FlowControl								: T_BOARD_CONFIG_STRING;		-- (NONE, SW, HW_CTS_RTS, HW_RTR_RTS)
53		BaudRate									: T_BOARD_CONFIG_STRING;		-- e.g. "115.2 kBd"
54		BaudRate_Max							: T_BOARD_CONFIG_STRING;
55	end record;
56
57	-- Data structures to describe Ethernet
58	type T_BOARD_ETHERNET_DESC is record
59		IPStyle										: T_BOARD_CONFIG_STRING;
60		RS_DataInterface					: T_BOARD_CONFIG_STRING;
61		PHY_Device								: T_BOARD_CONFIG_STRING;
62		PHY_DeviceAddress					: STD_LOGIC_VECTOR(7 downto 0);
63		PHY_DataInterface					: T_BOARD_CONFIG_STRING;
64		PHY_ManagementInterface		: T_BOARD_CONFIG_STRING;
65	end record;
66
67	subtype T_BOARD_ETHERNET_DESC_INDEX		is NATURAL range 0 to 7;
68	type		T_BOARD_ETHERNET_DESC_VECTOR	is array(NATURAL range <>) of T_BOARD_ETHERNET_DESC;
69
70	-- Data structures to describe a board layout
71	type T_BOARD_INFO is record
72		BoardName			: T_BOARD_CONFIG_STRING;
73		FPGADevice		: T_BOARD_CONFIG_STRING;
74		UART					: T_BOARD_UART_DESC;
75		Ethernet			: T_BOARD_ETHERNET_DESC_VECTOR(T_BOARD_ETHERNET_DESC_INDEX);
76		EthernetCount	: T_BOARD_ETHERNET_DESC_INDEX;
77	end record;
78
79	type T_BOARD_INFO_VECTOR	is array (natural range <>) of T_BOARD_INFO;
80
81	constant C_POC_NUL										: CHARACTER;
82	constant C_BOARD_STRING_EMPTY					: T_BOARD_STRING;
83	constant C_BOARD_CONFIG_STRING_EMPTY	: T_BOARD_CONFIG_STRING;
84	constant C_DEVICE_STRING_EMPTY				: T_DEVICE_STRING;
85	CONSTANT C_BOARD_INFO_LIST						: T_BOARD_INFO_VECTOR;
86
87	function conf(str : string) return T_BOARD_CONFIG_STRING;
88end package;
89
90
91package body config_private is
92	constant C_POC_NUL										: CHARACTER								:= '~';
93	constant C_BOARD_STRING_EMPTY					: T_BOARD_STRING					:= (others => C_POC_NUL);
94	constant C_BOARD_CONFIG_STRING_EMPTY	: T_BOARD_CONFIG_STRING		:= (others => C_POC_NUL);
95	constant C_DEVICE_STRING_EMPTY				: T_DEVICE_STRING					:= (others => C_POC_NUL);
96
97	function conf(str : string) return T_BOARD_CONFIG_STRING is
98		constant ConstNUL		: STRING(1 to 1)				:= (others => C_POC_NUL);
99		variable Result			: STRING(1 to T_BOARD_CONFIG_STRING'length);
100	begin
101		Result := (others => C_POC_NUL);
102		if (str'length > 0) then
103			Result(1 to imin(T_BOARD_CONFIG_STRING'length, imax(1, str'length))) := ite((str'length > 0), str(1 to imin(T_BOARD_CONFIG_STRING'length, str'length)), ConstNUL);
104		end if;
105		return Result;
106	end function;
107
108	constant C_BOARD_ETHERNET_DESC_EMPTY	: T_BOARD_ETHERNET_DESC		:= (
109		IPStyle										=> C_BOARD_CONFIG_STRING_EMPTY,
110		RS_DataInterface					=> C_BOARD_CONFIG_STRING_EMPTY,
111		PHY_Device								=> C_BOARD_CONFIG_STRING_EMPTY,
112		PHY_DeviceAddress					=> x"00",
113		PHY_DataInterface					=> C_BOARD_CONFIG_STRING_EMPTY,
114		PHY_ManagementInterface		=> C_BOARD_CONFIG_STRING_EMPTY
115	);
116
117	-- predefined UART descriptions
118	function brd_CreateUART(IsDTE : BOOLEAN; FlowControl : STRING; BaudRate : STRING; BaudRate_Max : STRING := "") return T_BOARD_UART_DESC is
119		variable Result			: T_BOARD_UART_DESC;
120	begin
121		Result.IsDTE				:= IsDTE;
122		Result.FlowControl	:= conf(FlowControl);
123		Result.BaudRate			:= conf(BaudRate);
124		Result.BaudRate_Max	:= ite((BaudRate_Max = ""), conf(BaudRate), conf(BaudRate_Max));
125		return Result;
126	end function;
127
128	--																																					IsDTE		FlowControl			BaudRate
129	constant C_BOARD_UART_EMPTY							: T_BOARD_UART_DESC	:= brd_CreateUART(TRUE,		"NONE",				"0 Bd");
130	constant C_BOARD_UART_DTE_115200_NONE		: T_BOARD_UART_DESC	:= brd_CreateUART(TRUE,		"NONE",				"115.2 kBd");
131	constant C_BOARD_UART_DCE_115200_NONE		: T_BOARD_UART_DESC	:= brd_CreateUART(FALSE,	"NONE",				"115.2 kBd");
132	constant C_BOARD_UART_DCE_115200_HWCTS	: T_BOARD_UART_DESC	:= brd_CreateUART(FALSE,	"HW_CTS_RTS",	"115.2 kBd");
133	constant C_BOARD_UART_DCE_460800_NONE		: T_BOARD_UART_DESC	:= brd_CreateUART(FALSE,	"NONE",				"460.8 kBd");
134	constant C_BOARD_UART_DTE_921600_NONE		: T_BOARD_UART_DESC	:= brd_CreateUART(FALSE,	"NONE",				"921.6 kBd");
135
136	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
137		variable Result		: T_BOARD_ETHERNET_DESC;
138	begin
139		Result.IPStyle									:= conf(IPStyle);
140		Result.RS_DataInterface					:= conf(RS_DataInt);
141		Result.PHY_Device								:= conf(PHY_Device);
142		Result.PHY_DeviceAddress				:= PHY_DevAddress;
143		Result.PHY_DataInterface				:= conf(PHY_DataInt);
144		Result.PHY_ManagementInterface	:= conf(PHY_MgntInt);
145		return Result;
146	end function;
147
148	constant C_BOARD_ETH_EMPTY							: T_BOARD_ETHERNET_DESC		:= brd_CreateEthernet("", "", "", x"00", "", "");
149	constant C_BOARD_ETH_SOFT_GMII_88E1111	: T_BOARD_ETHERNET_DESC		:= brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"07", "GMII", "MDIO");
150	constant C_BOARD_ETH_HARD_GMII_88E1111	: T_BOARD_ETHERNET_DESC		:= brd_CreateEthernet("HARD", "GMII", "MARVEL_88E1111", x"07", "GMII", "MDIO");
151	constant C_BOARD_ETH_SOFT_SGMII_88E1111	: T_BOARD_ETHERNET_DESC		:= brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"07", "SGMII", "MDIO_OVER_IIC");
152
153	constant C_BOARD_ETH_NONE		: T_BOARD_ETHERNET_DESC_VECTOR(T_BOARD_ETHERNET_DESC_INDEX)	:= (others => C_BOARD_ETH_EMPTY);
154
155
156	-- Board Descriptions
157	-- ===========================================================================
158	CONSTANT C_BOARD_INFO_LIST		: T_BOARD_INFO_VECTOR		:= (
159		-- Altera boards
160		-- =========================================================================
161		(
162			BoardName =>			conf("DE0"),
163			FPGADevice =>			conf("EP3C16F484"),										-- EP3C16F484
164			UART =>						C_BOARD_UART_EMPTY,
165			Ethernet =>				C_BOARD_ETH_NONE,
166			EthernetCount =>	0
167		),(
168			BoardName =>			conf("S2GXAV"),
169			FPGADevice =>			conf("EP2SGX90FF1508C3"),							-- EP2SGX90FF1508C3
170			UART =>						C_BOARD_UART_EMPTY,
171			Ethernet =>				C_BOARD_ETH_NONE,
172			EthernetCount =>	0
173		),(
174			BoardName =>			conf("DE4"),
175			FPGADevice =>			conf("EP4SGX230KF40C2"),							-- EP4SGX230KF40C2
176			UART =>						C_BOARD_UART_DCE_460800_NONE,
177			Ethernet => (
178				0 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"00", "RGMII", "MDIO"),
179				1 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"01", "RGMII", "MDIO"),
180				2 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"02", "RGMII", "MDIO"),
181				3 => brd_CreateEthernet("SOFT", "GMII", "MARVEL_88E1111", x"03", "RGMII", "MDIO"),
182				others => C_BOARD_ETH_EMPTY
183			),
184			EthernetCount =>	4
185		),(
186			BoardName =>			conf("DE5"),
187			FPGADevice =>			conf("EP5SGXEA7N2F45C2"),							-- EP5SGXEA7N2F45C2
188			UART =>						C_BOARD_UART_EMPTY,
189			Ethernet =>				C_BOARD_ETH_NONE,
190			EthernetCount =>	0
191		),
192		-- Lattice boards
193		-- =========================================================================
194		(
195			BoardName =>			conf("ECP5 Versa"),
196			FPGADevice => 		conf("LFE5UM-45F-6BG381C"),						-- LFE5UM-45F-6BG381C
197			UART =>						C_BOARD_UART_EMPTY,
198			Ethernet =>				C_BOARD_ETH_NONE,
199			EthernetCount =>	0
200		),
201		-- Xilinx boards
202		-- =========================================================================
203		(
204			BoardName =>			conf("S3SK200"),
205			FPGADevice => 		conf("XC3S200FT256"),									-- XC2S200FT256
206			UART =>						C_BOARD_UART_EMPTY,
207			Ethernet =>				C_BOARD_ETH_NONE,
208			EthernetCount =>	0
209		),(
210			BoardName =>			conf("S3SK1000"),
211			FPGADevice =>			conf("XC3S1000FT256"),								-- XC2S200FT256
212			UART =>						C_BOARD_UART_EMPTY,
213			Ethernet =>				C_BOARD_ETH_NONE,
214			EthernetCount =>	0
215		),(
216			BoardName =>			conf("S3ESK500"),
217			FPGADevice =>			conf("XC3S500EFT256"),								-- XC2S200FT256
218			UART =>						C_BOARD_UART_EMPTY,
219			Ethernet =>				C_BOARD_ETH_NONE,
220			EthernetCount =>	0
221		),(
222			BoardName =>			conf("S3ESK1600"),
223			FPGADevice =>			conf("XC3S1600EFT256"),								-- XC2S200FT256
224			UART =>						C_BOARD_UART_EMPTY,
225			Ethernet =>				C_BOARD_ETH_NONE,
226			EthernetCount =>	0
227		),(
228			BoardName =>			conf("ATLYS"),
229			FPGADevice =>			conf("XC6SLX45-3CSG324"),							-- XC6SLX45-3CSG324
230			UART =>						C_BOARD_UART_DCE_460800_NONE,
231			Ethernet =>	(
232				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
233				others =>	C_BOARD_ETH_EMPTY),
234			EthernetCount =>	1
235		),(
236			BoardName =>			conf("ZC706"),
237			FPGADevice =>			conf("XC7Z045-2FFG900"),						-- XC7K325T-2FFG900C
238			UART =>						C_BOARD_UART_DTE_921600_NONE,
239			Ethernet =>				C_BOARD_ETH_NONE,
240			EthernetCount =>	0
241		),(
242			BoardName =>			conf("KC705"),
243			FPGADevice =>			conf("XC7K325T-2FFG900C"),						-- XC7K325T-2FFG900C
244			UART =>						C_BOARD_UART_DTE_921600_NONE,
245			Ethernet => (
246				0 =>			C_BOARD_ETH_SOFT_GMII_88E1111,
247				others =>	C_BOARD_ETH_EMPTY),
248			EthernetCount =>	1
249		),(
250			BoardName =>			conf("ML505"),
251			FPGADevice =>			conf("XC5VLX50T-1FF1136"),						-- XC5VLX50T-1FF1136
252			UART =>						C_BOARD_UART_DCE_115200_NONE,
253			Ethernet => (
254				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
255				others =>	C_BOARD_ETH_EMPTY),
256			EthernetCount =>	1
257		),(
258			BoardName =>			conf("ML506"),
259			FPGADevice =>			conf("XC5VSX50T-1FFG1136"),						-- XC5VSX50T-1FFG1136
260			UART =>						C_BOARD_UART_DCE_115200_NONE,
261			Ethernet => (
262				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
263				others =>	C_BOARD_ETH_EMPTY),
264			EthernetCount =>	1
265		),(
266			BoardName =>			conf("ML507"),
267			FPGADevice =>			conf("XC5VFX70T-1FFG1136"),						-- XC5VFX70T-1FFG1136
268			UART =>						C_BOARD_UART_DCE_115200_NONE,
269			Ethernet => (
270				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
271				others =>	C_BOARD_ETH_EMPTY),
272			EthernetCount =>	1
273		),(
274			BoardName =>			conf("XUPV5"),
275			FPGADevice =>			conf("XC5VLX110T-1FF1136"),						-- XC5VLX110T-1FF1136
276			UART =>						C_BOARD_UART_DCE_115200_NONE,
277			Ethernet => (
278				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
279				others =>	C_BOARD_ETH_EMPTY),
280			EthernetCount =>	1
281		),(
282			BoardName =>			conf("ML605"),
283			FPGADevice =>			conf("XC6VLX240T-1FF1156"),						-- XC6VLX240T-1FF1156
284			UART =>						C_BOARD_UART_EMPTY,
285			Ethernet => (
286				0 =>			C_BOARD_ETH_HARD_GMII_88E1111,
287				others =>	C_BOARD_ETH_EMPTY),
288			EthernetCount =>	1
289		),(
290			BoardName =>			conf("VC707"),
291			FPGADevice =>			conf("XC7VX485T-2FFG1761C"),					-- XC7VX485T-2FFG1761C
292			UART =>						C_BOARD_UART_DTE_921600_NONE,
293			Ethernet => (
294				0 =>			C_BOARD_ETH_SOFT_SGMII_88E1111,
295				others =>	C_BOARD_ETH_EMPTY),
296			EthernetCount =>	1
297		),(
298			BoardName =>			conf("VC709"),
299			FPGADevice =>			conf("XC7VX690T-2FFG1761C"),					-- XC7VX690T-2FFG1761C
300			UART =>						C_BOARD_UART_DTE_921600_NONE,
301			Ethernet =>				C_BOARD_ETH_NONE,
302			EthernetCount =>	0
303		),(
304			BoardName =>			conf("ZEDBOARD"),
305			FPGADevice =>			conf("XC7Z020-1CLG484"),							-- XC7Z020-1CLG484
306			UART =>						C_BOARD_UART_EMPTY,
307			Ethernet =>				C_BOARD_ETH_NONE,
308			EthernetCount =>	0
309		),
310		-- Custom Board (MUST BE LAST ONE)
311		-- =========================================================================
312		(
313			BoardName =>			conf("Custom"),
314			FPGADevice =>			conf("Device is unknown for a custom board"),
315			UART =>						C_BOARD_UART_EMPTY,
316			Ethernet =>				C_BOARD_ETH_NONE,
317			EthernetCount =>	0
318		)
319	);
320end package body;
321
322
323library	IEEE;
324use			IEEE.std_logic_1164.all;
325use			IEEE.numeric_std.all;
326
327library	PoC;
328use			PoC.my_config.all;
329use			PoC.my_project.all;
330use 		PoC.config_private.all;
331use			PoC.utils.all;
332
333
334package config is
335	constant PROJECT_DIR			: string	:= MY_PROJECT_DIR;
336	constant OPERATING_SYSTEM	: string	:= MY_OPERATING_SYSTEM;
337
338	-- List of known FPGA / Chip vendors
339	-- ---------------------------------------------------------------------------
340	type T_VENDOR is (
341		VENDOR_UNKNOWN,
342		VENDOR_ALTERA,
343		VENDOR_LATTICE,
344		VENDOR_XILINX
345	);
346
347	-- List of known synthesis tool chains
348	-- ---------------------------------------------------------------------------
349	type T_SYNTHESIS_TOOL is (
350		SYNTHESIS_TOOL_UNKNOWN,
351		SYNTHESIS_TOOL_ALTERA_QUARTUS2,
352		SYNTHESIS_TOOL_LATTICE_LSE,
353		SYNTHESIS_TOOL_SYNOPSIS,
354		SYNTHESIS_TOOL_XILINX_XST,
355		SYNTHESIS_TOOL_XILINX_VIVADO
356	);
357
358	-- List of known device families
359	-- ---------------------------------------------------------------------------
360	type T_DEVICE_FAMILY is (
361		DEVICE_FAMILY_UNKNOWN,
362		-- Altera
363		DEVICE_FAMILY_ARRIA,
364		DEVICE_FAMILY_CYCLONE,
365		DEVICE_FAMILY_STRATIX,
366		-- Lattice
367		DEVICE_FAMILY_ICE,
368		DEVICE_FAMILY_MACHXO,
369		DEVICE_FAMILY_ECP,
370		-- Xilinx
371		DEVICE_FAMILY_SPARTAN,
372		DEVICE_FAMILY_ZYNQ,
373		DEVICE_FAMILY_ARTIX,
374		DEVICE_FAMILY_KINTEX,
375		DEVICE_FAMILY_VIRTEX
376	);
377
378	type T_DEVICE_SERIES is (
379		DEVICE_SERIES_UNKNOWN,
380		-- Xilinx FPGA series
381		DEVICE_SERIES_7_SERIES,
382		DEVICE_SERIES_ULTRASCALE,
383		DEVICE_SERIES_ULTRASCALE_PLUS
384	);
385
386	-- List of known devices
387	-- ---------------------------------------------------------------------------
388	type T_DEVICE is (
389		DEVICE_UNKNOWN,
390		-- Altera
391		DEVICE_MAX2, DEVICE_MAX10,																					-- Altera.Max
392		DEVICE_ARRIA1, DEVICE_ARRIA2, DEVICE_ARRIA5, DEVICE_ARRIA10,				-- Altera.Arria
393		DEVICE_CYCLONE1, DEVICE_CYCLONE2, DEVICE_CYCLONE3, DEVICE_CYCLONE4,	-- Altera.Cyclone
394			DEVICE_CYCLONE5,																									--
395		DEVICE_STRATIX1, DEVICE_STRATIX2, DEVICE_STRATIX3, DEVICE_STRATIX4,	-- Altera.Stratix
396			DEVICE_STRATIX5, DEVICE_STRATIX10,																--
397		-- Lattice
398		DEVICE_ICE40, DEVICE_ICE65, DEVICE_ICE5,														-- Lattice.iCE
399		DEVICE_MACHXO, DEVICE_MACHXO2,																			-- Lattice.MachXO
400		DEVICE_ECP3, DEVICE_ECP4, DEVICE_ECP5,															-- Lattice.ECP
401		-- Xilinx
402		DEVICE_SPARTAN3, DEVICE_SPARTAN6,																		-- Xilinx.Spartan
403		DEVICE_ZYNQ7, DEVICE_ZYNQ_ULTRA_PLUS,																-- Xilinx.Zynq
404		DEVICE_ARTIX7,																											-- Xilinx.Artix
405		DEVICE_KINTEX7, DEVICE_KINTEX_ULTRA, DEVICE_KINTEX_ULTRA_PLUS,			-- Xilinx.Kintex
406		DEVICE_VIRTEX5,	DEVICE_VIRTEX6, DEVICE_VIRTEX7,											-- Xilinx.Virtex
407			DEVICE_VIRTEX_ULTRA, DEVICE_VIRTEX_ULTRA_PLUS											--
408	);
409
410	-- List of known device subtypes
411	-- ---------------------------------------------------------------------------
412	type T_DEVICE_SUBTYPE is (
413		DEVICE_SUBTYPE_NONE,
414		-- Altera
415		DEVICE_SUBTYPE_E,
416		DEVICE_SUBTYPE_GS,
417		DEVICE_SUBTYPE_GX,
418		DEVICE_SUBTYPE_GT,
419		-- Lattice
420		DEVICE_SUBTYPE_U,
421		DEVICE_SUBTYPE_UM,
422		-- Xilinx
423		DEVICE_SUBTYPE_X,
424		DEVICE_SUBTYPE_T,
425		DEVICE_SUBTYPE_XT,
426		DEVICE_SUBTYPE_HT,
427		DEVICE_SUBTYPE_LX,
428		DEVICE_SUBTYPE_SXT,
429		DEVICE_SUBTYPE_LXT,
430		DEVICE_SUBTYPE_TXT,
431		DEVICE_SUBTYPE_FXT,
432		DEVICE_SUBTYPE_CXT,
433		DEVICE_SUBTYPE_HXT
434	);
435
436	-- List of known transceiver (sub-)types
437	-- ---------------------------------------------------------------------------
438	type T_TRANSCEIVER is (
439		TRANSCEIVER_NONE,
440		-- TODO: add more? Altera transceivers
441		-- Altera transceivers
442		TRANSCEIVER_GXB,																										-- Altera GXB transceiver
443		--Lattice transceivers
444		TRANSCEIVER_MGT,																										-- Lattice transceiver
445		-- Xilinx transceivers
446		TRANSCEIVER_GTP_DUAL,	TRANSCEIVER_GTPE1, TRANSCEIVER_GTPE2,					-- Xilinx GTP transceivers
447		TRANSCEIVER_GTX,			TRANSCEIVER_GTXE1, TRANSCEIVER_GTXE2,					-- Xilinx GTX transceivers
448		TRANSCEIVER_GTH,			TRANSCEIVER_GTHE1, TRANSCEIVER_GTHE2,					-- Xilinx GTH transceivers
449		TRANSCEIVER_GTZ,																										-- Xilinx GTZ transceivers
450		TRANSCEIVER_GTY																											-- Xilinx GTY transceivers
451	);
452
453	-- Properties of an FPGA architecture
454	-- ===========================================================================
455	type T_DEVICE_INFO is record
456		Vendor						: T_VENDOR;
457		Device						: T_DEVICE;
458		DevFamily					: T_DEVICE_FAMILY;
459		DevNumber					: natural;
460		DevSubType				: T_DEVICE_SUBTYPE;
461		DevSeries					: T_DEVICE_SERIES;
462
463		TransceiverType		: T_TRANSCEIVER;
464		LUT_FanIn					: positive;
465	end record;
466
467	-- Functions extracting board and PCB properties from "MY_BOARD"
468	-- which is declared in package "my_config".
469	-- ===========================================================================
470	function BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY)								return NATURAL;
471	function BOARD_INFO(BoardConfig : STRING := C_BOARD_STRING_EMPTY)						return T_BOARD_INFO;
472	function BOARD_NAME(BoardConfig : STRING := C_BOARD_STRING_EMPTY) 					return STRING;
473	function BOARD_DEVICE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) 				return STRING;
474	function BOARD_UART_BAUDRATE(BoardConfig : STRING := C_BOARD_STRING_EMPTY)	return STRING;
475
476	-- Functions extracting device and architecture properties from "MY_DEVICE"
477	-- which is declared in package "my_config".
478	-- ===========================================================================
479	function VENDOR(DeviceString : string := C_DEVICE_STRING_EMPTY)						return T_VENDOR;
480	function SYNTHESIS_TOOL(DeviceString : string := C_DEVICE_STRING_EMPTY)		return T_SYNTHESIS_TOOL;
481	function DEVICE(DeviceString : string := C_DEVICE_STRING_EMPTY)						return T_DEVICE;
482	function DEVICE_FAMILY(DeviceString : string := C_DEVICE_STRING_EMPTY)		return T_DEVICE_FAMILY;
483	function DEVICE_NUMBER(DeviceString : string := C_DEVICE_STRING_EMPTY)		return natural;
484	function DEVICE_SUBTYPE(DeviceString : string := C_DEVICE_STRING_EMPTY)		return T_DEVICE_SUBTYPE;
485	function DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY)		return T_DEVICE_SERIES;
486
487	function TRANSCEIVER_TYPE(DeviceString : string := C_DEVICE_STRING_EMPTY)	return T_TRANSCEIVER;
488	function LUT_FANIN(DeviceString : string := C_DEVICE_STRING_EMPTY)				return positive;
489
490	function DEVICE_INFO(DeviceString : string := C_DEVICE_STRING_EMPTY)			return T_DEVICE_INFO;
491
492	-- force FSM to predefined encoding in debug mode
493	function getFSMEncoding_gray(debug : BOOLEAN) return STRING;
494end package;
495
496
497package body config is
498	-- inlined function from PoC.utils, to break dependency
499	-- ===========================================================================
500	function ite(cond : BOOLEAN; value1 : STRING; value2 : STRING) return STRING is begin
501		if cond then	return value1;	else	return value2;	end if;
502	end function;
503
504	-- chr_is* function
505	function chr_isDigit(chr : CHARACTER) return boolean is
506	begin
507		return ((CHARACTER'pos('0') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('9')));
508	end function;
509
510	function chr_isAlpha(chr : character) return boolean is
511	begin
512		return (((CHARACTER'pos('a') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('z'))) or
513						((CHARACTER'pos('A') <= CHARACTER'pos(chr)) and (CHARACTER'pos(chr) <= CHARACTER'pos('Z'))));
514	end function;
515
516	function str_length(str : STRING) return NATURAL is
517	begin
518		for i in str'range loop
519			if (str(i) = C_POC_NUL) then
520				return i - str'low;
521			end if;
522		end loop;
523		return str'length;
524	end function;
525
526	function str_trim(str : STRING) return STRING is
527	begin
528		for i in str'range loop
529			if (str(i) = C_POC_NUL) then
530				return str(str'low to i-1);
531			end if;
532		end loop;
533		return str;
534	end function;
535
536	function str_imatch(str1 : STRING; str2 : STRING) return BOOLEAN is
537		constant len	: NATURAL 		:= imin(str1'length, str2'length);
538		variable chr1	: CHARACTER;
539		variable chr2	: CHARACTER;
540	begin
541		-- if both strings are empty
542		if ((str1'length = 0 ) and (str2'length = 0)) then		return TRUE;	end if;
543		-- compare char by char
544		for i in 0 to len-1 loop
545			chr1	:= str1(str1'low + i);
546			chr2	:= str2(str2'low + i);
547			if (CHARACTER'pos('A') <= CHARACTER'pos(chr1)) and (CHARACTER'pos(chr1) <= CHARACTER'pos('Z')) then
548				chr1	:= CHARACTER'val(CHARACTER'pos(chr1) - CHARACTER'pos('A') + CHARACTER'pos('a'));
549			end if;
550			if (CHARACTER'pos('A') <= CHARACTER'pos(chr2)) and (CHARACTER'pos(chr2) <= CHARACTER'pos('Z')) then
551				chr2	:= CHARACTER'val(CHARACTER'pos(chr2) - CHARACTER'pos('A') + CHARACTER'pos('a'));
552			end if;
553			if (chr1 /= chr2) then
554				return FALSE;
555			elsif ((chr1 = C_POC_NUL) xor (chr2 = C_POC_NUL)) then
556				return FALSE;
557			elsif ((chr1 = C_POC_NUL) and (chr2 = C_POC_NUL)) then
558				return TRUE;
559			end if;
560		end loop;
561		-- check special cases,
562		if ((str1'length = len) and (str2'length = len)) then 	-- both strings are fully consumed and equal
563			return TRUE;
564		elsif (str1'length > len) then
565			return (str1(str1'low + len) = C_POC_NUL);						-- str1 is longer, but str_length equals len
566		else
567      return (str2(str2'low + len) = C_POC_NUL);						-- str2 is longer, but str_length equals len
568		end if;
569	end function;
570
571	function str_find(str : STRING; pattern : STRING; start : NATURAL := 0) return BOOLEAN is
572	begin
573		for i in imax(str'low, start) to (str'high - pattern'length + 1) loop
574			exit when (str(i) = C_POC_NUL);
575			if (str(i to i + pattern'length - 1) = pattern) then
576				return TRUE;
577			end if;
578		end loop;
579		return FALSE;
580	end function;
581
582	-- private functions required by board description
583	-- ModelSim requires that this functions is defined before it is used below.
584	-- ===========================================================================
585	function getLocalDeviceString(DeviceString : STRING) return STRING is
586		constant ConstNUL				: STRING(1 to 1)				:= (others => C_POC_NUL);
587		constant MY_DEVICE_STR	: STRING								:= BOARD_DEVICE;
588		variable Result					: STRING(1 to T_DEVICE_STRING'length);
589	begin
590		Result := (others => C_POC_NUL);
591		-- report DeviceString for debugging
592		if (POC_VERBOSE = TRUE) then
593			report "getLocalDeviceString: DeviceString='" & str_trim(DeviceString) & "' MY_DEVICE='" & str_trim(MY_DEVICE) & "' MY_DEVICE_STR='" & str_trim(MY_DEVICE_STR) & "'"  severity NOTE;
594		end if;
595		-- if DeviceString is populated
596		if ((str_length(DeviceString) /= 0) and (str_imatch(DeviceString, "None") = FALSE)) then
597			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);
598		-- if MY_DEVICE is set, prefer it
599		elsif ((str_length(MY_DEVICE) /= 0) and (str_imatch(MY_DEVICE, "None") = FALSE)) then
600			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);
601		-- otherwise use MY_BOARD
602		else
603			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);
604		end if;
605		return Result;
606	end function;
607
608	function extractFirstNumber(str : STRING) return NATURAL is
609		variable low			: integer;
610		variable high			: integer;
611		variable Result		: NATURAL;
612		variable Digit		: INTEGER;
613	begin
614		low			:= -1;
615		high		:= -1;
616		for i in str'low to str'high loop
617			if chr_isDigit(str(i)) then
618				low := i;
619				exit;
620			end if;
621		end loop;
622		-- abort if no digit can be found
623		if (low = -1) then		return 0; end if;
624
625		for i in (low + 1) to str'high loop
626			if chr_isAlpha(str(i)) then
627				high := i - 1;
628				exit;
629			end if;
630		end loop;
631
632		if (high = -1) then		return 0; end if;
633		-- return INTEGER'value(str(low to high));			-- 'value(...) is not supported by Vivado Synth 2014.1
634
635		-- convert substring to a number
636		for i in low to high loop
637			if (chr_isDigit(str(i)) = FALSE) then
638				return 0;
639			end if;
640			Result	:= (Result * 10) + (character'pos(str(i)) - character'pos('0'));
641		end loop;
642		return Result;
643	end function;
644
645	-- Public functions
646	-- ===========================================================================
647	-- TODO: comment
648	function BOARD(BoardConfig : string := C_BOARD_STRING_EMPTY) return NATURAL is
649		constant MY_BRD			: T_BOARD_CONFIG_STRING	:= ite((BoardConfig /= C_BOARD_STRING_EMPTY), conf(BoardConfig), conf(MY_BOARD));
650		constant BOARD_NAME	: STRING								:= str_trim(MY_BRD);
651	begin
652		if (POC_VERBOSE = TRUE) then	report "PoC configuration: Used board is '" & BOARD_NAME & "'" severity NOTE;		end if;
653		for i in C_BOARD_INFO_LIST'range loop
654			if str_imatch(BOARD_NAME, C_BOARD_INFO_LIST(i).BoardName) then
655				return  i;
656			end if;
657		end loop;
658
659		report "Unknown board name in MY_BOARD = " & MY_BRD & "." severity failure;
660		return C_BOARD_INFO_LIST'high;
661	end function;
662
663	function BOARD_INFO(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return T_BOARD_INFO is
664		constant BRD	: NATURAL := BOARD(BoardConfig);
665  begin
666		return  C_BOARD_INFO_LIST(BRD);
667	end function;
668
669	-- TODO: comment
670	function BOARD_NAME(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING is
671		constant BRD	: NATURAL := BOARD(BoardConfig);
672  begin
673		return str_trim(C_BOARD_INFO_LIST(BRD).BoardName);
674	end function;
675
676	-- TODO: comment
677	function BOARD_DEVICE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING is
678		constant BRD	: NATURAL := BOARD(BoardConfig);
679  begin
680		return str_trim(C_BOARD_INFO_LIST(BRD).FPGADevice);
681	end function;
682
683	function BOARD_UART_BAUDRATE(BoardConfig : STRING := C_BOARD_STRING_EMPTY) return STRING is
684		constant BRD	: NATURAL := BOARD(BoardConfig);
685  begin
686		return str_trim(C_BOARD_INFO_LIST(BRD).UART.BaudRate);
687	end function;
688
689	-- purpose: extract vendor from MY_DEVICE
690	function VENDOR(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_VENDOR is
691		constant MY_DEV		: string(1 to 32)	:= getLocalDeviceString(DeviceString);
692		constant VEN_STR2	: string(1 to 2)  := MY_DEV(1 to 2);
693		constant VEN_STR3	: string(1 to 3)  := MY_DEV(1 to 3);
694	begin
695		case VEN_STR2 is
696			when "EP" =>		return VENDOR_ALTERA;
697			when "XC" =>		return VENDOR_XILINX;
698			when others =>	null;
699		end case;
700		case VEN_STR3 is
701			when "iCE" =>		return VENDOR_LATTICE;		-- iCE devices
702			when "LCM" =>		return VENDOR_LATTICE;		-- MachXO device
703			when "LFE" =>		return VENDOR_LATTICE;		-- ECP devices
704			when others =>	report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
705										 -- return statement is explicitly missing otherwise XST won't stop
706		end case;
707	end function;
708
709	function SYNTHESIS_TOOL(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_SYNTHESIS_TOOL is
710		constant VEN			: T_VENDOR				:= VENDOR(DeviceString);
711	begin
712		case VEN is
713			when VENDOR_ALTERA =>
714				return SYNTHESIS_TOOL_ALTERA_QUARTUS2;
715			when VENDOR_LATTICE =>
716				return SYNTHESIS_TOOL_LATTICE_LSE;
717				--return SYNTHESIS_TOOL_SYNOPSIS;
718			when VENDOR_XILINX =>
719				if (1 fs /= 1 us) then
720					return SYNTHESIS_TOOL_XILINX_XST;
721				else
722					return SYNTHESIS_TOOL_XILINX_VIVADO;
723				end if;
724			when others =>
725				return SYNTHESIS_TOOL_UNKNOWN;
726		end case;
727	end function;
728
729	-- purpose: extract device from MY_DEVICE
730	function DEVICE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE is
731		constant MY_DEV		: string(1 to 32)	:= getLocalDeviceString(DeviceString);
732		constant VEN			: T_VENDOR				:= VENDOR(DeviceString);
733		constant DEV_STR	: string(3 to  4)	:= MY_DEV(3 to 4);
734	begin
735		case VEN is
736			when VENDOR_ALTERA =>
737				case DEV_STR is
738					when "1C"	 => return DEVICE_CYCLONE1;
739					when "2C"	 => return DEVICE_CYCLONE2;
740					when "3C"	 => return DEVICE_CYCLONE3;
741					when "1S"	 => return DEVICE_STRATIX1;
742					when "2S"	 => return DEVICE_STRATIX2;
743					when "4S"	 => return DEVICE_STRATIX4;
744					when "5S"	 => return DEVICE_STRATIX5;
745					when others => report "Unknown Altera device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
746				end case;
747
748			when VENDOR_LATTICE =>
749				if		(MY_DEV(1 to 6) = "LCMX02") then	return DEVICE_MACHXO2;
750				elsif	(MY_DEV(1 to 5) = "LCMX0") then		return DEVICE_MACHXO;
751				elsif	(MY_DEV(1 to 5) = "iCE40") then		return DEVICE_ICE40;
752				elsif	(MY_DEV(1 to 5) = "iCE65") then		return DEVICE_ICE65;
753				elsif	(MY_DEV(1 to 4) = "iCE5") then		return DEVICE_ICE5;
754				elsif	(MY_DEV(1 to 4) = "LFE3") then		return DEVICE_ECP3;
755				elsif	(MY_DEV(1 to 4) = "LFE4") then		return DEVICE_ECP4;
756				elsif	(MY_DEV(1 to 4) = "LFE5") then		return DEVICE_ECP5;
757				else	report "Unknown Lattice device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
758				end if;
759
760			when VENDOR_XILINX =>
761				case DEV_STR is
762					when "7A"	 => return DEVICE_ARTIX7;
763					when "7K"	 => return DEVICE_KINTEX7;
764					when "KU"	 => return DEVICE_KINTEX_ULTRA;
765					when "3S"	 => return DEVICE_SPARTAN3;
766					when "6S"	 => return DEVICE_SPARTAN6;
767					when "5V"	 => return DEVICE_VIRTEX5;
768					when "6V"	 => return DEVICE_VIRTEX6;
769					when "7V"	 => return DEVICE_VIRTEX7;
770					when "VU"	 => return DEVICE_VIRTEX_ULTRA;
771					when "7Z"	 => return DEVICE_ZYNQ7;
772					when others => report "Unknown Xilinx device in MY_DEVICE = '" & MY_DEV & "'" severity failure;
773				end case;
774
775			when others => report "Unknown vendor in MY_DEVICE = " & MY_DEV & "." severity failure;
776										 -- return statement is explicitly missing otherwise XST won't stop
777		end case;
778	end function;
779
780	-- purpose: extract device from MY_DEVICE
781	function DEVICE_FAMILY(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_FAMILY is
782		constant MY_DEV		: string(1 to 32)	:= getLocalDeviceString(DeviceString);
783		constant VEN			: T_VENDOR				:= VENDOR(DeviceString);
784		constant FAM_CHAR	: character				:= MY_DEV(4);
785	begin
786		case VEN is
787			when VENDOR_ALTERA =>
788				case FAM_CHAR is
789					when 'C' =>		return DEVICE_FAMILY_CYCLONE;
790					when 'S' =>		return DEVICE_FAMILY_STRATIX;
791					when others =>	report "Unknown Altera device family in MY_DEVICE = '" & MY_DEV & "'" severity failure;
792				end case;
793
794			when VENDOR_LATTICE =>
795				case FAM_CHAR is
796					--when 'M' =>		return DEVICE_FAMILY_MACHXO;
797					when 'E' =>		return DEVICE_FAMILY_ECP;
798					when others =>	report "Unknown Lattice device family in MY_DEVICE = '" & MY_DEV & "'" severity failure;
799				end case;
800
801			when VENDOR_XILINX =>
802				case FAM_CHAR is
803					when 'A' =>		return DEVICE_FAMILY_ARTIX;
804					when 'K' =>		return DEVICE_FAMILY_KINTEX;
805					when 'S' =>		return DEVICE_FAMILY_SPARTAN;
806					when 'V' =>		return DEVICE_FAMILY_VIRTEX;
807					when 'Z' =>		return DEVICE_FAMILY_ZYNQ;
808					when others => report "Unknown Xilinx device family in MY_DEVICE = '" & MY_DEV & "'" severity failure;
809				end case;
810
811			when others => report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
812										 -- return statement is explicitly missing otherwise XST won't stop
813		end case;
814	end function;
815
816	-- some devices share some common features: e.g. XADC, BlockRAM, ...
817	function DEVICE_SERIES(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_SERIES is
818		constant MY_DEV	: string(1 to 32)	:= getLocalDeviceString(DeviceString);
819		constant DEV		: T_DEVICE				:= DEVICE(DeviceString);
820	begin
821		case DEV is
822			-- all Xilinx ****7 devices
823			when DEVICE_ARTIX7 | DEVICE_KINTEX7 | DEVICE_VIRTEX7 | DEVICE_ZYNQ7 =>
824				return DEVICE_SERIES_7_SERIES;
825			-- all Xilinx ****UltraScale devices
826			when DEVICE_KINTEX_ULTRA | DEVICE_VIRTEX_ULTRA =>
827				return DEVICE_SERIES_ULTRASCALE;
828			-- all Xilinx ****UltraScale+ devices
829			when DEVICE_KINTEX_ULTRA_PLUS | DEVICE_VIRTEX_ULTRA_PLUS | DEVICE_ZYNQ_ULTRA_PLUS =>
830				return DEVICE_SERIES_ULTRASCALE_PLUS;
831			when others =>
832				return DEVICE_SERIES_UNKNOWN;
833		end case;
834	end function;
835
836	function DEVICE_NUMBER(DeviceString : string := C_DEVICE_STRING_EMPTY) return natural is
837		constant MY_DEV		: string(1 to 32)	:= getLocalDeviceString(DeviceString);
838		constant VEN			: T_VENDOR				:= VENDOR(DeviceString);
839	begin
840		case VEN is
841			when VENDOR_ALTERA =>		return extractFirstNumber(MY_DEV(5 to MY_DEV'high));
842			when VENDOR_LATTICE =>	return extractFirstNumber(MY_DEV(6 to MY_DEV'high));
843			when VENDOR_XILINX =>		return extractFirstNumber(MY_DEV(5 to MY_DEV'high));
844			when others =>					report "Unknown vendor in MY_DEVICE = '" & MY_DEV & "'" severity failure;
845															-- return statement is explicitly missing otherwise XST won't stop
846		end case;
847	end function;
848
849	function DEVICE_SUBTYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return t_device_subtype is
850		constant MY_DEV				: string(1 to 32)	:= getLocalDeviceString(DeviceString);
851		constant DEV					: T_DEVICE				:= DEVICE(MY_DEV);
852		constant DEV_SUB_STR	: string(1 to 2)	:= MY_DEV(5 to 6);																-- work around for GHDL
853	begin
854		case DEV is
855			-- TODO: extract Arria GX subtype
856			when DEVICE_ARRIA1 =>
857				report "TODO: parse Arria device subtype." severity failure;
858				return DEVICE_SUBTYPE_NONE;
859			-- TODO: extract ArriaII GX,GZ subtype
860			when DEVICE_ARRIA2 =>
861				report "TODO: parse ArriaII device subtype." severity failure;
862				return DEVICE_SUBTYPE_NONE;
863			-- TODO: extract ArriaV GX, GT, SX, GZ subtype
864			when DEVICE_ARRIA5 =>
865				report "TODO: parse ArriaV device subtype." severity failure;
866				return DEVICE_SUBTYPE_NONE;
867			-- TODO: extract Arria10 GX, GT, SX subtype
868			when DEVICE_ARRIA10 =>
869				report "TODO: parse Arria10 device subtype." severity failure;
870				return DEVICE_SUBTYPE_NONE;
871			-- Altera Cyclon I, II, III, IV, V devices have no subtype
872			when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 | DEVICE_CYCLONE4 |
873					 DEVICE_CYCLONE5 =>																															return DEVICE_SUBTYPE_NONE;
874
875			when DEVICE_STRATIX2 =>
876				if		chr_isDigit(DEV_SUB_STR(1)) then																						return DEVICE_SUBTYPE_NONE;
877				elsif	(DEV_SUB_STR = "GX") then																										return DEVICE_SUBTYPE_GX;
878				else	report "Unknown Stratix II subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
879				end if;
880
881			when DEVICE_STRATIX4 =>
882				if		(DEV_SUB_STR(1) = 'E') then																									return DEVICE_SUBTYPE_E;
883				elsif	(DEV_SUB_STR = "GX") then																										return DEVICE_SUBTYPE_GX;
884--				elsif	(DEV_SUB_STR = "GT") then																										return DEVICE_SUBTYPE_GT;
885				else	report "Unknown Stratix IV subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
886				end if;
887
888			-- TODO: extract StratixV subtype
889			when DEVICE_STRATIX5 =>
890				report "TODO: parse Stratix V device subtype." severity failure;
891				return DEVICE_SUBTYPE_NONE;
892
893			when DEVICE_ECP5 =>
894				if		(DEV_SUB_STR(1) = 'U') then																									return DEVICE_SUBTYPE_U;
895				elsif	(DEV_SUB_STR = "UM") then																										return DEVICE_SUBTYPE_UM;
896				else	report "Unknown Lattice ECP5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
897				end if;
898
899			when DEVICE_SPARTAN3 =>
900				report "TODO: parse Spartan3 / Spartan3E / Spartan3AN device subtype." severity failure;
901				return DEVICE_SUBTYPE_NONE;
902
903			when DEVICE_SPARTAN6 =>
904				if		((DEV_SUB_STR = "LX") and (not	str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LX;
905				elsif	((DEV_SUB_STR = "LX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LXT;
906				else	report "Unknown Virtex-5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
907				end if;
908
909			when DEVICE_VIRTEX5 =>
910				if		((DEV_SUB_STR = "LX") and (not	str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LX;
911				elsif	((DEV_SUB_STR = "LX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LXT;
912				elsif	((DEV_SUB_STR = "SX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_SXT;
913				elsif	((DEV_SUB_STR = "TX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_TXT;
914				elsif	((DEV_SUB_STR = "FX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_FXT;
915				else	report "Unknown Virtex-5 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
916				end if;
917
918			when DEVICE_VIRTEX6 =>
919				if		((DEV_SUB_STR = "LX") and (not	str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LX;
920				elsif	((DEV_SUB_STR = "LX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_LXT;
921				elsif	((DEV_SUB_STR = "SX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_SXT;
922				elsif	((DEV_SUB_STR = "CX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_CXT;
923				elsif	((DEV_SUB_STR = "HX") and (			str_find(MY_DEV(7 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_HXT;
924				else	report "Unknown Virtex-6 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
925				end if;
926
927			when DEVICE_ARTIX7 =>
928				if		(													(			str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_T;
929				else	report "Unknown Artix-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
930				end if;
931
932			when DEVICE_KINTEX7 =>
933				if		(													(			str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_T;
934				else	report "Unknown Kintex-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
935				end if;
936
937			when DEVICE_KINTEX_ULTRA =>																															return DEVICE_SUBTYPE_NONE;
938			when DEVICE_KINTEX_ULTRA_PLUS =>																												return DEVICE_SUBTYPE_NONE;
939
940			when DEVICE_VIRTEX7 =>
941				if		(														(		str_find(MY_DEV(5 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_T;
942				elsif	((DEV_SUB_STR(1) = 'X') and (		str_find(MY_DEV(6 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_XT;
943				elsif	((DEV_SUB_STR(1) = 'H') and (		str_find(MY_DEV(6 TO MY_DEV'high), "T"))) then	return DEVICE_SUBTYPE_HT;
944				else	report "Unknown Virtex-7 subtype: MY_DEVICE = '" & MY_DEV & "'" severity failure;
945				end if;
946
947			when DEVICE_VIRTEX_ULTRA =>																															return DEVICE_SUBTYPE_NONE;
948			when DEVICE_VIRTEX_ULTRA_PLUS =>																												return DEVICE_SUBTYPE_NONE;
949
950			when DEVICE_ZYNQ7 =>																																		return DEVICE_SUBTYPE_NONE;
951			when DEVICE_ZYNQ_ULTRA_PLUS =>																													return DEVICE_SUBTYPE_NONE;
952
953			when others => report "Device sub-type is unknown for the given device." severity failure;
954									-- return statement is explicitly missing otherwise XST won't stop
955		end case;
956
957	end function;
958
959	function LUT_FANIN(DeviceString : string := C_DEVICE_STRING_EMPTY) return positive is
960		constant MY_DEV	: string(1 to 32)	:= getLocalDeviceString(DeviceString);
961		constant DEV		: T_DEVICE				:= DEVICE(DeviceString);
962		constant SERIES	: T_DEVICE_SERIES	:= DEVICE_SERIES(DeviceString);
963	begin
964		case SERIES is
965			when DEVICE_SERIES_7_SERIES | DEVICE_SERIES_ULTRASCALE |
966					 DEVICE_SERIES_ULTRASCALE_PLUS =>														return 6;
967			when others => null;
968		end case;
969		case DEV is
970			when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 =>				return 4;
971			when DEVICE_STRATIX1 | DEVICE_STRATIX2 =>													return 4;
972			when DEVICE_STRATIX4 | DEVICE_STRATIX5 =>													return 6;
973
974			when DEVICE_ECP5 =>																								return 4;
975
976			when DEVICE_SPARTAN3 =>																						return 4;
977			when DEVICE_SPARTAN6 =>																						return 6;
978			when DEVICE_VIRTEX5 | DEVICE_VIRTEX6 =>														return 6;
979
980			when others => report "LUT fan-in is unknown for the given device." severity failure;
981									-- return statement is explicitly missing otherwise XST won't stop
982		end case;
983	end function;
984
985	function TRANSCEIVER_TYPE(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_TRANSCEIVER is
986		constant MY_DEV		: string(1 to 32)		:= getLocalDeviceString(DeviceString);
987		constant DEV			: T_DEVICE					:= DEVICE(DeviceString);
988		constant DEV_NUM	: natural						:= DEVICE_NUMBER(DeviceString);
989		constant DEV_SUB	: t_device_subtype	:= DEVICE_SUBTYPE(DeviceString);
990	begin
991		case DEV is
992			when DEVICE_MAX2 | DEVICE_MAX10 =>																return TRANSCEIVER_NONE;		-- Altera MAX II, 10 devices have no transceivers
993			when DEVICE_CYCLONE1 | DEVICE_CYCLONE2 | DEVICE_CYCLONE3 =>				return TRANSCEIVER_NONE;		-- Altera Cyclon I, II, III devices have no transceivers
994
995			when DEVICE_STRATIX2 =>						return TRANSCEIVER_GXB;
996			when DEVICE_STRATIX4 =>						return TRANSCEIVER_GXB;
997			--when DEVICE_STRATIX5 =>						return TRANSCEIVER_GXB;
998
999			when DEVICE_ECP5 =>								return TRANSCEIVER_MGT;
1000
1001			when DEVICE_SPARTAN3 =>						return TRANSCEIVER_NONE;		-- Xilinx Spartan3 devices have no transceivers
1002			when DEVICE_SPARTAN6 =>
1003				case DEV_SUB is
1004					when DEVICE_SUBTYPE_LX =>			return TRANSCEIVER_NONE;
1005					when DEVICE_SUBTYPE_LXT =>		return TRANSCEIVER_GTPE1;
1006					when others =>								report "Unknown Spartan-6 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
1007				end case;
1008
1009			when DEVICE_VIRTEX5 =>
1010				case DEV_SUB is
1011					when DEVICE_SUBTYPE_LX =>			return TRANSCEIVER_NONE;
1012					when DEVICE_SUBTYPE_SXT =>		return TRANSCEIVER_GTP_DUAL;
1013					when DEVICE_SUBTYPE_LXT =>		return TRANSCEIVER_GTP_DUAL;
1014					when DEVICE_SUBTYPE_TXT =>		return TRANSCEIVER_GTX;
1015					when DEVICE_SUBTYPE_FXT =>		return TRANSCEIVER_GTX;
1016					when others =>								report "Unknown Virtex-5 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
1017				end case;
1018
1019			when DEVICE_VIRTEX6 =>
1020				case DEV_SUB is
1021					when DEVICE_SUBTYPE_LX =>			return TRANSCEIVER_NONE;
1022					when DEVICE_SUBTYPE_SXT =>		return TRANSCEIVER_GTXE1;
1023					when DEVICE_SUBTYPE_LXT =>		return TRANSCEIVER_GTXE1;
1024					when DEVICE_SUBTYPE_HXT =>		return TRANSCEIVER_GTXE1;
1025					when others =>								report "Unknown Virtex-6 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
1026				end case;
1027
1028			when DEVICE_ARTIX7 =>							return TRANSCEIVER_GTPE2;
1029			when DEVICE_KINTEX7 =>						return TRANSCEIVER_GTXE2;
1030			when DEVICE_VIRTEX7 =>
1031				case DEV_SUB is
1032					when DEVICE_SUBTYPE_T =>			return TRANSCEIVER_GTXE2;
1033					when DEVICE_SUBTYPE_XT =>
1034						if (DEV_NUM = 485) then			return TRANSCEIVER_GTXE2;
1035						else												return TRANSCEIVER_GTHE2;
1036						end if;
1037					when DEVICE_SUBTYPE_HT =>			return TRANSCEIVER_GTHE2;
1038					when others =>								report "Unknown Virtex-7 subtype: " & t_device_subtype'image(DEV_SUB) severity failure;
1039				end case;
1040			when DEVICE_ZYNQ7 =>
1041				case DEV_NUM is
1042					when 10 | 20 =>								return TRANSCEIVER_NONE;
1043					when 15 =>										return TRANSCEIVER_GTPE2;
1044					when others =>								return TRANSCEIVER_GTXE2;
1045				end case;
1046
1047			when others => report "Unknown device." severity failure;
1048									-- return statement is explicitly missing otherwise XST won't stop
1049		end case;
1050	end function;
1051
1052	-- purpose: extract architecture properties from DEVICE
1053	function DEVICE_INFO(DeviceString : string := C_DEVICE_STRING_EMPTY) return T_DEVICE_INFO is
1054		variable Result					: T_DEVICE_INFO;
1055	begin
1056		Result.Vendor						:= VENDOR(DeviceString);
1057		Result.Device						:= DEVICE(DeviceString);
1058		Result.DevFamily				:= DEVICE_FAMILY(DeviceString);
1059		Result.DevNumber				:= DEVICE_NUMBER(DeviceString);
1060		Result.DevSubType				:= DEVICE_SUBTYPE(DeviceString);
1061		Result.DevSeries				:= DEVICE_SERIES(DeviceString);
1062		Result.TransceiverType	:= TRANSCEIVER_TYPE(DeviceString);
1063		Result.LUT_FanIn				:= LUT_FANIN(DeviceString);
1064
1065		return Result;
1066	end function;
1067
1068	-- force FSM to predefined encoding in debug mode
1069	function getFSMEncoding_gray(debug : BOOLEAN) return STRING is
1070	begin
1071		if (debug = true) then
1072			return "gray";
1073		else
1074			case VENDOR is
1075				when VENDOR_ALTERA =>		return "default";
1076				--when VENDOR_LATTICE =>	return "default";
1077				when VENDOR_XILINX =>		return "auto";
1078				when others =>					report "Unknown vendor." severity failure;
1079																-- return statement is explicitly missing otherwise XST won't stop
1080			end case;
1081		end if;
1082	end function;
1083end package body;
1084