---------------------------------------------------------------------------------------------------
-- TOP_FPGA.VHD
-- (C) 2025 JAPAN LOGIC DESIGN 日本ロジック設計
-- No unauthorized reproduction or AI training allowed.
-- Unauthorized reproduction prohibited.
---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------
-- Ver : Date		: Description
-- 0.1 : 2026.02.09	: 1st Version
---------------------------------------------------------------------------------------------------
-- 概要：	FPGA全体のTOPロジック
-- 
---------------------------------------------------------------------------------------------------

-- Use IEEE library -------------------------------------------------------------------------------
library	IEEE;
use		IEEE.std_logic_1164.ALL;
use		IEEE.std_logic_ARITH.ALL;
use		IEEE.std_logic_UNSIGNED.ALL;

-- 配列のための追加
use WORK.TYPES.all;

-- エンティティ宣言 -------------------------------------------------------------------------------

entity TOP_FPGA is
port (
	-- システム
	nRESET			: in	std_logic;		-- nRESET
	CLK_IN			: in	std_logic;		-- CLOCK 12MHz
	SWITCH_RES_IN	: in	std_logic;		-- RESET用スイッチ(正論理)
	-- DRP信号MONITOR
	MONI_DRP_DEN	: out	std_logic;
	MONI_DRP_DWE	: out	std_logic;
	MONI_DRP_DRDY	: out	std_logic;
	MONI_DRP_EOC	: out	std_logic;
	MONI_DRP_BUSY	: out	std_logic;
	-- XADC アナログ入力信号
	vp_in			: in	std_logic;
	vn_in			: in	std_logic;
	vauxp4			: in	std_logic;
	vauxn4			: in	std_logic;
	vauxp12			: in	std_logic;
	vauxn12			: in	std_logic;
	-- UART
	UART_RX			: in	std_logic;
	UART_TX			: out	std_logic;
	-- LED
	LED_ONOFF_OUT	: out std_logic			-- ロジック動作中LED
);
end TOP_FPGA;

architecture RTL of TOP_FPGA is ------------------------------------------------------

-- 固定値定義 -------------------------------------------------------------------------------------
-- UARTクロック分周比	50.0MHz/460800/2-1 = 53d = 35h
constant	CLOCK_DIV_VALUE		: std_logic_vector(15 downto 0)	:= X"0035";
-- UART通信時間待ち 1mS : 50.0MHz/1000 -1 = 49999d = C34Fh
constant	COUNT_TRIG_TIMEOUT	: std_logic_vector(23 downto 0)	:= X"00C34F";
-- LED 1秒点滅分周比
--	50MHz/2-1 = 24999999d = 17D783Fh
	constant	LED_BLINK_DIV	: std_logic_vector(31 downto 0)	:= X"017D783F";
-- RESET-SW用チャタリング除去分周比
--	ノイズ除去時間:100mS, 50MHz/10Hz-1 = 4999999d = 4C4B3Fh
	constant	REDUCTION_TIME	: std_logic_vector(23 downto 0)	:= X"4C4B3F";

-- 信号定義 ---------------------------------------------------------------------------------------
-- ステートマシン用 -----------------------------
-- S1
TYPE SIGNAL_STATUS_1 IS (	S1_JOB_START, S1_TIME_WAIT, S1_SEND_N1, S1_SEND_N2, S1_SEND_N3,
							S1_SEND_N4, S1_STATUS_END );
SIGNAL S1_STATUS		: SIGNAL_STATUS_1;
-- 一般信号 -------------------------------------
signal CLK_MMCM			: std_logic;
signal PLL_LOCKED		: std_logic;
signal pRESET			: std_logic;
signal nRESET_2			: std_logic;
signal RESET_C			: std_logic_vector(7 downto 0);
signal SWITCH_RES_OUT	: std_logic;
signal SIG_IN_DATA		: std_logic_vector(15 downto 0);
signal LED_ONOFF_OUT_f	: std_logic;

