
use work.AdOCNet_2DMesh_pkg.all;

----------------------------------------------------------------------------------------------------
-- Actual File Name      = AdOCNet.vhd
-- Title & purpose       = ADACSYS On-Chip-Network - Network architecture for system on chip intercommunication
-- Author                = Automaticaly generated by YANGO netlist generator - made by Matthieu PAYET (ADACSYS) - matthieu.payet@adacsys.com
-- Creation Date         = 2015-02-09 11:39
-- Version               = 0.1
-- Simple Description    = Network architecture for system on chip intercommunication
-- Specific issues       = 
-- Speed                 = 
-- Area estimates        = 
-- Tools (version)       = 13.1
-- HDL standard followed = VHDL 2001 standard
-- Revisions & ECOs      = 1.0
----------------------------------------------------------------------------------------------------
	
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_arith.all;
--------------------------------------------------------------------------------
-- ENTITY: AdOCNet - Network architecture for system on chip intercommunication
--------------------------------------------------------------------------------
entity AdOCNet_2DMesh is 
	generic(
		DimY                  : natural             := 3;
		DimX                  : natural             := 3;
		FlitWidth             : natural             := 16;
		NbInputs_Table        : DIMX_x_DIMY_NUMERIC;
		NbOutputs_Table       : DIMX_x_DIMY_NUMERIC;
		InputFifoDepth_Table  : DIMX_x_DIMY_NUMERIC);
	port(
		AckTx    : IN  std_logic_vector(DimX*DimY-1 downto 0);
		DataIn   : IN  FLITS(DimX*DimY-1 downto 0);
		AckRx    : OUT std_logic_vector(DimX*DimY-1 downto 0);
		Tx       : OUT std_logic_vector(DimX*DimY-1 downto 0);
		DataOut  : OUT FLITS(DimX*DimY-1 downto 0);
		Rx       : IN  std_logic_vector(DimX*DimY-1 downto 0);
		Reset    : IN  std_logic;
		Clock    : IN  std_logic
	);
end entity AdOCNet_2DMesh;

--------------------------------------------------------------------------------
-- ARCHITECTURE: RTL - Network architecture for system on chip communication
--------------------------------------------------------------------------------
architecture RTL of AdOCNet_2DMesh is

	type ROUTERS_DATA is array(natural range DimX*DimY-1 downto 0) of FLITS(4 downto 0);
	type ROUTERS_BITS is array(natural range DimX*DimY-1 downto 0) of std_logic_vector(4 downto 0);

	signal DataIn_i  : ROUTERS_DATA;
	signal Rx_i      : ROUTERS_BITS;
	signal AckRx_i   : ROUTERS_BITS;
	signal DataOut_i : ROUTERS_DATA;
	signal Tx_i      : ROUTERS_BITS;
	signal AckTx_i   : ROUTERS_BITS;
	
	constant NbPorts : integer := 5;
	constant NORTH : integer := 0;
	constant SOUTH : integer := 1;
	constant EAST  : integer := 2;
	constant WEST  : integer := 3;
	constant LOCAL : integer := 4;
	
