LIBRARY ieee;
USE ieee.numeric_std.all;
USE ieee.std_logic_1164.all;

ENTITY epwm_spi IS
	GENERIC
	(
		COUNT			:	positive := 1								--! pocet periferii ePWM
	);
	PORT
	(
		CLK				:	IN std_logic;								--! interni hodinovy signal
		RST				:	IN std_logic;								--! signal reset aktivni v logicke 1

		SCLK			:	IN std_logic;								--! Hodinovy signal SPI
		CS_N			:	IN std_logic;								--! Chip select signal SPI
		MOSI			:	IN std_logic;								--! Master Out Slave In SPI 
		MISO			:	OUT std_logic;								--! Master In Slave Out SPI		

		OUTPUT1			:	OUT std_logic_vector(15 DOWNTO 0);			--! vystup slouzici pro kontrolu dat

		TZ				:	IN std_logic_vector(5 DOWNTO 0);
		EPWMXA			:	OUT std_logic_vector(COUNT-1 DOWNTO 0);
		EPWMXB			: 	OUT std_logic_vector(COUNT-1 DOWNTO 0);
		EPWMxSOCA		:	OUT std_logic_vector(COUNT-1 DOWNTO 0);
		EPWMxSOCB		:	OUT std_logic_vector(COUNT-1 DOWNTO 0);
		EPWMxINTn		:  	OUT std_logic_vector(COUNT-1 DOWNTO 0)
	);
END epwm_spi;

ARCHITECTURE Behavioral OF epwm_spi IS

	SIGNAL CE			:	std_logic_vector(COUNT - 1 DOWNTO 0) := (OTHERS => '0');
	SIGNAL DIN			:	std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
	SIGNAL ADDR			:	std_logic_vector(7 DOWNTO 0) := (OTHERS => '0');

	type arr is array (0 to COUNT-1) of std_logic_vector(15 downto 0);
	SIGNAL DOUT: arr;

	SIGNAL EPWM_add		:	std_logic_vector(7 DOWNTO 0);
	SIGNAL EPWM_reg		:	std_logic_vector(7 DOWNTO 0);
	SIGNAL EPWM_val		:	std_logic_vector(15 DOWNTO 0);
	SIGNAL EPWM_vld		:	std_logic;
	SIGNAL EPWM_dat		:	std_logic_vector(15 DOWNTO 0);

BEGIN

	-- pri spravnem zpracovani dat Parserem priradi data do internich bufferu a zapise do registru

	PROCESS(CLK, RST)
	BEGIN
		IF rising_edge(CLK) THEN
			IF RST = '1' THEN
				FOR i IN 0 TO COUNT-1 LOOP
					CE(i)	 <= '0';
				END LOOP;
			ELSE
				IF(EPWM_vld = '1') THEN
					-- podminka jestli adresa zarizeni neni mimo rozsah
					IF ((to_integer(unsigned(EPWM_add))) <= COUNT) THEN
					
						ADDR <= EPWM_reg;
						DIN  <= EPWM_val;
						
						-- hromadny zapis
						IF((to_integer(unsigned(EPWM_add))) = 0) THEN
							FOR i IN 0 TO COUNT-1 LOOP
								CE(i)	 <= '1';
							END LOOP;

						-- jednotlivy zapis
						ELSE
							CE(to_integer(unsigned(EPWM_add))-1)	 <= '1';
						END IF;
						
					END IF;

					-- multiplexer cteni ePWM registru
					EPWM_dat <= DOUT(to_integer(unsigned(EPWM_add)));
					
				ELSE
					FOR i IN 0 TO COUNT-1 LOOP
						CE(i)	 <= '0';
					END LOOP;
				END IF;
			END IF;
		END IF;
	END PROCESS;

	OUTPUT1 <= DIN;

	spi_parser: ENTITY work.spi_parser
	PORT MAP
	(	
		CLK			=> CLK,
		RST 		=> RST,
		SCLK 		=> SCLK,
		CS_N 		=> CS_N,
		MOSI 		=> MOSI,
		MISO 		=> MISO,

		EPWM_add 	=> EPWM_add,
		EPWM_reg 	=> EPWM_reg,
		EPWM_val 	=> EPWM_val,
		EPWM_vld 	=> EPWM_vld,
		EPWM_dat	=> EPWM_dat
	);
	
	GenerateEPWM: FOR i IN 0 TO COUNT-1 GENERATE
		epwm: ENTITY work.epwm_registers
			PORT MAP
			(
				CLK			=> CLK,
				RST 		=> RST,
				CE			=> CE(i),
				DIN			=> DIN,
				DOUT		=> DOUT(i),
				ADDR		=> ADDR,

				EPWMxSYNCI	=> '0',
				TZ			=> TZ,
				EPWMxSYNCO	=> open,
				EPWMXA		=> EPWMXA(i),
				EPWMXB		=> EPWMXB(i),
				EPWMxSOCA	=> EPWMxSOCA(i),
				EPWMxSOCB	=> EPWMxSOCB(i),
				EPWMxINTn	=> EPWMxINTn(i)
			);
	END GENERATE GenerateEPWM;

END Behavioral;