----------------------------------------------------------------------------------
-- Company:  University of Connecticut
-- Engineer: Igor Senderovich
-- 
-- Create Date:    10:22:32 09/24/2007 
-- Design Name:    Multiplexed Registers to simulate Eth. control regs.
-- Module Name:    Regs - Behavioral 
-- Description: 	 256 x 8bit muxed register bank
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Regs is
    Port ( Clk : in  STD_LOGIC;
           Rst : in  STD_LOGIC;
           Go_GetPacket : in  STD_LOGIC_VECTOR (2 downto 0);
			  iINT_sug : in  STD_LOGIC;
			  iINT_type : in  STD_LOGIC_VECTOR (3 downto 0);
			  iINT : out STD_LOGIC;
           Wr : in  STD_LOGIC;
           Rd : in  STD_LOGIC;
           A : in  STD_LOGIC_VECTOR (7 downto 0);
           D : in  STD_LOGIC_VECTOR (7 downto 0);
           Q : out  STD_LOGIC_VECTOR (7 downto 0);
			  Done_Send : out STD_LOGIC
			  );
end Regs;

architecture Behavioral of Regs is
	component c_delay is
		Port ( Clk : in  STD_LOGIC;
           D : in  STD_LOGIC;
           Q : out  STD_LOGIC);
	end component;
	component Logger is
    Port ( Clk : in  STD_LOGIC;
           --Rst : in  STD_LOGIC;
           En : in  STD_LOGIC;
           A : in  STD_LOGIC_VECTOR (7 downto 0);
           D : in  STD_LOGIC_VECTOR (7 downto 0));
	end component;
	component read_file is
    Port ( Clk : in  STD_LOGIC;
           --Rst : in  STD_LOGIC;
           Go : in  STD_LOGIC;
			  filenum : in integer range 7 downto 0;
			  Ain : in  STD_LOGIC_VECTOR (7 downto 0);
           Wr : out  STD_LOGIC;
           A : out  STD_LOGIC_VECTOR (7 downto 0);
           D : out  STD_LOGIC_VECTOR (7 downto 0);
			  Done : out STD_LOGIC);
	end component;
	component write_file is
    Port ( Clk : in  STD_LOGIC;
           --Rst : in  STD_LOGIC;
           Go : in  STD_LOGIC;
			  --filenum : in integer range 7 downto 0;
			  Astart : in  STD_LOGIC_VECTOR (7 downto 0);
			  Astop : in  STD_LOGIC_VECTOR (7 downto 0);
           A : out  STD_LOGIC_VECTOR (7 downto 0);
           Din : in  STD_LOGIC_VECTOR (7 downto 0);
			  Done : out STD_LOGIC
			  );
	end component;

	type registers8bit is array (integer range <>) of STD_LOGIC_VECTOR (7 downto 0);
	signal reg : registers8bit (255 downto 0);

	component RxRegs is
    Port ( Clk : in  STD_LOGIC;
           Rst : in  STD_LOGIC;
           Wr : in  STD_LOGIC;
           A : in  STD_LOGIC_VECTOR (7 downto 0);
           D : in  STD_LOGIC_VECTOR (7 downto 0);
           Q : out  STD_LOGIC_VECTOR (7 downto 0));
	end component;

	signal TxBuf : registers8bit (127 downto 0);
	signal FlashMem : registers8bit (8191 downto 8185);

	signal intAddr :  integer range 255 downto 0;
   signal Q_int :  STD_LOGIC_VECTOR (7 downto 0);

   signal Rx_A :  STD_LOGIC_VECTOR (7 downto 0);
   signal Rx_A_fread :  STD_LOGIC_VECTOR (7 downto 0);
   signal RxAddr :  STD_LOGIC_VECTOR (7 downto 0);
   signal Rx_D :  STD_LOGIC_VECTOR (7 downto 0);
   signal Rx_Q :  STD_LOGIC_VECTOR (7 downto 0);
   signal Rx_Wr :  STD_LOGIC;
	signal filenum : integer range 7 downto 0;
   signal Go_GetPacket1bit :  STD_LOGIC;

   signal TxByte :  STD_LOGIC_VECTOR (7 downto 0);
   signal TxA :  STD_LOGIC_VECTOR (7 downto 0);
	signal Go_SendPacket : STD_LOGIC;
	signal SendPacket : STD_LOGIC;
	signal Done_Send_int : STD_LOGIC;