begin
	-----------------------------------------------------------------------
	GEN_Y : FOR iy in 0 to DimY-1 generate
		GEN_X : FOR ix in 0 to DimX-1 generate  
			GEN_ROUTER_BOTTOM: if(iy = 0) generate
			---------------------------------------------------
				GEN_ROUTER_BOTTOM_LEFT: if(ix = 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_BOTTOM_LEFT;
			------------------------------------------------------
				GEN_ROUTER_BOTTOM_RIGHT: if(ix = DimX-1) and (ix /= 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_BOTTOM_RIGHT;
			------------------------------------------------------
				GEN_ROUTER_BOTTOM_CENTRAL: if(ix > 0 AND ix < DimX-1) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_BOTTOM_CENTRAL;
			end generate GEN_ROUTER_BOTTOM;
			
			GEN_ROUTER_TOP: if (iy = DimY-1) and (iy /= 0) generate
			---------------------------------------------------
				GEN_ROUTER_TOP_LEFT: if(ix = 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_TOP_LEFT;
			------------------------------------------------------
				GEN_ROUTER_TOP_RIGHT: if(ix = DimX-1) and (ix /= 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_TOP_RIGHT;
			------------------------------------------------------
				GEN_ROUTER_TOP_CENTRAL: if(ix > 0 AND ix < DimX-1) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_TOP_CENTRAL;
			end generate GEN_ROUTER_TOP;
			
			GEN_ROUTER_MIDDLE: if(iy > 0 and iy < DimY-1) generate
			---------------------------------------------------
				GEN_ROUTER_MIDDLE_LEFT: if(ix = 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_MIDDLE_LEFT;
			------------------------------------------------------
				GEN_ROUTER_MIDDLE_RIGHT: if(ix = DimX-1) and (ix /= 0) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_MIDDLE_RIGHT;
			------------------------------------------------------
				GEN_ROUTER_MIDDLE_CENTRAL: if(ix > 0 AND ix < DimX-1) generate
					Router: entity work.Router_2DMesh(RTL)
						generic map(
							X_Local => ix,
							Y_Local => iy,
							FlitWidth => FlitWidth,
							NbOutputs => 5,
							NbInputs => 5,
							InputFifoDepth => InputFifoDepth_Table(iy*DimX+ix)
							)
						port map(
							Reset => Reset,
							Clock => Clock,
							HS_DataIn => DataIn_i(iy*DimX+ix),
							HS_Rx => Rx_i(iy*DimX+ix),
							HS_AckRx => AckRx_i(iy*DimX+ix),
							HS_DataOut => DataOut_i(iy*DimX+ix),
							HS_Tx => Tx_i(iy*DimX+ix),
							HS_AckTx => AckTx_i(iy*DimX+ix)
							);
				end generate GEN_ROUTER_MIDDLE_CENTRAL;
			end generate GEN_ROUTER_MIDDLE;
		end generate GEN_X;
	end generate GEN_Y; 
	-----------------------------------------------------------------------
	
	GEN_CONNECTION_Y: FOR iiy in 0 to DimY-1 generate
		GEN_CONNECTION_X: FOR iix in 0 to DimX-1 generate
			GEN_CONNECTION_PORTS: FOR iid in 0 to NbPorts-1 generate
				GEN_CONNECTION_N: if(iid = 0) generate
					GEN_NO_CONNECTION_NS: if(iiy = DimY-1) generate
						DataIn_i(iiy*DimX+iix)(NORTH) <= (others => '0');
						Rx_i(iiy*DimX+iix)(NORTH)     <= '0';
--						AckRx_i(iiy*DimX+iix)(NORTH)  <= '0';
					end generate GEN_NO_CONNECTION_NS;
					GEN_CONNECTION_NS: if(iiy < DimY-1) generate
						DataIn_i(iiy*DimX+iix)(NORTH) <= DataOut_i((iiy+1)*DimX+iix)(SOUTH);
						Rx_i(iiy*DimX+iix)(NORTH)     <= Tx_i((iiy+1)*DimX+iix)(SOUTH);
						AckTx_i((iiy+1)*DimX+iix)(SOUTH) <= AckRx_i(iiy*DimX+iix)(NORTH);
					end generate  GEN_CONNECTION_NS;
				end generate GEN_CONNECTION_N;

				GEN_CONNECTION_S: if(iid = 1) generate
					GEN_NO_CONNECTION_SN: if(iiy = 0) generate
						DataIn_i(iiy*DimX+iix)(SOUTH) <= (others => '0');
						Rx_i(iiy*DimX+iix)(SOUTH)     <= '0';
--						AckRx_i(iiy*DimX+iix)(SOUTH)  <= '0';
					end generate GEN_NO_CONNECTION_SN;
					GEN_CONNECTION_SN:   if(iiy > 0) generate
						DataIn_i(iiy*DimX+iix)(SOUTH) <= DataOut_i((iiy-1)*DimX+iix)(NORTH);
						Rx_i(iiy*DimX+iix)(SOUTH)     <= Tx_i((iiy-1)*DimX+iix)(NORTH);
						AckTx_i((iiy-1)*DimX+iix)(NORTH) <= AckRx_i(iiy*DimX+iix)(SOUTH);
					end generate GEN_CONNECTION_SN;
				end generate GEN_CONNECTION_S;

				GEN_CONNECTION_E: if(iid = 2) generate
					-- 
					GEN_NO_CONNECTION_EW: if(iix = DimX-1) generate
						DataIn_i(iiy*DimX+iix)(EAST) <= (others => '0');
						Rx_i(iiy*DimX+iix)(EAST)     <= '0';
--						AckRx_i(iiy*DimX+iix)(EAST)  <= '0';
					end generate GEN_NO_CONNECTION_EW;     
					GEN_CONNECTION_EW: if(iix < DimX-1 ) generate
						DataIn_i(iiy*DimX+iix)(EAST)  <= DataOut_i(iiy*DimX+iix+1)(WEST);
						Rx_i(iiy*DimX+iix)(EAST)      <= Tx_i(iiy*DimX+iix+1)(WEST);
						AckTx_i(iiy*DimX+iix+1)(WEST) <= AckRx_i(iiy*DimX+iix)(EAST);
					end generate GEN_CONNECTION_EW;  
				end generate GEN_CONNECTION_E;

				GEN_CONNECTION_W: if(iid = 3) generate
					GEN_NO_CONNECTION_WE: if(iix = 0) generate
						DataIn_i(iiy*DimX+iix)(WEST) <= (others => '0');
						Rx_i(iiy*DimX+iix)(WEST)     <= '0';
--						AckRx_i(iiy*DimX+iix)(WEST)  <= '0';
					end generate GEN_NO_CONNECTION_WE;
					GEN_CONNECTION_WE: if(iix > 0) generate
						DataIn_i(iiy*DimX+iix)(WEST)  <= DataOut_i(iiy*DimX+iix-1)(EAST);
						Rx_i(iiy*DimX+iix)(WEST)      <= Tx_i(iiy*DimX+iix-1)(EAST);
						AckTx_i(iiy*DimX+iix-1)(EAST) <= AckRx_i(iiy*DimX+iix)(WEST);
					end generate GEN_CONNECTION_WE;
				end generate GEN_CONNECTION_W;
				
				GEN_CONNECTION_LOCAL: if(iid = 4) generate
					DataIn_i(iiy*DimX+iix)(LOCAL) <= DataIn(iiy*DimX+iix);
					Rx_i(iiy*DimX+iix)(LOCAL)     <= Rx(iiy*DimX+iix);
					AckRx(iiy*DimX+iix)           <= AckRx_i(iiy*DimX+iix)(LOCAL);
					DataOut(iiy*DimX+iix)         <= DataOut_i(iiy*DimX+iix)(LOCAL);
					Tx(iiy*DimX+iix)              <= Tx_i(iiy*DimX+iix)(LOCAL);
					AckTx_i(iiy*DimX+iix)(LOCAL)  <= AckTx(iiy*DimX+iix);
				end generate GEN_CONNECTION_LOCAL;
				
			end generate GEN_CONNECTION_PORTS;
		end generate GEN_CONNECTION_X;
	end generate  GEN_CONNECTION_Y;
	-----------------------------------------------------------------

end architecture RTL;

