----------------------------------------------------------------------------------
-- Company: 
-- Engineer: Darcy Cook
-- 
-- Create Date:    13:57:49 03/30/2009 
-- Design Name: 
-- Module Name:    MPSoC_top - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: This is the top module used to connect the system together
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity MPSoC_top is
	generic
	(  		
		DATA_WIDTH                     : integer              := 16;
		GLB_MEM_SIZE						 : integer					:= 8192; -- this must be 2^ADDR_WIDTH to ensure that there are no dead addresses
		ADDR_WIDTH							 : integer              := 13;
		NUM_MICROS                     : integer              := 4;
		NUM_ACTIVE_MICROS					 : integer					:= 4;
		MEM_CLK_DIV 		             : integer              := 10;
		NUM_DFG_NODES                  : integer              := 16;		
		ITER_NUM_WIDTH                 : integer              := 16;
		MAX_ITER								 : integer              := 500;		
		DFG_NODE_WIDTH						 : integer              := 8;
		PROC_ADDR_WIDTH 					 : integer 					:= 4;
		INFO_ADDR_WIDTH 					 : integer 					:= 4;
		SNOOPY_DATA_WIDTH					 : integer 					:= 32
	);
	Port 
	( 
		clk : in  STD_LOGIC;
		reset : in  STD_LOGIC;
		
		RS232_RX : in std_logic;
		RS232_TX : out std_logic;
		
		LEDs_4Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 3);
		DIPSWs_4Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 3);
		PushButtons_5Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 4)		
	);
end MPSoC_top;