begin

	intAddr <= conv_integer(A);

	--u0: Logger port map (Clk, Wr, A, Q_int); --logging module that acts on falling edge of Wr

	u1: c_delay port map (Clk, SendPacket, Go_SendPacket);
	TxByte <= TxBuf(conv_integer(TxA(6 downto 0)));
	u2: write_file port map (Clk,Go_SendPacket,X"00", reg(88),TxA,TxByte,Done_Send_int);
	

	filenum <= conv_integer(Go_GetPacket);
	Go_GetPacket1bit <= Go_GetPacket(2) or Go_GetPacket(1) or Go_GetPacket(0);
	u3: read_file port map (Clk, Go_GetPacket1bit, filenum, X"00", Rx_Wr, Rx_A_fread, Rx_D);
	u4: RxRegs port map (Clk, Rst, Rx_Wr, Rx_A,Rx_D,Rx_Q);
	Rx_A <= Rx_A_fread when Rx_Wr='1' else RxAddr;

	RxAddr<=reg(23);
	

	Regs : process (Clk, Rst, Wr, Rd, Rx_Q)
	begin
	
		if (Rst = '1') then
			for i in 1 to 22 loop
				reg(i) <= X"FF";
			end loop;
			reg(23) <= X"00"; --RXFIFOHEAD pointer init. value
			for i in 24 to 30 loop
				reg(i) <= X"FF";
			end loop;
			
			-- Program packet max value
			--- header  Loc/Typ  Mask Data   CRC
			-- (  14  +    2  +   4  + 2*32 + 4 = 88  
			--  max byte long program packet)
			reg(31) <= X"00"; -- CPLENH init. value
			reg(32) <= X"58"; -- CPLENL init. value 
			--reg(32) <= X"28"; -- shorter CPLENL init. value 
			for i in 33 to 98 loop
				reg(i) <= X"FF";
			end loop;
			
			reg(99) <="00110000"; -- 0x63 INT0 -Interrupt reg. 0
			reg(100)<="00000000"; -- 0x64 INT0EN
			
			reg(105) <= X"1F";
			reg(104) <= X"FF";
			FlashMem(8185) <= X"FC";	FlashMem(8186) <= X"11";
			FlashMem(8187) <= X"22";	FlashMem(8188) <= X"33";
			FlashMem(8189) <= X"44";	FlashMem(8190) <= X"55";
			FlashMem(8191) <= X"66";
			
			reg(127)<="00000100"; -- 0x7F INT1 -Interrupt reg. 1
			reg(124)<="00000000"; -- 0x7D INT1EN

			reg(120)<="11110001"; -- 0x78 PHYCN -Phys. layer ctrl reg.
			--reg()<="00000000"; -- 0x00 Register
			reg(255)<="0000000" & Done_Send_int;
			
			iINT <= '1';
			
			
			for i in 127 downto 0 loop
				TxBuf(i) <= X"00";
			end loop;

		else
			if falling_edge(Clk) then
				if (iINT_sug='0') then
					reg(99) <= "0" & iINT_type(3 downto 1) & "0000";
					reg(127) <= "00000" & iINT_type(0) & "00";
					iINT <= '0';
				else
					if (Rd='1' and intAddr=127) then
						iINT <= '1';
					end if;
				end if;

				
			
				if (Wr = '1') then
					case intAddr is 
						when 4		=> TxBuf(conv_integer(reg(8) & reg(9)))<=D;
						when 83		=> SendPacket <= '1';
						when 99		=> reg(0) <= reg(0);  -- (do nothing if asked to
						when 127		=> reg(0) <= reg(0);  --  to write to INT regs)
						when 17		=> reg(23)<= X"00"; -- read RXFIFOHEAD (AutoRd addr)
																	-- beginning-1 on skipped packet
						when others => reg(intAddr) <= D;
					end case;
				else
					if (Rd = '1') then
						case intAddr is
							when 1		=> reg(23)<=reg(23)+X"01"; --uses AutoRd interface's RXFIFOHEAD pointer
							--when 2		=> RxAddr<=reg(9); reg(2) <= Rx_Q;  --uses random access RXADDRL pointer
							when 4		=> reg(4) <= TxBuf(conv_integer(reg(8) & reg(9))); --reading to Tx buffer
							when 5		=> if (reg(104)/=X"FF") then reg(104) <= reg(104) + X"01"; --auto-reading MAC addr from Flash Mem.
												else reg(104)<=X"FA"; end if;
																 --Note: only incrementing LSByte (MSByte always 0x1F in this case)
							when others	=> reg <= reg;
						end case;
					else
						SendPacket <= '0';
						reg <= reg;
						reg(1) <= Rx_Q;
						reg(5) <= FlashMem(conv_integer(reg(105) & reg(104) ));
					end if;
				end if;
			else
				reg <= reg;
			end if;
		end if;
	end process Regs;

	Q_int <= reg(intAddr);
	Q <= Q_int;
	
end Behavioral;