LIBRARY ieee, work;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.std_logic_unsigned.all;

ENTITY quatre_lignes IS
	GENERIC (
		CONSTANT taille_input : natural := 6
	);
	PORT (
		line_out 	: out	std_logic_vector(8 downto 0);
		pixel_out	: out	std_logic_vector(9 downto 0);

		sortie		: OUT	STD_LOGIC_VECTOR(taille_input-1 DOWNTO 0);

		line_num 	: in	std_logic_vector(8 downto 0);
		pixel_num	: in	std_logic_vector(9 downto 0);

		clock		: in	std_logic;
		entree		: IN	STD_LOGIC_VECTOR(taille_input-1 DOWNTO 0)
	);

END quatre_lignes ;

ARCHITECTURE a OF quatre_lignes IS

component minmax
	GENERIC (
		taille : natural
	);
	PORT (
		inA     : in	std_logic_vector(taille-1 downto 0);
		inB     : in	std_logic_vector(taille-1 downto 0);

		min     : out	std_logic_vector(taille-1 downto 0);
		max     : out	std_logic_vector(taille-1 downto 0)
	);
END component ;

component une_ligne
	GENERIC (
		taille_flux : natural
	);
	PORT (
		clock		: in	std_logic;
		
		wren		: in	std_logic;
		pixel_num	: in	std_logic_vector(9 downto 0);

		data_sig	: IN	STD_LOGIC_VECTOR(taille_flux-1 DOWNTO 0);
		
		q_n		: out	STD_LOGIC_VECTOR(taille_flux-1 DOWNTO 0); -- q(addr)
		q_n1	: out	STD_LOGIC_VECTOR(taille_flux-1 DOWNTO 0); -- q(addr+1)
		q_n2	: out	STD_LOGIC_VECTOR(taille_flux-1 DOWNTO 0); -- q(addr+2)
		q_n3	: out	STD_LOGIC_VECTOR(taille_flux-1 DOWNTO 0)  -- q(addr+3)
	);
END component ;

signal q_n_A, q_n1_A, q_n2_A, q_n3_A : std_logic_vector(taille_input-1 downto 0);
signal q_n_B, q_n1_B, q_n2_B, q_n3_B : std_logic_vector(taille_input-1 downto 0);
signal q_n_C, q_n1_C, q_n2_C, q_n3_C : std_logic_vector(taille_input-1 downto 0);
signal q_n_D, q_n1_D, q_n2_D, q_n3_D : std_logic_vector(taille_input-1 downto 0);
signal wren_A, wren_B, wren_C, wren_D : std_logic;

signal d_n_A, d_n1_A, d_n2_A, d_n3_A : std_logic_vector(taille_input-1 downto 0);
signal d_n_B, d_n1_B, d_n2_B, d_n3_B : std_logic_vector(taille_input-1 downto 0);
signal d_n_C, d_n1_C, d_n2_C, d_n3_C : std_logic_vector(taille_input-1 downto 0);

signal somme : std_logic_vector(taille_input-1+4 downto 0);

signal sA,sB,sC,sD,sE,sF, tA,tB,tC,tD,tE,tF, uA,uB,uC,uD,uE,uF, vA,vB,vC,vD,vE,vF,vG,vH,vI,vJ, wA,wB,wC,wD, xA,xB,xC,xD,xE, Median : std_logic_vector(taille_input-1 downto 0);

BEGIN

-- l'entree est envoyee vers un des 4 buffers de lignes
-- 3 sont en lecture et 1 est en écriture
wren_A   <= not line_num(0) and not line_num(1);  -- A
wren_B   <=     line_num(0) and not line_num(1);  -- B
wren_C   <= not line_num(0) and     line_num(1);  -- C
wren_D   <=     line_num(0) and     line_num(1);  -- D

-- on recupere 12 pixels (3 lignes de 4 pixels)

selection : process(line_num, q_n_A, q_n1_A, q_n2_A, q_n3_A, q_n_B, q_n1_B, q_n2_B, q_n3_B, q_n_C, q_n1_C, q_n2_C, q_n3_C, q_n_D, q_n1_D, q_n2_D, q_n3_D)
begin
	case line_num(1 downto 0) is
		when "00" =>
			d_n_A <= q_n_B; d_n1_A <= q_n1_B; d_n2_A <= q_n2_B; d_n3_A <= q_n3_B;
			d_n_B <= q_n_C; d_n1_B <= q_n1_C; d_n2_B <= q_n2_C; d_n3_B <= q_n3_C;
			d_n_C <= q_n_D; d_n1_C <= q_n1_D; d_n2_C <= q_n2_D; d_n3_C <= q_n3_D;
		when "01" =>
			d_n_A <= q_n_C; d_n1_A <= q_n1_C; d_n2_A <= q_n2_C; d_n3_A <= q_n3_C;
			d_n_B <= q_n_D; d_n1_B <= q_n1_D; d_n2_B <= q_n2_D; d_n3_B <= q_n3_D;
			d_n_C <= q_n_A; d_n1_C <= q_n1_A; d_n2_C <= q_n2_A; d_n3_C <= q_n3_A;
		when "10" =>
			d_n_A <= q_n_D; d_n1_A <= q_n1_D; d_n2_A <= q_n2_D; d_n3_A <= q_n3_D;
			d_n_B <= q_n_A; d_n1_B <= q_n1_A; d_n2_B <= q_n2_A; d_n3_B <= q_n3_A;
			d_n_C <= q_n_B; d_n1_C <= q_n1_B; d_n2_C <= q_n2_B; d_n3_C <= q_n3_B;
		when "11" =>
			d_n_A <= q_n_A; d_n1_A <= q_n1_A; d_n2_A <= q_n2_A; d_n3_A <= q_n3_A;
			d_n_B <= q_n_B; d_n1_B <= q_n1_B; d_n2_B <= q_n2_B; d_n3_B <= q_n3_B;
			d_n_C <= q_n_C; d_n1_C <= q_n1_C; d_n2_C <= q_n2_C; d_n3_C <= q_n3_C;
	end case;