architecture Behavioral of MPSoC_top is
	signal mem_clk : std_logic;
	
	signal global_mem_addr : STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);	
	signal global_mem_data : STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
	signal global_mem_read_write : std_logic;
	signal global_mem_CE : std_logic;
	
	signal proc_addr_bus : STD_LOGIC_VECTOR ((NUM_MICROS*ADDR_WIDTH)-1 downto 0);
	signal proc_data_bus : STD_LOGIC_VECTOR ((NUM_MICROS*DATA_WIDTH)-1 downto 0);
	signal mem_cntrl_data_bus : STD_LOGIC_VECTOR ((NUM_MICROS*DATA_WIDTH)-1 downto 0);
	signal proc_acks : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	signal mem_ctrl_acks : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0) := "0";
	signal proc_read_write : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	signal proc_mem_request : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	
	signal start_task_control : std_logic := '1';
	signal executing_task : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	signal task_iteration_num : STD_LOGIC_VECTOR ((NUM_MICROS*ITER_NUM_WIDTH)-1 downto 0);
	signal start_exec_task : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	signal proc_done_tasks : STD_LOGIC_VECTOR (NUM_MICROS-1 downto 0);
	signal all_procs_done_tasks : std_logic := '0'; 
	signal dfg_node : STD_LOGIC_VECTOR ((NUM_MICROS*DFG_NODE_WIDTH)-1 downto 0);
	signal task_control_reset : std_logic := '1';
	
	signal snoopy_proc_task_addr : std_logic_vector(PROC_ADDR_WIDTH-1 downto 0);
	signal snoopy_info_addr : std_logic_vector(INFO_ADDR_WIDTH-1 downto 0);
	signal snoopy_data : std_logic_vector(SNOOPY_DATA_WIDTH-1 downto 0);	
		
	COMPONENT Multiprocs
	PORT(
		fpga_0_RS232_Uart_1_RX_pin : IN std_logic;
		sys_clk_pin : IN std_logic;
		sys_rst_pin : IN std_logic;		
		fpga_0_LEDs_4Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 3);
		fpga_0_DIPSWs_4Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 3);
		fpga_0_PushButtons_5Bit_GPIO_IO_pin : INOUT std_logic_vector(0 to 4);      
		fpga_0_RS232_Uart_1_TX_pin : OUT std_logic;
		fpga_0_net_gnd_pin : OUT std_logic;
		fpga_0_net_gnd_1_pin : OUT std_logic;
		fpga_0_net_gnd_2_pin : OUT std_logic;
		fpga_0_net_gnd_3_pin : OUT std_logic;
		fpga_0_net_gnd_4_pin : OUT std_logic;
		fpga_0_net_gnd_5_pin : OUT std_logic;
		fpga_0_net_gnd_6_pin : OUT std_logic;
		Proc0_External_Mem_Data_In_pin : IN std_logic_vector(15 downto 0);
		Proc0_External_Mem_Ack_in_pin : IN std_logic;
		Proc0_iteration_num_pin : IN std_logic_vector(15 downto 0);
		Proc0_start_exec_pin : IN std_logic;
		Proc0_proc_done_pin : IN std_logic;
		Proc0_all_procs_done_pin : IN std_logic;    
		Proc0_External_Mem_Addr_pin : OUT std_logic_vector(12 downto 0);
		Proc0_External_Mem_Data_Out_pin : OUT std_logic_vector(15 downto 0);
		Proc0_External_Mem_RD_WR_pin : OUT std_logic;
		Proc0_External_Mem_Request_pin : OUT std_logic;
		Proc0_External_Mem_Ack_out_pin : OUT std_logic;
		Proc0_start_task_control_pin : OUT std_logic;
		Proc0_dfg_node_pin : IN std_logic_vector(7 downto 0);
		Proc0_executing_pin : OUT std_logic;
		Proc1_External_Mem_Data_In_pin : IN std_logic_vector(15 downto 0);
		Proc1_External_Mem_Ack_in_pin : IN std_logic;
		Proc1_iteration_num_pin : IN std_logic_vector(15 downto 0);
		Proc1_start_exec_pin : IN std_logic;
		Proc1_dfg_node_pin : IN std_logic_vector(7 downto 0);
		Proc1_proc_done_pin : IN std_logic;
		Proc1_all_procs_done_pin : IN std_logic;
		Proc1_External_Mem_Addr_pin : OUT std_logic_vector(12 downto 0);
		Proc1_External_Mem_Data_Out_pin : OUT std_logic_vector(15 downto 0);
		Proc1_External_Mem_RD_WR_pin : OUT std_logic;
		Proc1_External_Mem_Request_pin : OUT std_logic;
		Proc1_External_Mem_Ack_out_pin : OUT std_logic;		
		Proc1_executing_pin : OUT std_logic;
		
		Proc2_External_Mem_Data_In_pin : IN std_logic_vector(15 downto 0);
		Proc2_External_Mem_Ack_in_pin : IN std_logic;
		Proc2_iteration_num_pin : IN std_logic_vector(15 downto 0);
		Proc2_start_exec_pin : IN std_logic;
		Proc2_dfg_node_pin : IN std_logic_vector(7 downto 0);
		Proc2_proc_done_pin : IN std_logic;
		Proc2_all_procs_done_pin : IN std_logic;
		Proc2_External_Mem_Addr_pin : OUT std_logic_vector(12 downto 0);
		Proc2_External_Mem_Data_Out_pin : OUT std_logic_vector(15 downto 0);
		Proc2_External_Mem_RD_WR_pin : OUT std_logic;
		Proc2_External_Mem_Request_pin : OUT std_logic;
		Proc2_External_Mem_Ack_out_pin : OUT std_logic;		
		Proc2_executing_pin : OUT std_logic;
		
		Proc3_External_Mem_Data_In_pin : IN std_logic_vector(15 downto 0);
		Proc3_External_Mem_Ack_in_pin : IN std_logic;
		Proc3_iteration_num_pin : IN std_logic_vector(15 downto 0);
		Proc3_start_exec_pin : IN std_logic;
		Proc3_dfg_node_pin : IN std_logic_vector(7 downto 0);
		Proc3_proc_done_pin : IN std_logic;
		Proc3_all_procs_done_pin : IN std_logic;
		Proc3_External_Mem_Addr_pin : OUT std_logic_vector(12 downto 0);
		Proc3_External_Mem_Data_Out_pin : OUT std_logic_vector(15 downto 0);
		Proc3_External_Mem_RD_WR_pin : OUT std_logic;
		Proc3_External_Mem_Request_pin : OUT std_logic;
		Proc3_External_Mem_Ack_out_pin : OUT std_logic;		
		Proc3_executing_pin : OUT std_logic;
		
		snoopy_data_pin : IN std_logic_vector(31 downto 0);
		snoopy_proc_task_addr_pin : OUT std_logic_vector(3 downto 0);
		snoopy_info_addr_pin : OUT std_logic_vector(3 downto 0)
		);
	END COMPONENT;

	

