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

---------------------------------------------------------------------------------------------------
-- Ver : Date		: Description
-- 0.1 : 2026.01.01.: 1st Version
---------------------------------------------------------------------------------------------------
-- 解説:
--	[TOP_FPGA.VHD]用のテストベンチ
--	ModelSim, Vivadoシミュレーション で共有できる記述としてある
---------------------------------------------------------------------------------------------------

-- Use IEEE library -------------------------------------------------------------------------------
library	IEEE;
	use	IEEE.STD_LOGIC_1164.ALL;
	use	IEEE.STD_LOGIC_ARITH.ALL;
	use	IEEE.STD_LOGIC_UNSIGNED.ALL;
	use	IEEE.std_logic_textio.all;		-- ファイル書き込み用
	use	std.textio.all;

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

entity	TEST_BENCH is
end		TEST_BENCH;

architecture SIM of TEST_BENCH is -----------------------------------------------------------------

-- 固定値定義 -------------------------------------------------------------------------------------
constant	CYCLE12 : time		:= 83.3 ns;	-- クロック 12MHz

-- ファイル関連宣言 -------------------------------------------------------------------------------
constant	filename : string	:= "UART_DATA.TXT";
file		output_file : text;

-- 信号定義 ---------------------------------------------------------------------------------------

-- タイトル用 -----------------------------------
	signal simulation_title1	: string( 1 to 20 );	-- 波形の上側に表示するタイトル
	signal simulation_title2	: string( 1 to 20 );

-- システム -------------------------------------
	signal CLK_IN				: std_logic;
	signal nRESET				: std_logic;
	signal SWITCH_RES_IN		: std_logic;
	signal SIM_LOOP_C			: std_logic_vector(23 downto 0);

-- UART -----------------------------------------
	signal UART_TX					: std_logic;
	signal UART_RX					: std_logic;
-- UART モジュール(シミュレーション用モデル)
	signal SIM_TX_DATA_IN			: std_logic_vector(7 downto 0);
	signal SIM_TX_DATA_SET			: std_logic;
	signal SIM_TX_BUSY				: std_logic;
	signal SIM_TX_PARITY_ODD_EVEN	: std_logic;
	signal SIM_RX_DATA				: std_logic_vector(7 downto 0);
	signal SIM_RX_RECIEVE_END		: std_logic;
-- ロジックアナライザー入力端子 -----------------
	signal LOGIC_ANALYZER_IN		: std_logic_vector(14 downto 0);
-- LED ------------------------------------------
	signal LED_ONOFF_OUT			: std_logic;

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

-- FPGA TOP モジュール --------------------------
component TOP_FPGA
port (
	-- システム
	nRESET				: in	std_logic;						-- nRESET
	CLK_IN				: in	std_logic;						-- CLOCK 12MHz
	SWITCH_RES_IN		: in	std_logic;						-- RESET用スイッチ(正論理)
	-- UART
	UART_RX				: in	std_logic;
	UART_TX				: out	std_logic;
	-- ロジアナ入力
	LOGIC_ANALYZER_IN	: in	std_logic_vector(14 downto 0);
	-- LED
	LED_ONOFF_OUT		: out std_logic							-- ロジック動作中LED
);
end component ;

-- UART モジュール(シミュレーション用モデル) ----
component SIM_MODULE_UART_8_bit
port (
	-- システム
	nRESET					: in	std_logic;						-- 外部 RESETIN 入力(負論理)
	CLK_IN					: in	std_logic;						-- クロック	20MHz
	-- 送信
	SIM_TX_DATA_IN			: in	std_logic_vector(7 downto 0);	-- 送信データ
	SIM_TX_DATA_SET			: in	std_logic;						-- 動作開始信号
	SIM_TX_BUSY				: out	std_logic;						-- 送信処理中は '1'、送信終了後 '0'
	SIM_UART_TX				: out	std_logic;
	SIM_TX_PARITY_ODD_EVEN	: in	std_logic;						-- パリティ 0:偶数、1:奇数
	-- 受信
	SIM_UART_RX				: in	std_logic;
	SIM_RX_DATA				: out	std_logic_vector(7 downto 0);	-- 受信データ
	SIM_RX_PARITY_bit		: out	std_logic;						-- 受信したパリティビット
	SIM_RX_PARITY_ODD_EVEN	: out	std_logic;						-- 受信パリティ 0:偶数、1:奇数
	SIM_RX_BUSY				: out	std_logic;						-- 受信処理中は '1'、受信終了後 '0'
	SIM_RX_RECIEVE_END		: out	std_logic						-- 受信終了信号 (1-CLOCK)
);
end component ;

