-- TestBench Template 
-- ce module permet de tester le FIFO et de valider son fonctionnement.
  LIBRARY ieee;
  USE ieee.std_logic_1164.ALL;
  USE ieee.numeric_std.ALL;
  Library  NocLib ;
 use NocLib.CoreTypes.all;
  ENTITY testbench IS
  END testbench;

  ARCHITECTURE behavior OF testbench IS 
constant clk_period : time := 10 ns;
constant MSIZE :natural :=256;
  signal clk : std_logic := '0';
  signal reset : std_logic := '0';
  -- Component Declaration
         
component FIFO_256_FWFT  --Le FIFO à tester
	port (
	clk: IN std_logic;
	din: IN std_logic_VECTOR(7 downto 0);
	rd_en: IN std_logic;
	srst: IN std_logic;
	wr_en: IN std_logic;
	dout: OUT std_logic_VECTOR(7 downto 0);
	empty: OUT std_logic;
	full: OUT std_logic);
end component;
component proto_receiv -- permet de tester la lecture dans le FIFO
generic (sizemem : natural := 64);
 port (
 clk,reset : in std_logic;
 fifo_empty,fifo_full : in std_logic;
  pop : out std_logic:='0';
 fifo_out : in std_logic_vector(Word-1 downto 0);
 rcv_start : in std_logic; --début de la réception
 rcv_ack :in std_logic;   -- acquittement de la réception
 rcv_comp : out std_logic; -- fin de la réception
 mem :out memory(0 to sizemem-1));
end component;

component proto_send
generic (sizemem : natural := 64);
 port (
 clk,reset : in std_logic;
 fifo_empty,fifo_full : in std_logic;
  push : out std_logic:='0';
 fifo_in : out std_logic_vector(Word-1 downto 0);
 snd_start : in std_logic; --début de l'emission
 snd_ack :in std_logic;   -- acquittement de l'émission
 snd_comp : out std_logic; -- fin de l'émission
 mem :in memory(0 to sizemem-1));
 
 end component;
 
type typ_snd_rec is ( fillmem,send1, send2, recv1,recv2);
type typ_receiv is (r_wait,r_head,r_dlen,r_glen,r_start,r_end);
			signal storage1,storage2 : memory (0 to MSIZE-1);
          SIGNAL fifo_empty,fifo_full :  std_logic:='0';
			 signal push,pop ,spush,spop:  std_logic:='0';
          SIGNAL data_in,data_out:  std_logic_vector(7 downto 0);
          signal ROn,Rdone,RAck:std_logic:='0';
			 signal SOn,Sdone,SAck:std_logic:='0';
			 signal etreceiv :typ_receiv;
			
			 signal pipo : typ_snd_rec;

  BEGIN
			
  

uut : FIFO_256_FWFT
		port map (
			clk => clk,
			din => data_in,
			rd_en => pop,
			srst => reset,
			wr_en => push,
			dout => data_out,
			empty => fifo_empty,
			full => fifo_full);
			
rec_pro: proto_receiv generic map(sizemem =>MSIZE)
	port map (clk=>clk,
				reset=>reset,
				fifo_empty=>fifo_empty,
				fifo_full=>fifo_full,
				rcv_start =>Ron,
				rcv_ack => Rack,
				rcv_comp=> Rdone,
				pop=>pop,
				fifo_out =>data_out,
				mem=>storage2
				);
snd_pro: proto_send generic map (sizemem =>MSIZE)
port map (clk=>clk,
				reset=>reset,
				fifo_empty=>fifo_empty,
				fifo_full=>fifo_full,
				snd_start =>Son,
				snd_ack => Sack,
				snd_comp=> Sdone,
				push=>push,
				fifo_in =>data_in,
				mem=>storage1
				);
 clk_process :process
   begin
		clk <= '0';
		wait for clk_period/2;
		clk <= '1';
		wait for clk_period/2;
		
   end process;
reset_proc: process 
   begin		
      -- hold reset state for 100 ns.
      reset<='0';
		wait for 1 ns;	
		reset<='1';
      wait for clk_period*10;
		reset<='0';
		wait;
      -- insert stimulus here 
end process;
pr_pingpong : process(clk,reset)
variable i: natural range 0 to MSIZE-1;
begin
if reset='1' then
	pipo<=fillmem;
	i:=0;
	else
	if rising_edge(clk) then
	case pipo is
		when fillmem => -- remplissage de la mémoire d'envoie
		if i=0 then
		storage1(0)<=x"51"; -- le code de la fonction
		elsif i=1 then
		storage1(1)<=x"05"; -- le nombre d'octets à envoyer dans le tampon.
		elsif (i>=2) and (i<= MSIZE-2) then
		storage1(i)<=std_logic_vector(to_unsigned(i-2,Word));
		
		else
			pipo<=send1;
			i:=0;
		end if;
		i:=i+1;
		when send1 =>
			
			Son<='1'; --activer l'emission des données
			Sack<='0';
			if i=2 then --activer la réception des données
				Ron<='1';
			else 
				Ron<='0';
				i:=i+1;
			end if;
			if sdone='1' then
				pipo<=send2;
						
			end if;
		when send2 =>
			i:=0;
			Son<='0';
			Sack<='1';
			pipo<=recv1;
		when recv1 =>
			ron<='1';
			rack<='0';
			if Rdone='1' then
				pipo<=recv2;
			end if;
		when recv2 =>
			Ron<='0';
			Rack<='1';
			pipo<=send1;
			i:=0;
	end case;
		
	
	end if;
end if;
end process;

END;
