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

---------------------------------------------------------------------------------------------------
-- Ver : Date		: Description
-- 0.1 : 2026.02.12	: 1st Version
---------------------------------------------------------------------------------------------------
-- 概要：
--	・16bitデータを、16進数文字に変換し、UART送信する
--	・SEND_0D_0A='1' の場合は、データの代わりに改行コードを送信する。0Dh,0Ah
-- 
---------------------------------------------------------------------------------------------------

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

architecture RTL of UART_SEND_HEX is ------------------------------------------------------

-- 固定値定義 -------------------------------------------------------------------------------------
-- UARTクロック分周比	50.0MHz/460800/2-1 = 53d = 35h
constant	CLOCK_DIV_VALUE		: std_logic_vector(15 downto 0)	:= X"0035";

-- 信号定義 ---------------------------------------------------------------------------------------
-- ステートマシン用 -----------------------------
-- S1
type SIGNAL_STATUS_1 IS (	S1_JOB_START, S1_SEND_4A, S1_SEND_4B, S1_SEND_3A, S1_SEND_3B, 
							S1_SEND_2A, S1_SEND_2B, S1_SEND_1A, S1_SEND_1B, S1_SPACE_A, 
							S1_SPACE_B, S1_OD_OA, S1_OD_OA_2, S1_OD_OA_3, S1_OD_OA_4, 
							S1_STATUS_END );
signal S1_STATUS	: SIGNAL_STATUS_1;
-- 一般信号 -------------------------------------
signal TX_DATA_IN			: std_logic_vector(7 downto 0);
signal TX_SEND_START		: std_logic;
signal TX_SEND_END			: std_logic;

signal REG_DATA_HEX_1		: std_logic_vector(3 downto 0);
signal REG_DATA_HEX_2		: std_logic_vector(3 downto 0);
signal REG_DATA_HEX_3		: std_logic_vector(3 downto 0);
signal REG_DATA_HEX_4		: std_logic_vector(3 downto 0);
signal CHAR_1				: std_logic_vector(7 downto 0);
signal CHAR_2				: std_logic_vector(7 downto 0);
signal CHAR_3				: std_logic_vector(7 downto 0);
signal CHAR_4				: std_logic_vector(7 downto 0);

signal XADC_REG_DATA		: XADC_REG_READ_array;

-- ファンクション定義 -----------------------------------------------------------------------------
function	func_bin_to_hex( DATA_4bit : std_logic_vector ) return std_logic_vector is
variable	DATA_HEX	: std_logic_vector(7 downto 0);
begin
	if		( DATA_4bit = X"0" ) then	DATA_HEX := X"30";
	elsif	( DATA_4bit = X"1" ) then	DATA_HEX := X"31";
	elsif	( DATA_4bit = X"2" ) then	DATA_HEX := X"32";
	elsif	( DATA_4bit = X"3" ) then	DATA_HEX := X"33";
	elsif	( DATA_4bit = X"4" ) then	DATA_HEX := X"34";
	elsif	( DATA_4bit = X"5" ) then	DATA_HEX := X"35";
	elsif	( DATA_4bit = X"6" ) then	DATA_HEX := X"36";
	elsif	( DATA_4bit = X"7" ) then	DATA_HEX := X"37";
	elsif	( DATA_4bit = X"8" ) then	DATA_HEX := X"38";
	elsif	( DATA_4bit = X"9" ) then	DATA_HEX := X"39";
	elsif	( DATA_4bit = X"A" ) then	DATA_HEX := X"41";
	elsif	( DATA_4bit = X"B" ) then	DATA_HEX := X"42";
	elsif	( DATA_4bit = X"C" ) then	DATA_HEX := X"43";
	elsif	( DATA_4bit = X"D" ) then	DATA_HEX := X"44";
	elsif	( DATA_4bit = X"E" ) then	DATA_HEX := X"45";
	else								DATA_HEX := X"46";	-- 'F'
	end if;
	return	DATA_HEX;
end function func_bin_to_hex;

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

-- UART モジュール ------------------------------
component MODULE_UART_8_bit
port (
	-- システム
	nRESET				: in	std_logic;						-- 外部 RESETIN 入力(負論理)
	CLK_IN				: in	std_logic;						-- クロック	20MHz
	-- 分周比
	CLOCK_DIV_VALUE		: in	std_logic_vector(15 downto 0);	-- クロック分周比: (例) 20MHz/100Kbps/2 = 100d
	-- UART信号
	UART_RX				: in	std_logic;
	UART_TX				: out	std_logic;
	-- 送信
	TX_DATA_IN			: in	std_logic_vector(7 downto 0);	-- 送信データ
	TX_PARITY_ODD_EVEN	: in	std_logic;						-- パリティ 0:偶数、1:奇数
	TX_SEND_START		: in	std_logic;						-- 動作開始信号
	TX_BUSY				: out	std_logic;						-- 送信処理中は '1'、送信終了後 '0'
	TX_SEND_END			: out	std_logic;						-- 送信終了信号 (1-CLOCK)
	-- 受信
	RX_DATA				: out	std_logic_vector(7 downto 0);	-- 受信データ
	RX_PARITY_ODD_EVEN	: out	std_logic;						-- 受信データから計算したパリティの値 0:偶数、1:奇数
	RX_PARITY_bit		: out	std_logic;						-- 受信したパリティビットの値
	RX_BUSY				: out	std_logic;						-- 受信処理中は '1'、受信終了後 '0'
	RX_RECIEVE_END		: out	std_logic						-- 受信終了信号 (1-CLOCK)
);
end component ;

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

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