signal DRP_DEN			: std_logic;
signal DRP_DWE			: std_logic;
signal DRP_DADDR		: std_logic_vector(6 downto 0);
signal DRP_DO			: std_logic_vector(15 downto 0);
signal DRP_DRDY			: std_logic;
signal DRP_EOC			: std_logic;
signal DRP_BUSY			: std_logic;

signal REG_ADDRESS		: std_logic_vector(4 downto 0);
signal XADC_REG_DATA	: XADC_REG_READ_array;

signal SEND_START		: std_logic;
signal SEND_END			: std_logic;
signal SEND_0D_0A		: std_logic;
signal UART_SEND_DATA	: std_logic_vector(15 downto 0);

signal TRIG_TIMEOUT_C	: std_logic_vector(23 downto 0);
signal TRIG_TIMEOUT_F	: std_logic;

-- 使用モジュール宣言 -----------------------------------------------------------------------------

-- MMCM(PLL) ------------------------------------
component clk_wiz_0
port (
	clk_out1			: out	std_logic;
	reset				: in	std_logic;
	locked				: out	std_logic;
	clk_in1				: in	std_logic
);
end component ;

-- XADCモジュール -------------------------------
COMPONENT xadc_wiz_0
PORT (
	di_in				: in std_logic_vector(15 downto 0);
	daddr_in			: in std_logic_vector(6 downto 0);
	den_in				: in std_logic;
	dwe_in				: in std_logic;
	drdy_out			: out std_logic;
	do_out				: out std_logic_vector(15 downto 0);
	dclk_in				: in std_logic;
	reset_in			: in std_logic;
	vp_in				: in std_logic;
	vn_in				: in std_logic;
	--
    vauxp4				: in std_logic;
    vauxn4				: in std_logic;
	vauxp12				: in std_logic;
	vauxn12				: in std_logic;
	--
	channel_out			: out std_logic_vector(4 DOWNTO 0);
	eoc_out				: out std_logic;
	alarm_out			: out std_logic;
	eos_out				: out std_logic;
	busy_out			: out std_logic 
);
end component;

-- XADC-DRP ロジック ----------------------------
component MODULE_XADC_DRP
port(
	-- システム
	nRESET			: in	std_logic;
	CLK_IN			: in	std_logic;
	-- DRP信号
	DRP_DEN			: out	std_logic;
	DRP_DWE			: out	std_logic;
	DRP_DADDR		: out	std_logic_vector(6 downto 0);
--	DRP_DI			: out	std_logic_vector(15 downto 0);	-- 未使用
	DRP_DO			: in	std_logic_vector(15 downto 0);
	DRP_DRDY		: in	std_logic;
--	DRP_EOC			: in	std_logic;
--	DRP_BUSY		: in	std_logic;						-- 未使用
	-- XADCレジスタREADデータ
	XADC_REG_DATA	: out XADC_REG_READ_array
);
end component ;

-- UART 16進数送信 ------------------------------
component UART_SEND_HEX
port(
	-- システム
	nRESET			: in	std_logic;		-- nRESET
	CLK_IN			: in	std_logic;		-- CLOCK 12MHz
	-- 制御信号
	SEND_START		: in	std_logic;		-- 送信開始
	SEND_END		: out	std_logic;		-- 送信終了
	SEND_0D_0A		: in	std_logic;		-- 0D,0A 送信指定
	-- 送信データ
	UART_SEND_DATA	: in	std_logic_vector(15 downto 0);
	-- UART
	UART_RX			: in	std_logic;
	UART_TX			: out	std_logic
);
end component ;

-- LED点滅ロジック ------------------------------
component LED_BLINK
port(
	-- システム
	nRESET			: in	std_logic;						-- Reset
	CLK_IN			: in	std_logic;						-- Clock
	-- データ
	LED_BLINK_DIV	: in	std_logic_vector(31 downto 0);	-- 点滅周期指定
	LED_ONOFF_OUT	: out	std_logic						-- LED ON/OFF OUT
);
end component ;