begin
	LEDs_4Bit_GPIO_IO_pin(0) <= '0';
	LEDs_4Bit_GPIO_IO_pin(1) <= '0';
	LEDs_4Bit_GPIO_IO_pin(2) <= '0';
	LEDs_4Bit_GPIO_IO_pin(3) <= '0';
	
	task_control_reset <= start_task_control or (not reset);
	all_procs_done_tasks <= proc_done_tasks(0); -- and all proc_done_tasks together here
	
	CLK_DIVIDE_I : entity clk_divide
   generic map
   (     
      DIV_FACTOR => MEM_CLK_DIV		
   )
   port map
   (
      clk_in => clk,
		reset => not reset,
		clk_out => mem_clk		
   );

	MEM_CNTL_I : entity memory_controller
   generic map
   (     
      NUM_MICROS => NUM_MICROS,		
		D_WIDTH => DATA_WIDTH,
		A_WIDTH => ADDR_WIDTH		
   )
   port map
   (
      clk => mem_clk,
		reset => not reset,
		micro_addr_buses => proc_addr_bus,
      micro_data_out_buses => mem_cntrl_data_bus,
		micro_data_in_buses => proc_data_bus,
      micro_mem_requests => proc_mem_request,
      micro_ack_ins => proc_acks,
      micro_ack_outs => mem_ctrl_acks,
      micro_read_write => proc_read_write,
      mem_addr => global_mem_addr,
      mem_data => global_mem_data,
      mem_read_write => global_mem_read_write,
		mem_CE => global_mem_CE		
   );
		
	GLB_MEM_I : entity global_memory
   generic map
   (     
		D_WIDTH => DATA_WIDTH,		
		A_WIDTH => ADDR_WIDTH		
   )
   port map
   (
      clk => mem_clk,
		reset => not reset,
		CE => global_mem_CE,
      read_write => global_mem_read_write,
      data => global_mem_data, 
      address => global_mem_addr				
   );
		
	Inst_Multiprocs: Multiprocs PORT MAP(
		fpga_0_RS232_Uart_1_RX_pin => RS232_RX,
		fpga_0_RS232_Uart_1_TX_pin => RS232_TX,
		--fpga_0_LEDs_4Bit_GPIO_IO_pin => LEDs_4Bit_GPIO_IO_pin,
		fpga_0_DIPSWs_4Bit_GPIO_IO_pin => DIPSWs_4Bit_GPIO_IO_pin,
		fpga_0_PushButtons_5Bit_GPIO_IO_pin => PushButtons_5Bit_GPIO_IO_pin,
		--fpga_0_net_gnd_pin => ,
		--fpga_0_net_gnd_1_pin => ,
		--fpga_0_net_gnd_2_pin => ,
		--fpga_0_net_gnd_3_pin => ,
		--fpga_0_net_gnd_4_pin => ,
		--fpga_0_net_gnd_5_pin => ,
		--fpga_0_net_gnd_6_pin => ,
		sys_clk_pin => clk,
		sys_rst_pin => reset,
		Proc0_External_Mem_Addr_pin => proc_addr_bus(ADDR_WIDTH-1 downto 0),
		Proc0_External_Mem_Ack_in_pin => mem_ctrl_acks(0),		
		Proc0_External_Mem_Data_Out_pin => proc_data_bus(DATA_WIDTH-1 downto 0),
		Proc0_External_Mem_Data_In_pin => mem_cntrl_data_bus(DATA_WIDTH-1 downto 0),
		Proc0_External_Mem_RD_WR_pin => proc_read_write(0),
		Proc0_External_Mem_Request_pin => proc_mem_request(0),
		Proc0_External_Mem_Ack_out_pin => proc_acks(0),
		Proc0_start_task_control_pin => start_task_control,
		Proc0_executing_pin => executing_task(0),
		Proc0_iteration_num_pin => task_iteration_num(ITER_NUM_WIDTH-1 downto 0),
		Proc0_start_exec_pin => start_exec_task(0),
		Proc0_proc_done_pin => proc_done_tasks(0),
		Proc0_all_procs_done_pin => all_procs_done_tasks, 	
		Proc0_dfg_node_pin => dfg_node(DFG_NODE_WIDTH-1 downto 0),
		
		Proc1_External_Mem_Data_In_pin => mem_cntrl_data_bus((2*DATA_WIDTH)-1 downto DATA_WIDTH),
		Proc1_External_Mem_Ack_in_pin => mem_ctrl_acks(1),
		Proc1_iteration_num_pin => task_iteration_num((2*ITER_NUM_WIDTH)-1 downto ITER_NUM_WIDTH),
		Proc1_start_exec_pin => start_exec_task(1),
		Proc1_dfg_node_pin => dfg_node((2*DFG_NODE_WIDTH)-1 downto DFG_NODE_WIDTH),
		Proc1_proc_done_pin => proc_done_tasks(1),
		Proc1_all_procs_done_pin => all_procs_done_tasks, 
		Proc1_External_Mem_Addr_pin => proc_addr_bus((2*ADDR_WIDTH)-1 downto ADDR_WIDTH),
		Proc1_External_Mem_Data_Out_pin => proc_data_bus((2*DATA_WIDTH)-1 downto DATA_WIDTH),
		Proc1_External_Mem_RD_WR_pin => proc_read_write(1),
		Proc1_External_Mem_Request_pin => proc_mem_request(1),
		Proc1_External_Mem_Ack_out_pin => proc_acks(1),		
		Proc1_executing_pin => executing_task(1),
		
		Proc2_External_Mem_Data_In_pin => mem_cntrl_data_bus((3*DATA_WIDTH)-1 downto 2*DATA_WIDTH),
		Proc2_External_Mem_Ack_in_pin => mem_ctrl_acks(2),
		Proc2_iteration_num_pin => task_iteration_num((3*ITER_NUM_WIDTH)-1 downto 2*ITER_NUM_WIDTH),
		Proc2_start_exec_pin => start_exec_task(2),
		Proc2_dfg_node_pin => dfg_node((3*DFG_NODE_WIDTH)-1 downto 2*DFG_NODE_WIDTH),
		Proc2_proc_done_pin => proc_done_tasks(2),
		Proc2_all_procs_done_pin => all_procs_done_tasks, 
		Proc2_External_Mem_Addr_pin => proc_addr_bus((3*ADDR_WIDTH)-1 downto 2*ADDR_WIDTH),
		Proc2_External_Mem_Data_Out_pin => proc_data_bus((3*DATA_WIDTH)-1 downto 2*DATA_WIDTH),
		Proc2_External_Mem_RD_WR_pin => proc_read_write(2),
		Proc2_External_Mem_Request_pin => proc_mem_request(2),
		Proc2_External_Mem_Ack_out_pin => proc_acks(2),		
		Proc2_executing_pin => executing_task(2),
		
		Proc3_External_Mem_Data_In_pin => mem_cntrl_data_bus((4*DATA_WIDTH)-1 downto 3*DATA_WIDTH),
		Proc3_External_Mem_Ack_in_pin => mem_ctrl_acks(3),
		Proc3_iteration_num_pin => task_iteration_num((4*ITER_NUM_WIDTH)-1 downto 3*ITER_NUM_WIDTH),
		Proc3_start_exec_pin => start_exec_task(3),
		Proc3_dfg_node_pin => dfg_node((4*DFG_NODE_WIDTH)-1 downto 3*DFG_NODE_WIDTH),
		Proc3_proc_done_pin => proc_done_tasks(3),
		Proc3_all_procs_done_pin => all_procs_done_tasks, 
		Proc3_External_Mem_Addr_pin => proc_addr_bus((4*ADDR_WIDTH)-1 downto 3*ADDR_WIDTH),
		Proc3_External_Mem_Data_Out_pin => proc_data_bus((4*DATA_WIDTH)-1 downto 3*DATA_WIDTH),
		Proc3_External_Mem_RD_WR_pin => proc_read_write(3),
		Proc3_External_Mem_Request_pin => proc_mem_request(3),
		Proc3_External_Mem_Ack_out_pin => proc_acks(3),		
		Proc3_executing_pin => executing_task(3),
				
		snoopy_proc_task_addr_pin => snoopy_proc_task_addr,
		snoopy_info_addr_pin => snoopy_info_addr,
		snoopy_data_pin => snoopy_data	
	);	
	
	TASK_CONTROL_I : entity dfg_scheduler
   generic map
   (     
		NUM_DFG_NODES => NUM_DFG_NODES,		
		NUM_MICROS => NUM_MICROS,
		NUM_ACTIVE_MICROS => NUM_ACTIVE_MICROS,
		ITER_NUM_WIDTH => ITER_NUM_WIDTH,
		MAX_ITER => MAX_ITER,
		DFG_NODE_WIDTH => DFG_NODE_WIDTH	
   )
   port map
   (
      clk => clk,
      reset => task_control_reset,
		executing => executing_task,
		iteration_num => task_iteration_num,      
      start_exec => start_exec_task,
      dfg_node => dfg_node,
		proc_done => proc_done_tasks		
   );
	
	SNOOPY_I : entity snoopy
   generic map
   (     
		NUM_MICROS => NUM_MICROS,
		NUM_DFG_NODES => NUM_DFG_NODES,
		DFG_NODE_WIDTH => DFG_NODE_WIDTH,
		PROC_ADDR_WIDTH => PROC_ADDR_WIDTH,
		INFO_ADDR_WIDTH => INFO_ADDR_WIDTH,
		DATA_WIDTH => SNOOPY_DATA_WIDTH
   )
   port map
   (
      clk => clk,
      reset => not reset,
		mem_requests => proc_mem_request,
		executing_task => executing_task,
		start_task_control => task_control_reset,
		proc_tasks_done => proc_done_tasks,
		all_tasks_done => all_procs_done_tasks,
		dfg_node => dfg_node,
		
		proc_task_addr => snoopy_proc_task_addr,
		info_addr => snoopy_info_addr,
		data => snoopy_data			
   );

end Behavioral;

