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