-- UART モジュール ------------------------------
m_MODULE_UART_8_bit : MODULE_UART_8_bit
port map(
	-- システム
	nRESET				=> nRESET,
	CLK_IN				=> CLK_IN,
	-- 分周比
	CLOCK_DIV_VALUE		=> CLOCK_DIV_VALUE,
	-- UART信号
	UART_RX				=> UART_RX,			-- RX
	UART_TX				=> UART_TX,			-- TX
	-- 送信
	TX_DATA_IN			=> TX_DATA_IN,
	TX_PARITY_ODD_EVEN	=> '0',				-- パリティ 0:偶数、1:奇数,
	TX_SEND_START		=> TX_SEND_START,
	TX_BUSY				=> open,
	TX_SEND_END			=> TX_SEND_END,		-- 送信終了信号 (1-CLOCK)
	-- 受信
	RX_DATA				=> open,
	RX_PARITY_ODD_EVEN	=> open,
	RX_PARITY_bit		=> open,
	RX_BUSY				=> open,
	RX_RECIEVE_END		=> open
);

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

	---------------------------------------------
	-- 16bit DATA => 16進文字変換
	---------------------------------------------
	REG_DATA_HEX_1(3 downto 0)	<= UART_SEND_DATA(3 downto 0);
	REG_DATA_HEX_2(3 downto 0)	<= UART_SEND_DATA(7 downto 4);
	REG_DATA_HEX_3(3 downto 0)	<= UART_SEND_DATA(11 downto 8);
	REG_DATA_HEX_4(3 downto 0)	<= UART_SEND_DATA(15 downto 12);
	CHAR_1 <= func_bin_to_hex( REG_DATA_HEX_1 );
	CHAR_2 <= func_bin_to_hex( REG_DATA_HEX_2 );
	CHAR_3 <= func_bin_to_hex( REG_DATA_HEX_3 );
	CHAR_4 <= func_bin_to_hex( REG_DATA_HEX_4 );

	---------------------------------------------
	-- メインシーケンサ[S1]
	---------------------------------------------
	process ( CLK_IN ) begin
		if ( CLK_IN'event and CLK_IN = '1' ) then	-- '
			if ( nRESET = '0' ) then
				TX_DATA_IN		<= (others => '0');
				TX_SEND_START	<= '0';
				S1_STATUS		<= S1_JOB_START;
			else
				case S1_STATUS is
				-- 送信開始判定 -----------------
				when S1_JOB_START =>
					TX_DATA_IN		<= (others => '0');
					TX_SEND_START	<= '0';
					if (( SEND_START = '1' ) and ( SEND_0D_0A = '0' )) then		S1_STATUS <= S1_SEND_4A;
					elsif (( SEND_START = '1' ) and ( SEND_0D_0A = '1' )) then	S1_STATUS <= S1_OD_OA;
					else														S1_STATUS <= S1_JOB_START;
					end if;
				-- コード送信(15 downto 12)
				when S1_SEND_4A =>
					TX_DATA_IN		<= CHAR_4;
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_SEND_4B;
				when S1_SEND_4B =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_SEND_3A;
					else							S1_STATUS <= S1_SEND_4B;	-- LOOP
					end if;
				-- コード送信(11 downto 8)
				when S1_SEND_3A =>
					TX_DATA_IN		<= CHAR_3;
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_SEND_3B;
				when S1_SEND_3B =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_SEND_2A;
					else							S1_STATUS <= S1_SEND_3B;	-- LOOP
					end if;
				-- コード送信(7 downto 4)
				when S1_SEND_2A =>
					TX_DATA_IN		<= CHAR_2;
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_SEND_2B;
				when S1_SEND_2B =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_SEND_1A;
					else							S1_STATUS <= S1_SEND_2B;	-- LOOP
					end if;
				-- コード送信(3 downto 0)
				when S1_SEND_1A =>
					TX_DATA_IN		<= CHAR_1;
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_SEND_1B;
				when S1_SEND_1B =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_SPACE_A;
					else							S1_STATUS <= S1_SEND_1B;	-- LOOP
					end if;
				-- ',' コード送信
				when S1_SPACE_A =>
					TX_DATA_IN		<= X"2C";		-- ','
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_SPACE_B;
				when S1_SPACE_B =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_STATUS_END;	-- END
					else							S1_STATUS <= S1_SPACE_B;	-- LOOP
					end if;
				-- 0D,0A コード送信
				when S1_OD_OA =>
					TX_DATA_IN		<= X"0D";
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_OD_OA_2;
				when S1_OD_OA_2 =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_OD_OA_3;
					else							S1_STATUS <= S1_OD_OA_2;	-- LOOP
					end if;
				when S1_OD_OA_3 =>
					TX_DATA_IN		<= X"0A";
					TX_SEND_START	<= '1';
					S1_STATUS		<= S1_OD_OA_4;
				when S1_OD_OA_4 =>
					TX_DATA_IN		<= TX_DATA_IN;
					TX_SEND_START	<= '0';
					if ( TX_SEND_END = '1' ) then	S1_STATUS <= S1_STATUS_END;
					else							S1_STATUS <= S1_OD_OA_4;	-- LOOP
					end if;
				-- 終了
				when S1_STATUS_END =>
					TX_DATA_IN		<= (others => '0');
					TX_SEND_START	<= '0';
					S1_STATUS		<= S1_JOB_START;
				-- その他(本来ここは実行されない)
				when others	=>
					TX_DATA_IN		<= (others => '0');
					TX_SEND_START	<= '0';
					S1_STATUS		<= S1_JOB_START;
				end case;
			end if;
		end if;
	end process;

	---------------------------------------------
	-- 終了フラグ
	---------------------------------------------
	SEND_END	<= '1' when ( S1_STATUS = S1_STATUS_END ) else '0';

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

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