end process;

-- pour tester, mais c plus complique en vrai.
somme <= ("0000"&q_n_A) + ("0000"&q_n1_A) + ("0000"&q_n2_A) + ("0000"&q_n3_A)
		+ ("0000"&q_n_B) + ("0000"&q_n1_B) + ("0000"&q_n2_B) + ("0000"&q_n3_B)
		+ ("0000"&q_n_C) + ("0000"&q_n1_C) + ("0000"&q_n2_C) + ("0000"&q_n3_C)
		+ ("0000"&q_n_D) + ("0000"&q_n1_D) + ("0000"&q_n2_D) + ("0000"&q_n3_D);

synchroclock : process(clock)
begin
	if (rising_edge(clock)) then
		--sortie <= somme(taille_flux-1+4 downto 4);
		sortie <= Median;
		line_out <= line_num;
		pixel_out <= pixel_num;
	end if;
end process;
	
	
ligne_A : une_ligne GENERIC MAP (
		taille_flux => taille_input
	)
	PORT MAP
	(
		clock => clock,
		wren  => wren_A,
		pixel_num => pixel_num,
		data_sig => entree,
		q_n => q_n_A,
		q_n1 => q_n1_A,
		q_n2 => q_n2_A,
		q_n3 => q_n3_A
	);
ligne_B : une_ligne GENERIC MAP (
		taille_flux => taille_input
	)
	PORT MAP
	(
		clock => clock,
		wren  => wren_B,
		pixel_num => pixel_num,
		data_sig => entree,
		q_n => q_n_B,
		q_n1 => q_n1_B,
		q_n2 => q_n2_B,
		q_n3 => q_n3_B
	);
ligne_C : une_ligne GENERIC MAP (
		taille_flux => taille_input
	)
	PORT MAP
	(
		clock => clock,
		wren  => wren_C,
		pixel_num => pixel_num,
		data_sig => entree,
		q_n => q_n_C,
		q_n1 => q_n1_C,
		q_n2 => q_n2_C,
		q_n3 => q_n3_C
	);
ligne_D : une_ligne GENERIC MAP (
		taille_flux => taille_input
	)
	PORT MAP
	(
		clock => clock,
		wren  => wren_D,
		pixel_num => pixel_num,
		data_sig => entree,
		q_n => q_n_D,
		q_n1 => q_n1_D,
		q_n2 => q_n2_D,
		q_n3 => q_n3_D
	);

minmax1 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n1_A,
		inB => d_n2_A,
		min => sA,
		max => sB
	);
minmax2 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n1_B,
		inB => d_n2_B,
		min => tA,
		max => tB
	);
minmax3 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n1_C,
		inB => d_n2_C,
		min => uA,
		max => uB
	);
minmax4 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n_A,
		inB => sA,
		min => sC,
		max => sF
	);
minmax5 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n_B,
		inB => tA,
		min => tC,
		max => tD
	);
minmax6 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => d_n_C,
		inB => uA,
		min => uC,
		max => uD
	);
minmax7 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => sF,
		inB => sB,
		min => sD,
		max => sE
	);
minmax8 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => tD,
		inB => tB,
		min => tE,
		max => tF
	);
minmax9 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => uD,
		inB => uB,
		min => uE,
		max => uF
	);
minmax10 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => sC,
		inB => tC,
		min => vA,
		max => vB
	);
minmax11 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => tF,
		inB => uF,
		min => vC,
		max => vD
	);
minmax12 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => tE,
		inB => uE,
		min => vE,
		max => vF
	);
minmax13 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => vB,
		inB => uC,
		min => wA,
		max => wB
	);
minmax14 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => sD,
		inB => vE,
		min => vG,
		max => vH
	);
minmax15 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => sE,
		inB => vC,
		min => wC,
		max => wD
	);
minmax16 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => vH,
		inB => vF,
		min => vI,
		max => vJ
	);
minmax17 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => vI,
		inB => wC,
		min => xA,
		max => xB
	);
minmax18 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => wB,
		inB => xA,
		min => xC,
		max => xD
	);
minmax19 : minmax GENERIC MAP ( taille => taille_input )
	PORT MAP
	(	inA => xD,
		inB => xB,
		min => Median,
		max => xE
	);

END a;