-- ノイズ除去ロジック ---------------------------
component NOISE_REDUCTION
port(
	-- システム
	nRESET				: in std_logic;
	CLK_IN				: in std_logic;						-- CLOCK
	-- 時間指定
	REDUCTION_TIME		: in std_logic_vector(23 downto 0);	-- ノイズ除去時間
	-- 初期値指定
	NOISE_DEFAULT		: in std_logic;						-- 初期値指定 正論理='0'、負論理='1' 推奨
	-- 入出力
	NOISE_REDUC_IN		: in std_logic;						-- 元信号入力
	NOISE_REDUC_OUT		: out std_logic						-- ノイズ除去後の信号出力
);
end component ;

begin ---------------------------------------------------------------------------------------------

-- モジュール読み出し -----------------------------------------------------------------------------

-- MMCM(PLL)モジュール --------------------------
m_clk_wiz_0 : clk_wiz_0
port map(
	clk_out1			=> CLK_MMCM,
	reset				=> pRESET,			-- 正規RESET(正論理)
	locked				=> PLL_LOCKED,
	clk_in1				=> CLK_IN
);
-- RESET 正論理
	pRESET	<= not nRESET;	-- 正規RESET

-- XADCモジュール -------------------------------
m_xadc_wiz_0 : xadc_wiz_0
PORT MAP (
	di_in				=> (others => '0'),
	daddr_in			=> DRP_DADDR,
	den_in				=> DRP_DEN,
	dwe_in				=> DRP_DWE,
	drdy_out			=> DRP_DRDY,
	do_out				=> DRP_DO,
	dclk_in				=> CLK_MMCM,		-- MMCM
	reset_in			=> pRESET,
	vp_in				=> vp_in,
	vn_in				=> vn_in,
	--
    vauxp4				=> vauxp4,
    vauxn4				=> vauxn4,
	vauxp12				=> vauxp12,
	vauxn12				=> vauxn12,
	--
	channel_out			=> open,
	eoc_out				=> DRP_EOC,
	alarm_out			=> open,
	eos_out				=> open,
	busy_out			=> DRP_BUSY
);

-- XADC-DRP ロジック ----------------------------
m_MODULE_XADC_DRP : MODULE_XADC_DRP
port map(
	-- システム
	nRESET				=> nRESET_2,		-- nRESET-2
	CLK_IN				=> CLK_MMCM,		-- MMCM
	-- DRP信号
	DRP_DEN				=> DRP_DEN,
	DRP_DWE				=> DRP_DWE,
	DRP_DADDR			=> DRP_DADDR,
--	DRP_DI
	DRP_DO				=> DRP_DO,
	DRP_DRDY			=> DRP_DRDY,
--	DRP_EOC				=> DRP_EOC,
--	DRP_BUSY
	-- XADCレジスタREADデータ
	XADC_REG_DATA		=> XADC_REG_DATA
);

-- UART 16進数送信 ------------------------------
m_UART_SEND_HEX : UART_SEND_HEX
port map(
	-- システム
	nRESET				=> nRESET_2,		-- nRESET-2
	CLK_IN				=> CLK_MMCM,		-- MMCM
	-- 制御信号
	SEND_START			=> SEND_START,
	SEND_END			=> SEND_END,
	SEND_0D_0A			=> SEND_0D_0A,
	-- 送信データ
	UART_SEND_DATA		=> UART_SEND_DATA,
	-- UART
	UART_RX				=> UART_RX,
	UART_TX				=> UART_TX
);

-- LED点滅ロジック ------------------------------
m_LED_BLINK : LED_BLINK
port map(
	-- システム
	nRESET				=> nRESET_2,		-- nRESET-2
	CLK_IN				=> CLK_MMCM,		-- MMCM
	-- データ
	LED_BLINK_DIV		=> LED_BLINK_DIV,
	LED_ONOFF_OUT		=> LED_ONOFF_OUT_f
);

