--
-- VHDL Architecture FACT_FAD_lib.rs485_receiver.beha
--
-- Created:
--          by - Benjamin Krumm.UNKNOWN (EEPC8)
--          at - 12:16:57 11.06.2010
--
-- using Mentor Graphics HDL Designer(TM) 2009.2 (Build 10)
--
--
-- modified for FTU design by Q. Weitzel, 13 September 2010
-- timeout added, Q. Weitzel, 26 October 2010
-- 
-- modified for FAD design by D.Neise, 12. April 2011
-- modified library include statements mainly.
--

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

--library fad_rs485_definitions;
--USE fad_rs485_definitions.fad_rs485_constants.all;
library fact_fad_lib;
use fact_fad_lib.fad_rs485_constants.all;

ENTITY FAD_rs485_receiver IS
  generic(
    -- defined in fad_rs485_definitions.fad_rs485_constants
    RX_BYTES  : integer := RS485_MESSAGE_LEN_BYTES; -- no. of bytes to receive
    RX_WIDTH  : integer := RS485_MESSAGE_LEN_BYTES * 8  -- no. of bits to receive
  );
  port(
    rec_clk   : in  std_logic;
 
	-- Interface to MAX3485:
		rx_d     : IN  std_logic;
		rx_en    : OUT std_logic;
		tx_d     : OUT std_logic;
		tx_en    : OUT std_logic;
	
	
	rec_start : in std_logic;
	rec_timeout_occured : out std_logic := '0';
    rec_dout  : out std_logic_vector(RX_WIDTH - 1 downto 0) := (others => '0');
    rec_valid : out std_logic := '0'
  );
END ENTITY FAD_rs485_receiver;

ARCHITECTURE beha OF FAD_rs485_receiver IS
  
  signal rxcnt			: integer range 0 to RX_BYTES := 0;
  signal rxsr			: std_logic_vector(3 downto 0) := (others => '0');
  signal timeout_cnt	: integer range 0 to RS485_TIMEOUT + 1 := 0;
  signal rec_den		: std_logic := '0';
  signal rec_din		: std_logic_vector(7 downto 0) := (others => '0');
  signal start_sr		: std_logic_vector(1 downto 0) := (others => '0');
  signal started		: std_logic := '0'; -- 0-not running; 1-running
  
	component FAD_rs485_interface
	port(
		clk      : IN  std_logic;
		-- RS485
		rx_d     : IN  std_logic;
		rx_en    : OUT std_logic;
		tx_d     : OUT std_logic;
		tx_en    : OUT std_logic;
		-- FPGA
		rx_data  : OUT std_logic_vector (7 DOWNTO 0);
		--rx_busy  : OUT std_logic  := '0';
		rx_valid : OUT std_logic  := '0';
		tx_data  : IN  std_logic_vector (7 DOWNTO 0);
		tx_busy  : OUT std_logic  := '0';
		tx_start : IN  std_logic );
	end component;

  
BEGIN

	Inst_FAD_rs485_interface : FAD_rs485_interface
		port map(
			clk      => rec_clk,
			-- RS485
			rx_d     => rx_d,
			rx_en    => rx_en,
			tx_d     => tx_d,
			tx_en    => tx_en,
			-- FPGA
			rx_data  => rec_din,
			
			rx_valid => rec_den,
			tx_data  => "00000000",
			tx_busy  => open,
			tx_start => '0'
		);

-- process(rec_clk)
	-- begin
		-- if rising_edge(rec_clk) then
			-- start_sr <= start_sr(0) & rec_start;
			-- rxsr <= rxsr(2 downto 0) & rec_den;
			
			
			-- if (start_sr = "01") then
				-- started <= '1';
			-- end if;
			
			-- if ((rxcnt > 0) or (started = '1')) then
				-- timeout_cnt <= timeout_cnt + 1;
			-- else
				-- timeout_cnt <= 0;
			-- end if;
			
			-- if (timeout_cnt = RS485_TIMEOUT) then
				-- rxcnt <= 0;
				-- started <= '0';
				-- rec_timeout_occured <= '1';
				-- rec_valid <= '1';
			-- else
				-- if (rxsr(3 downto 2) = "01") then -- identify rising edge
					-- if (rxcnt = 0) then
						-- rec_dout <= (others => '0');
					-- end if;
					-- rec_dout((rxcnt*rec_din'length + rec_din'length - 1) downto (rxcnt*rec_din'length)) <= rec_din;
					-- rxcnt <= rxcnt + 1;
					-- if (rxcnt < RX_BYTES - 1) then
						-- rec_valid <= '0';
						-- rec_timeout_occured <= '0';
					-- else
						-- rxcnt <= 0;
						-- rec_valid <= '1';
					-- end if;
				-- end if;
			-- end if;
		
		-- end if; --if rising_edge(rec_clk)
	-- end process ;

	
	
	
	process (rec_clk)
	begin
		if rising_edge(rec_clk) then
			start_sr <= start_sr(0) & rec_start;
			rxsr <= rxsr(2 downto 0) & rec_den;

	
			if ((timeout_cnt = RS485_TIMEOUT) or (rxcnt = RX_BYTES))  then
				rxcnt <= 0;
				started <= '0';
				rec_valid <= '1';
				timeout_cnt <= 0;
				rec_timeout_occured <= '0';
				if (timeout_cnt = RS485_TIMEOUT) then
					rec_timeout_occured <= '1';
				end if;
			else
				-- since neither the timeout counter is overrun, 
					-- it should be increased if 'started'
				if (started = '1') then
					timeout_cnt <= timeout_cnt + 1;
				end if;
				
				-- nor the message, was completely received.
					-- maybe we have to receive a bit now --> 
				if (rxsr(3 downto 2) = "01") then -- identify rising edge of rec_den
					started <= '1';
					rec_dout((rxcnt*rec_din'length + rec_din'length - 1) downto (rxcnt*rec_din'length)) <= rec_din;
					rxcnt <= rxcnt + 1;
					if (rxcnt < RX_BYTES - 1) then
						rec_valid <= '0';
						rec_timeout_occured <= '0';
					end if;
				end if;
			
			end if;
			
			if (start_sr = "01") then
				started <= '1';
				rec_valid <= '0';
				rec_dout <= (others => '0');
			end if;

	
		end if; --rising edge
	end process;
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

END ARCHITECTURE beha;
