LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera; 
USE altera.altera_primitives_components.all; 

ENTITY TransmitRam IS
	PORT (	D_Out		: IN STD_LOGIC ;
			TransmitOn	: IN STD_LOGIC ;
			n_reset		: IN STD_LOGIC ;
			n_read		: IN STD_LOGIC ;
			slow_clock	: IN STD_LOGIC ;
			subadd		: IN STD_LOGIC_VECTOR (6 DOWNTO 0);
			user_data	: INOUT STD_LOGIC_VECTOR (7 DOWNTO 0);
			SPY1		: OUT STD_LOGIC;
			SPY2		: OUT STD_LOGIC;
			SPY3		: OUT STD_LOGIC;
			SPY4		: OUT STD_LOGIC;
			ck_usb		: IN STD_LOGIC 
		);
END TransmitRam;

ARCHITECTURE SYN OF TransmitRam IS
	SIGNAL DATA		: Std_Logic_vector (7 downto 0);
	SIGNAL sel_word	: Std_Logic_vector (7 downto 0);
	SIGNAL COUNT	: Std_Logic_vector (2 downto 0);
	signal carry, carry_Mem	: std_logic;
	signal rdfull	: std_logic;
	signal rdempty	: std_logic;
	signal FIFO_ReadOut		: std_logic_vector (7 downto 0);
	signal FIFO_w_used		: std_logic_vector (11 downto 0);
	signal tampon, rdreq	: std_logic;
	
COMPONENT big_fifo
	PORT(	aclr	: IN STD_LOGIC ;
			data	: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
			rdclk	: IN STD_LOGIC ;
			rdreq	: IN STD_LOGIC ;
			wrclk	: IN STD_LOGIC ;
			wrreq	: IN STD_LOGIC ;
			q		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
			rdempty	: OUT STD_LOGIC ;
			rdfull	: OUT STD_LOGIC ;
			rdusedw	: OUT STD_LOGIC_VECTOR (11 DOWNTO 0) );
END COMPONENT;

COMPONENT shift8register
	PORT(	aclr	: IN std_logic;
			clock	: IN std_logic;
			enable	: IN std_logic;
			shiftin	: in std_logic;
			q		: out STD_LOGIC_VECTOR (7 DOWNTO 0)	);
END COMPONENT;

COMPONENT data_count
	PORT(	aclr	: IN STD_LOGIC ;
			clk_en	: IN STD_LOGIC ;
			clock	: IN STD_LOGIC ;
			cout	: OUT STD_LOGIC ;
			q		: OUT STD_LOGIC_VECTOR (2 DOWNTO 0)	);
END COMPONENT;

COMPONENT Read_Word
	PORT(	reset		: IN	STD_LOGIC;
			n_read		: IN	STD_LOGIC;
			selection	: IN	STD_LOGIC;	-- selection lecture 
			word_x		: IN	STD_LOGIC_VECTOR(7 DOWNTO 0); -- registre à lire
			User_Data	: INOUT	STD_LOGIC_VECTOR(7 DOWNTO 0) ); -- bus USB
END	COMPONENT;

COMPONENT flipflop 
	PORT(	clock		: IN STD_LOGIC ;
			data		: IN STD_LOGIC ;
			q		: OUT STD_LOGIC		);
END COMPONENT;

BEGIN
-- 8 Latch Instantiation    // Serial to Parallel Converter
shift8register_inst : shift8register PORT MAP (
		aclr	 => NOT (n_reset),
		clock	 => NOT (slow_clock),
		enable	 => NOT (TransmitOn),
		shiftin	 => NOT (D_Out),
		q	 => DATA	);

-- FIFO for ReadOut Instantiation
big_fifo_inst : big_fifo PORT MAP (
		aclr	 => NOT (n_reset),
		data	 => DATA,
		rdclk	 => NOT (ck_usb),
		rdreq	 => rdreq,
		wrclk	 => slow_clock,
		wrreq	 => carry_Mem,
		q		 => FIFO_ReadOut,
		rdempty	 => rdempty,
		rdfull	 => rdfull,
		rdusedw	 => FIFO_w_used );

-- Counter for Serial-to-Parallel Conversion
-- and for FIFO Writing Enable Signal
data_count_inst : data_count	PORT MAP (
		aclr	=> NOT (n_reset),
		clk_en	=> NOT (TransmitOn),
		clock	=> NOT (slow_clock),
		cout	=> carry,
		q		=> COUNT	);

delay_carry_inst : flipflop 	PORT MAP (
		clock	=> NOT (slow_clock),
		data	=> carry,
		q		=> carry_Mem	);

----	// Machine de lecture de la FIFO de ReadOut (ecriture sur bus USB)
--ReadOut : Read_Word PORT MAP (
--		reset		=> n_reset,
--		n_read		=> n_read,
--		selection	=> sel_word(7),  
--		word_x		=> FIFO_readout,	-- registre à lire
--		User_Data	=> user_data -- bus USB
--	);
--
--	// Machine de lecture du LSB des word used de la FIFO (ecriture sur bus USB)
Read_Fifo_word_usedLSB : Read_Word PORT MAP (
		reset		=> n_reset,
		n_read		=> n_read,
		selection	=> sel_word(6), 
		word_x		=> FIFO_w_used(7 downto 0),	-- LSB word used
		User_Data	=> user_data -- bus USB
	);

--	// Machine de lecture du LSB des word used de la FIFO (ecriture sur bus USB)
Read_Fifo_word_usedMSB : Read_Word PORT MAP (
		reset		=> n_reset,
		n_read		=> n_read,
		selection	=> sel_word(5), 
		word_x		=> (rdempty & '0' & '0' & '0' & FIFO_w_used(11 downto 8)),	-- MSB word used
		User_Data	=> user_data -- bus USB
	);

-- FIFO Reading Enable Signal

process (ck_usb, n_reset) 
begin
	if (n_reset = '0') then
		tampon <= '0';
	elsif (ck_usb'event AND ck_usb = '1') then
		tampon <= NOT (n_read);
	end if;
end process;

rdreq <= sel_word(7) AND NOT(tampon) AND NOT(n_read);	-- Réduction du pulse de read à 1 période

user_data <= "ZZZZZZZZ" when n_reset = '0' else
	FIFO_readout when (sel_word(7) = '1' AND n_read = '0') else "ZZZZZZZZ" ;


make_sel_word : PROCESS(subadd)
BEGIN
	CASE subadd IS
	WHEN "0001101"	=>	sel_word <= "00100000";	-- add(13) = 5
	WHEN "0001110"	=>	sel_word <= "01000000";	-- add(14) = 6
	WHEN "0001111"	=>	sel_word <= "10000000";	-- add(15) = 7
	WHEN OTHERS	=>	sel_word <= "00000000";
END CASE;
END PROCESS make_sel_word;

SPY1 <= carry_Mem;
SPY2 <= rdempty;
SPY3 <= rdreq;
SPY4 <= FIFO_w_used(0);
END SYN;