-- プロシージャー（サブ関数）宣言 -----------------------------------------------------------------

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

-- PULL-UP ----------------------------------------------------------------------------------------
--	nRESET	<= 'H';

-- ファイルオープン -------------------------------------------------------------------------------
file_open	( output_file, filename, write_mode );

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

-- FPGA TOP モジュール --------------------------
m_TOP_FPGA : TOP_FPGA
port map(
	-- システム
	nRESET				=> nRESET,
	CLK_IN				=> CLK_IN,
	SWITCH_RES_IN		=> SWITCH_RES_IN,
	-- UART
	UART_RX				=> UART_RX,
	UART_TX				=> UART_TX,
	-- ロジアナ入力
	LOGIC_ANALYZER_IN	=> LOGIC_ANALYZER_IN,
-- LED
	LED_ONOFF_OUT		=> LED_ONOFF_OUT
);

-- UART モジュール(シミュレーション用モデル) ----
m_SIM_MODULE_UART_8_bit : SIM_MODULE_UART_8_bit
port map(
	-- システム
	nRESET					=> nRESET,
	CLK_IN					=> CLK_IN,
	-- 送信
	SIM_TX_DATA_IN			=> SIM_TX_DATA_IN,
	SIM_TX_DATA_SET			=> SIM_TX_DATA_SET,
	SIM_TX_BUSY				=> SIM_TX_BUSY,
	SIM_UART_TX				=> UART_RX,					-- TX
	SIM_TX_PARITY_ODD_EVEN	=> SIM_TX_PARITY_ODD_EVEN,
	-- 受信
	SIM_UART_RX				=> UART_TX,					-- RX
	SIM_RX_DATA				=> SIM_RX_DATA,
	SIM_RX_PARITY_bit		=> open,
	SIM_RX_PARITY_ODD_EVEN	=> open,
	SIM_RX_BUSY				=> open,
	SIM_RX_RECIEVE_END		=> SIM_RX_RECIEVE_END
);

-- クロック生成プロセス ---------------------------------------------------------------------------
-- 12MHz(83.3nsec)
process begin
	CLK_IN	<= '1';
	wait for CYCLE12/2;
	CLK_IN	<= '0';
	wait for CYCLE12/2;
end process;

