LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

LIBRARY WORK;
USE WORK.uart_types.all;

LIBRARY work;
use work.utils_pkg.all;

------------------------------------------------------------------------------------
ENTITY uart IS
	Generic
	(
		FIFO_DEPTH_RX	: positive := 16;
		FIFO_DEPTH_TX	: positive := 16
	);
	Port
	(
		clk			: in  STD_LOGIC;
		rst			: in  STD_LOGIC;
		we			: in  STD_LOGIC;
		re			: in  STD_LOGIC;
		din			: in  unsigned(7 downto 0);
		dout		: out unsigned(7 downto 0);
		ser_rx		: in  std_logic;
		ser_tx		: out std_logic;
		ctrl		: in  ctrl_t;
		status		: out status_t
	);
END uart;

ARCHITECTURE jtag OF uart IS

subtype addr_t is unsigned (2 downto 0);
subtype reg_t is unsigned (7 downto 0);

signal jtag_addr			: addr_t;
signal jtag_din				: reg_t;
signal jtag_dout			: reg_t;
signal jtag_we				: STD_LOGIC;
signal jtag_re				: STD_LOGIC;

signal rx_fifo_dout			: reg_t;
signal rx_fifo_full			: STD_LOGIC;
signal rx_fifo_empty		: STD_LOGIC;

signal tx_fifo_dout			: reg_t;
signal tx_fifo_full			: STD_LOGIC;
signal tx_fifo_empty		: STD_LOGIC;

signal rx_data_cs			: STD_LOGIC;
signal tx_data_cs			: STD_LOGIC;
signal rx_data_we			: STD_LOGIC;
signal tx_data_re			: STD_LOGIC;

begin

status.rx_present		<= not rx_fifo_empty;
status.tx_complete		<= '1';
status.tx_empty			<= tx_fifo_empty;
status.tx_full			<= tx_fifo_full;
	
inst_jtag_reg:  entity work.jtag_reg
	GENERIC MAP
	(
		INSTANCE_INDEX		=> 0,
		DATA_WIDTH			=> reg_t'length,		-- bits
		ADDR_WIDTH			=> addr_t'length		-- bits
	)
	PORT MAP
	(
		rst					=> rst,
		clk					=> clk,
		addr_o				=> jtag_addr,
		reg_i				=> jtag_din,
		reg_o				=> jtag_dout,
		we_o				=> jtag_we,
		re_o				=> jtag_re
	);

rx_data_we	<= rx_data_cs and jtag_we;

inst_rx_fifo: entity work.fifo_sync
	Generic map
	(
		addr_width			=> NextExpBaseTwo(FIFO_DEPTH_RX),
		data_width			=> reg_t'length
	)
	Port map
	(
		rst			=> rst,
		clk			=> clk,
		we			=> rx_data_we,
		re			=> re,
		fifo_full	=> rx_fifo_full,
		fifo_empty	=> rx_fifo_empty,
		data_w		=> jtag_dout,
		data_r		=> dout
	);

tx_data_re	<= tx_data_cs and jtag_re;

inst_tx_fifo: entity work.fifo_sync
	Generic map
	(
		addr_width			=> NextExpBaseTwo(FIFO_DEPTH_TX),
		data_width			=> reg_t'length
	)
	Port map
	(
		rst			=> rst,
		clk			=> clk,
		we			=> we,
		re			=> tx_data_re,
		fifo_full	=> tx_fifo_full,
		fifo_empty	=> tx_fifo_empty,
		data_w		=> din,
		data_r		=> tx_fifo_dout
	);

-- JTAG Registers
process(jtag_addr, tx_fifo_empty, rx_fifo_dout, tx_fifo_dout)
begin
	rx_data_cs	<= '0';
	tx_data_cs	<= '0';
	
	jtag_din			<= "0000000" & tx_fifo_empty;
	case jtag_addr is

	-- Reg #0
	when "000" => null;	-- Status

	-- Reg #1
	when "001" =>	-- RX-Data
		rx_data_cs	<= '1';
		jtag_din	<= rx_fifo_dout;

	-- Reg #2
	when "010" =>	-- TX-Data
		tx_data_cs	<= '1';
		jtag_din	<= tx_fifo_dout;
		

	when others => null;

	end case;

end process;		

end jtag;

------------------------------------------------------------------------------------
--
-- END OF FILE UART_RX.VHD
--
------------------------------------------------------------------------------------