-- ノイズ除去ロジック ---------------------------
m_NOISE_REDUCTION : NOISE_REDUCTION
port map(
	-- システム
	nRESET				=> nRESET,			-- 正規RESET
	CLK_IN				=> CLK_MMCM,		-- MMCM
	-- 時間指定
	REDUCTION_TIME		=> REDUCTION_TIME,
	-- 初期値指定
	NOISE_DEFAULT		=> '0',
	-- 入出力
	NOISE_REDUC_IN		=> SWITCH_RES_IN,	-- スイッチ入力(正論理)
	NOISE_REDUC_OUT		=> SWITCH_RES_OUT	-- チャタリング除去後の信号
);

-- ロジック本体 -----------------------------------------------------------------------------------

	---------------------------------------------
	-- RESET
	---------------------------------------------
	-- nRESET が本来のRESET入力。ただし基板にRESET-ICがついていないため、内蔵PULL-UPで '1' 固定。
	-- SWITCH_RES_OUT は、基板上のスイッチのチャタリングを取り除いた信号。
	-- この２つを合成してメインロジックのRESETとする。
	process ( CLK_MMCM ) begin
		if ( CLK_MMCM'event and CLK_MMCM = '1' ) then	-- '
			-- RESET
			if ( nRESET = '0' ) then						-- 負論理
				RESET_C(7 downto 0)	<= (others => '0');
				nRESET_2			<= '0';
			elsif ( SWITCH_RES_OUT = '1' )  then			-- 正論理
				RESET_C(7 downto 0)	<= (others => '0');
				nRESET_2			<= '0';
			-- END
			elsif ( RESET_C(7 downto 0) = X"CC" )  then
				RESET_C(7 downto 0)	<= RESET_C(7 downto 0);
				nRESET_2			<= '1';
			-- +1
			else
				RESET_C(7 downto 0)	<= RESET_C(7 downto 0) + 1 ;
				nRESET_2			<= '0';
			end if;
		end if;
	end process;

	---------------------------------------------
	-- メインシーケンサ[S1]
	---------------------------------------------
	process ( CLK_MMCM ) begin
		if ( CLK_MMCM'event and CLK_MMCM = '1' ) then	-- '
			if ( nRESET_2 = '0' ) then
				UART_SEND_DATA	<= (others => '0');
				SEND_START		<= '0';
				SEND_0D_0A		<= '0';
				S1_STATUS		<= S1_JOB_START;
			else
				case S1_STATUS is

				-- データ送信開始 ---------------
				when S1_JOB_START =>
					UART_SEND_DATA	<= (others => '0');
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					S1_STATUS		<= S1_TIME_WAIT;
				-- 時間待ち ---------------------
				-- ・XADCレジスタから最初のデータを読み取るまでの時間待ち
				-- ・PC側のターミナル処理に余裕を持たせる時間待ち
				when S1_TIME_WAIT =>
					UART_SEND_DATA	<= (others => '0');
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					if ( TRIG_TIMEOUT_F = '1' ) then	S1_STATUS <= S1_SEND_N1;
					else								S1_STATUS <= S1_TIME_WAIT;	-- LOOP
					end if;
				-- 送信
				when S1_SEND_N1 =>
					UART_SEND_DATA	<= XADC_REG_DATA( conv_integer( REG_ADDRESS ));
					SEND_START		<= '1';
					SEND_0D_0A		<= '0';
					S1_STATUS		<= S1_SEND_N2;
				-- 送信終了待ち
				when S1_SEND_N2 =>
					UART_SEND_DATA	<= UART_SEND_DATA;
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					if ( SEND_END = '1' ) then		S1_STATUS <= S1_SEND_N3;
					else							S1_STATUS <= S1_SEND_N2;	-- LOOP
					end if;
				-- 改行送信 ---------------------
				-- 改行判定
				when S1_SEND_N3 =>
					UART_SEND_DATA	<= UART_SEND_DATA;
					if ( REG_ADDRESS = "11111" ) then
						SEND_START	<= '1';
						SEND_0D_0A	<= '1';
						S1_STATUS	<= S1_SEND_N4;
					else
						SEND_START	<= '0';
						SEND_0D_0A	<= '0';
						S1_STATUS	<= S1_STATUS_END;	-- END
					end if;
				-- 送信終了待ち
				when S1_SEND_N4 =>
					UART_SEND_DATA	<= UART_SEND_DATA;
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					if ( SEND_END = '1' ) then		S1_STATUS <= S1_STATUS_END;
					else							S1_STATUS <= S1_SEND_N4;	-- LOOP
					end if;
				-- 終了 -------------------------
				when S1_STATUS_END =>
					UART_SEND_DATA	<= (others => '0');
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					S1_STATUS		<= S1_JOB_START;
				-- その他(本来ここは実行されない)
				when others	=>
					UART_SEND_DATA	<= (others => '0');
					SEND_START		<= '0';
					SEND_0D_0A		<= '0';
					S1_STATUS		<= S1_JOB_START;
				end case;
			end if;
		end if;
	end process;

	---------------------------------------------
	-- レジスタアドレス設定
	---------------------------------------------
	process ( CLK_MMCM ) begin
		if ( CLK_MMCM'event and CLK_MMCM = '1' ) then	-- '
			if ( nRESET_2 = '0' ) then				REG_ADDRESS	<= (others => '0');		-- RESET
			-- 1サイクル終了
			elsif ( S1_STATUS = S1_STATUS_END ) then
				if ( REG_ADDRESS = "11111" ) then	REG_ADDRESS	<= (others => '0');		-- 1Fh で RESET
				else								REG_ADDRESS	<= REG_ADDRESS + 1 ;	-- +1
				end if;
			-- KEEP
			else									REG_ADDRESS	<= REG_ADDRESS;			-- KEEP
			end if;
		end if;
	end process;

	---------------------------------------------
	-- UART通信時間待ち 1mS
	---------------------------------------------
	process ( CLK_MMCM ) begin
		if ( CLK_MMCM'event and CLK_MMCM = '1' ) then	-- '
			-- RESET
			if ( nRESET = '0' ) then
				TRIG_TIMEOUT_C	<= (others => '0');
				TRIG_TIMEOUT_F	<= '0';
			-- スタート
			elsif ( S1_STATUS = S1_JOB_START ) then
				TRIG_TIMEOUT_C	<= (others => '0');
				TRIG_TIMEOUT_F	<= '0';
			-- TIME OUT
			elsif ( TRIG_TIMEOUT_C = COUNT_TRIG_TIMEOUT ) then
				TRIG_TIMEOUT_C	<= TRIG_TIMEOUT_C;		-- KEEP
				TRIG_TIMEOUT_F	<= '1';
			-- +1
			else
				TRIG_TIMEOUT_C	<= TRIG_TIMEOUT_C + 1 ;
			end if;
		end if;
	end process;

-- 出力 -------------------------------------------------------------------------------------------

	-- DRP信号MONITOR
	MONI_DRP_DEN	<= DRP_DEN;
	MONI_DRP_DWE	<= DRP_DWE;
	MONI_DRP_DRDY	<= DRP_DRDY;
	MONI_DRP_EOC	<= DRP_EOC;
	MONI_DRP_BUSY	<= DRP_BUSY;
	-- 動作確認用LED
	LED_ONOFF_OUT	<= LED_ONOFF_OUT_f;		-- 点滅LED

-- END --------------------------------------------------------------------------------------------
-- (C) 2025 JAPAN LOGIC DESIGN 日本ロジック設計
-- No unauthorized reproduction or AI training allowed.
-- Unauthorized reproduction prohibited.
end RTL;