-- テスト信号生成 ---------------------------------------------------------------------------------
process ( CLK_IN ) begin
	if ( CLK_IN'event and CLK_IN = '1' ) then	-- '
		-- RESET
		if ( nRESET = '0' ) then	LOGIC_ANALYZER_IN <= (others => '0');
		else						LOGIC_ANALYZER_IN <= LOGIC_ANALYZER_IN + 1;
		end if;
	end if;
end process;

-- ファイル書き込みプロセス -----------------------------------------------------------------------
process
variable L_line : line ;
begin
	-- 1-CLOCK 待ち
	wait until rising_edge(CLK_IN);
	-- UART受信フラグ判定
	if ( SIM_RX_RECIEVE_END = '1' ) then
		-- ESC コードは文字に変更してラインバッファへ格納
		if ( SIM_RX_DATA = X"1B" ) then
			write( L_line, string'("ESC"));
			--	write( L_line, 'E' );
			--	write( L_line, 'S' );
			--	write( L_line, 'C' );
		-- その他のコードはそのままラインバッファへ格納
		else
			write( L_line, character'val( conv_integer(SIM_RX_DATA) ));	-- 文字型に変換
		end if;
		-- 改行検出で、ラインバッファの内容を書き出し
		if ( SIM_RX_DATA = X"0D" ) then	writeline( output_file, L_line );
		end if;
	end if;
end process;

-- メインシミュレーション -------------------------------------------------------------------------
process begin

-- 初期化 ---------------------------------------
	simulation_title1	<= "A7 LOGIC ANALYZER   ";
	simulation_title2	<= "INIT                ";

-- シミュレーション用初期化 ---------------------
	SIM_LOOP_C 	<= (others => '0');
	wait until rising_edge(CLK_IN);

-- 入力ピン初期化 -------------------------------
	wait until rising_edge(CLK_IN);
	wait for 1 nS;

	SWITCH_RES_IN			<= '0';
	SIM_TX_DATA_IN			<= (others => '0');
	SIM_TX_DATA_SET			<= '0';
	SIM_TX_PARITY_ODD_EVEN	<= '0';
	nRESET					<= '0';
	wait until rising_edge(CLK_IN);

-- nRESET 発生 ----------------------------------
	simulation_title2	<= "nRESET              ";
	wait until	rising_edge(CLK_IN);
	wait for 1 nS;
	nRESET				<= '0';
	wait until	rising_edge(CLK_IN);
	wait until	rising_edge(CLK_IN);
	wait until	rising_edge(CLK_IN);
	wait until	rising_edge(CLK_IN);
	wait for 1 nS;
	nRESET				<= '1';
	wait until	rising_edge(CLK_IN);
	wait until	rising_edge(CLK_IN);

-- MMCM(PLL)安定待ち ----------------------------
-- VIVADOのシミュレーションでは、起動に時間が掛かる
	simulation_title2	<= "WAIT MMCM START     ";
	wait until	rising_edge(CLK_IN);
	wait for 50 uS;
	wait until	rising_edge(CLK_IN);

-- ENTERキー受信 --------------------------------
	simulation_title2		<= "ENTER KEY           ";
	wait until rising_edge(CLK_IN) ;

	-- RESET 解除待ち
	wait for 20 uS;
	wait until rising_edge(CLK_IN) ;

	-- 送信:ENTER
	wait for 1 nS;
	SIM_TX_DATA_IN			<= X"0D";
	SIM_TX_PARITY_ODD_EVEN	<= '0';
	wait until rising_edge(CLK_IN) ;
	wait for 1 nS;
	SIM_TX_DATA_SET			<= '1';
	wait until rising_edge(CLK_IN) ;
	wait for 1 nS;
	SIM_TX_DATA_SET			<= '0';

	-- 送信開始待ち
	wait for 5 uS;
	wait until rising_edge(CLK_IN) ;

	-- 送信終了待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 3 nS;
		exit when ( SIM_TX_BUSY = '0' );		-- 送信終了
		exit when ( SIM_LOOP_C > X"004000" );	-- TIME OUT
	end loop;
	-- CHECK
	if ( SIM_TX_BUSY /= '0' ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;

-- UART 受信データ確認 --------------------------

	simulation_title2		<= "WAIT LINE 1         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	simulation_title2		<= "WAIT LINE 2         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	simulation_title2		<= "WAIT LINE 3         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	simulation_title2		<= "WAIT LINE 4         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	simulation_title2		<= "WAIT LINE 5         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	simulation_title2		<= "WAIT LINE 6         ";
	wait until rising_edge(CLK_IN) ;

	-- SIM側 [0Dh] 受信待ち
	SIM_LOOP_C				<= (others => '0');
	while ( true )  loop
		wait until rising_edge(CLK_IN) ;
		wait for 1 nS;
		SIM_LOOP_C		<= SIM_LOOP_C + '1';
		wait for CYCLE12 - 1 nS;
		exit when (( SIM_RX_RECIEVE_END = '1' ) and ( SIM_RX_DATA = X"0D" ));
		exit when ( SIM_LOOP_C > X"030000" );	-- TIME OUT
	end loop;

	wait until rising_edge(CLK_IN) ;
	wait for CYCLE12 - 1 nS;
	-- CHECK (時間は不問)
	if ( SIM_RX_DATA /= X"0D" ) then	report "<<<<<<< TIME-OUT >>>>>>>" severity failure;
	end if;


	-- 様子見
	wait until rising_edge(CLK_IN) ;
	simulation_title2		<= "WAIT AND SEE        ";
	wait until rising_edge(CLK_IN) ;
	wait for 100 uS;
	wait until rising_edge(CLK_IN) ;



-- ファイルクローズ -------------------------------------------------------------------------------
	file_close( output_file );

-- 終了[完走] -------------------------------------------------------------------------------------
	wait until rising_edge(CLK_IN) ;
	simulation_title1	<= "[ END ]             ";
	simulation_title2	<= "[ END ]             ";
	wait until rising_edge(CLK_IN) ;
--	wait for 1 uS;
	assert (false)	report "    <<<<<<<<<< END : The simulation was successful >>>>>>>>>>" severity failure;
	wait;

end process;

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

