----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    21:18:33 03/23/2013 
-- Design Name: 
-- Module Name:    Rx_accumulator - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 

----------------------------------------------------------------------------------
-- LIBRARY
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

----------------------------------------------------------------------------------

entity Rx_accumulator is
    Port ( CLK : 			in   STD_LOGIC;		-- 80 MHz clock from PLL
           RST : 			in   STD_LOGIC;
			  WE : 			in	  STD_LOGIC;
			  UNLOAD : 	 	in	  STD_LOGIC;		-- write enable and unload signal
           DATA_IN : 	in   STD_LOGIC_VECTOR (23 downto 0);		-- data in (from ABS IPCore)
			  ACC_NUMBER : out  STD_LOGIC_VECTOR (31 downto 0);		-- number of accumulated data
           DATA_OUT : 	out  STD_LOGIC_VECTOR (31 downto 0);		-- accumulated data out (to Rx FIFO IPCore)
			  DV : 			out  STD_LOGIC		-- data valid signal
			 );
end Rx_accumulator;

architecture Behavioral of Rx_accumulator is


----------------------------------------------------------------------------------
-- SIGNALS declaration
----------------------------------------------------------------------------------

	signal address_Reg : STD_LOGIC_VECTOR(10 downto 0) := (others => '0');	  	-- 11-bit address position for read
	signal address_RAM_read_Reg : STD_LOGIC_VECTOR(9 downto 0) := (others => '0');	-- 10-bit address of memory area for read
	signal address_RAM_write_Reg : STD_LOGIC_VECTOR(9 downto 0) := (others => '0');	-- 10-bit address of memory area for write
	signal data_in_Reg : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');		-- resized data in
	signal data_out_Reg : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');		-- accumulated data out
	signal first_write_Reg : STD_LOGIC := '1';	-- first write signal
	signal repetition_number_Reg : STD_LOGIC_VECTOR(31 downto 0) := X"00000001";		-- number of repetition

	type acc_RAM is array(0 to 1023) of STD_LOGIC_VECTOR(31 downto 0);
   signal accumulator : acc_RAM;		-- memory for input data



begin


	
	ACC_NUMBER <= repetition_number_Reg;
	DATA_OUT <= data_out_Reg;
	data_in_Reg <= STD_LOGIC_VECTOR("00000000" & UNSIGNED(DATA_IN));
	
	

	process (CLK) begin
		if rising_edge(CLK) then
			if (RST = '1') then
				first_write_Reg <= '1';
				address_Reg <= (others => '0');
				address_RAM_read_Reg <= (others => '0');
				address_RAM_write_Reg <= (others => '0');
				DV <= '0';
				data_out_Reg <= (others => '0');
				repetition_number_Reg <= X"00000001";
			else			
				DV <= '0';
					
				if (UNLOAD = '1') then
					if (address_Reg < "10000000000") then
						DV <= '1';							
						address_Reg <= STD_LOGIC_VECTOR(UNSIGNED(address_Reg) + 1);
						address_RAM_read_Reg <= STD_LOGIC_VECTOR(UNSIGNED(address_Reg(9 downto 0)) + 1);
					end if;
				
				elsif (WE = '1') then
					if (first_write_Reg = '1') then						
						accumulator(TO_INTEGER(UNSIGNED(address_RAM_write_Reg))) <= data_in_Reg;						
						address_RAM_write_Reg <= STD_LOGIC_VECTOR(UNSIGNED(address_RAM_write_Reg) + 1);
						
						if (address_RAM_write_Reg = "1111111111") then
							first_write_Reg <= '0';
						end if;
					else	
						accumulator(TO_INTEGER(UNSIGNED(address_RAM_write_Reg))) <= STD_LOGIC_VECTOR(UNSIGNED(accumulator(TO_INTEGER(UNSIGNED(address_RAM_write_Reg)))) + UNSIGNED(data_in_Reg));						
						address_RAM_write_Reg <= STD_LOGIC_VECTOR(UNSIGNED(address_RAM_write_Reg) + 1);
						
						if	(address_RAM_write_Reg = "1111111111") then
							repetition_number_Reg <= STD_LOGIC_VECTOR(UNSIGNED(repetition_number_Reg) + 1);
						end if;
					end if;
				end if;
				
				data_out_Reg <= accumulator(TO_INTEGER(UNSIGNED(address_RAM_read_Reg)));
				
			end if;
		end if;
	end process;
			



end Behavioral;
