-- Company: BUSE
-- ENgineer: PAVEL SUNKA
-- 
-- Create Date:   2.5.2018
-- Module Name:   BCM_dynamic
-- Project Name:  RGB PANEL
-- Target Devices: 10M08
-----------------------------         ----------------------------
-- Description:  dynamicka BCM
-----------------------------         ----------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_signed.all;
--	use IEEE.std_logic_signed.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

--use IEEE.math_real.all;

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

entity BCM_dynam is
	Port(
		ARST        : in  STD_LOGIC;
		CLK         : in  std_logic;
		WEREN       : in  std_logic;
		NEW_TEST    : in  std_logic;
		FIRST       : in  std_logic;
		RGB1        : in  std_logic_vector(17 downto 0);
		RGB2        : in  std_logic_vector(17 downto 0);
		WRITE_BIT1  : IN  std_logic_vector(2 downto 0); -- vysledek vystupniho multipleexeru pro prvni R(2)GB(0) bez latence
		WRITE_BIT2  : IN  std_logic_vector(2 downto 0); -- vysledek vystupniho multipleexeru pro druhe R(2)GB(0) bez latence
		END_ROW     : out std_logic;
		ACTUAL_BCMO : out std_logic_vector(5 downto 0):="000001";
		NEXT_BCMO   : out std_logic_vector(5 downto 0)
	);

end BCM_dynam;

architecture Behavioral of BCM_dynam is

	--	component bit_cnt
	component bit_cnt
		port(
			SRST        : in  STD_LOGIC;
			CLK         : in  std_logic;
			INA1        : in  std_logic_vector(2 downto 0);
			INA2        : in  std_logic_vector(2 downto 0);
			INB         : in  std_logic_vector(5 downto 0);
			BCM_MEM_BIT : in  std_logic;
			EN_CNT      : in  std_logic;
			RES         : out std_logic_vector(10 downto 0)
		);
	end component bit_cnt;

	component alesb_11b
		port(
			DATAA : IN  STD_LOGIC_VECTOR(10 DOWNTO 0);
			DATAB : IN  STD_LOGIC_VECTOR(10 DOWNTO 0);
			ALB   : OUT STD_LOGIC
		);
	end component alesb_11b;

	signal two   : std_logic_vector(10 downto 0) := (others => '0'); --vybrane druhe bity (2) 
	signal three : std_logic_vector(10 downto 0) := (others => '0'); --vybrane treti bity (4)
	signal four  : std_logic_vector(10 downto 0) := (others => '0'); --vybrane ctvrte bity(8) 
	signal five  : std_logic_vector(10 downto 0) := (others => '0'); --vybrane pate bity  (16)
	signal six   : std_logic_vector(10 downto 0) := (others => '0'); --vybrane seste bity (32)

	signal rst_cnt       : std_logic;   -- reset counteru
	signal cmpr_res      : std_logic_vector(3 downto 0) := (others => '0'); -- vysledky komparatoru
	signal not_collision : std_logic;   -- pri '1' nenastava kolize

	signal two_three    : std_logic_vector(10 downto 0); -- vystup z multiplexeru po comparatoru 2 a 3
	signal fiv_four     : std_logic_vector(10 downto 0); -- vystup z multiplexeru po comparatoru 4 a 5
	signal six_fiv_four : std_logic_vector(10 downto 0); -- vystup z multiplexeru po comparatoru 4 a 5 a 6

	signal next_bcm_h : std_logic_vector(4 downto 0) := (others => '0'); -- pomocny signal pro vystup nasledujiciho BCM
	signal bcm_res    : std_logic_vector(5 downto 0) := (others => '0'); -- pomocny signal pro zapis do pameti a na vystup NEXT_BCM

	signal mem_res     : std_logic_vector(4 downto 0) := (others => '0'); --	vystupni pamet
	signal mem_res_rev : std_logic_vector(4 downto 0) := (others => '0'); -- reverz vystupni pameti
	signal mem_bcm     : std_logic_vector(4 downto 0) := "11110";-- vystup z pameti pro zbyvajici BCM

	signal actual_BCM : std_logic_vector(5 downto 0) := "100000"; -- aktualni BCM
	signal next_BCM   : std_logic_vector(5 downto 0) := "000001"; -- nasledujici BCM

	signal b1     : std_logic_vector(5 downto 0);
	signal b2     : std_logic_vector(5 downto 0);
	signal b3     : std_logic_vector(5 downto 0);
	signal b4     : std_logic_vector(5 downto 0);
	signal b5     : std_logic_vector(5 downto 0);
	signal switch : std_logic_vector(5 downto 0) := "000001";
begin

	b5      <= (RGB2(17) & RGB2(11) & RGB2(5) & RGB1(17) & RGB1(11) & RGB1(5));
	rst_cnt <= ARST or NEW_TEST;
	uCnt_6 : component bit_cnt
		port map(
			SRST        => rst_cnt,
			CLK         => CLK,
			INA1        => WRITE_BIT1,
			INA2        => WRITE_BIT2,
			INB         => b5,          --(RGB2(17) & RGB2(11) & RGB2(5) & RGB1(17) & RGB1(11) & RGB1(5)),
			BCM_MEM_BIT => mem_bcm(4),
			EN_CNT      => WEREN,
			RES         => six
		);

	b4 <= (RGB2(16) & RGB2(10) & RGB2(4) & RGB1(16) & RGB1(10) & RGB1(4));
	uCnt_5 : component bit_cnt
		port map(
			SRST        => rst_cnt,
			CLK         => CLK,
			INA1        => WRITE_BIT1,
			INA2        => WRITE_BIT2,
			INB         => b4,          --(RGB2(16) & RGB2(10) & RGB2(4) & RGB1(16) & RGB1(10) & RGB1(4)),
			BCM_MEM_BIT => mem_bcm(3),
			EN_CNT      => WEREN,
			RES         => five
		);

	b3 <= (RGB2(15) & RGB2(9) & RGB2(3) & RGB1(15) & RGB1(9) & RGB1(3));
	uCnt_4 : component bit_cnt
		port map(
			SRST        => rst_cnt,
			CLK         => CLK,
			INA1        => WRITE_BIT1,
			INA2        => WRITE_BIT2,
			INB         => b3,          --(RGB2(15) & RGB2(9) & RGB2(3) & RGB1(15) & RGB1(9) & RGB1(3)),
			BCM_MEM_BIT => mem_bcm(2),
			EN_CNT      => WEREN,
			RES         => four
		);
	b2 <= (RGB2(14) & RGB2(9) & RGB2(2) & RGB1(14) & RGB1(9) & RGB1(2));
	uCnt_3 : component bit_cnt
		port map(
			SRST        => rst_cnt,
			CLK         => CLK,
			INA1        => WRITE_BIT1,
			INA2        => WRITE_BIT2,
			INB         => b2,          --(RGB2(14) & RGB2(9) & RGB2(2) & RGB1(14) & RGB1(9) & RGB1(2)),
			BCM_MEM_BIT => mem_bcm(1),
			EN_CNT      => WEREN,
			RES         => three
		);

	b1 <= (RGB2(13) & RGB2(8) & RGB2(1) & RGB1(13) & RGB1(9) & RGB1(1));
	uCnt_2 : component bit_cnt
		port map(
			SRST        => rst_cnt,
			CLK         => CLK,
			INA1        => WRITE_BIT1,
			INA2        => WRITE_BIT2,
			INB         => b1,          --(RGB2(13) & RGB2(8) & RGB2(1) & RGB1(13) & RGB1(9) & RGB1(1)),
			BCM_MEM_BIT => mem_bcm(0),
			EN_CNT      => WEREN,
			RES         => two
		);

	uCmpr23 : alesb_11b
		port map(
			DATAA => three,
			DATAB => two,
			ALB   => cmpr_res(0)
		);

	uCmpr45 : alesb_11b
		port map(
			DATAA => five,
			DATAB => four,
			ALB   => cmpr_res(1)
		);

	uCmpr456 : alesb_11b
		port map(
			DATAA => six,
			DATAB => fiv_four,
			ALB   => cmpr_res(2)
		);

	uCmpr23456 : alesb_11b
		port map(
			DATAA => six_fiv_four,
			DATAB => two_three,
			ALB   => cmpr_res(3)
		);

	--multiplexery	mezi komparatory
	two_three    <= two when cmpr_res(0) = '1' else three;
	fiv_four     <= four when cmpr_res(1) = '1' else five;
	six_fiv_four <= fiv_four when cmpr_res(2) = '1' else six;

	-- vysledek z komparatoru
	next_bcm_h <= "10000" when cmpr_res(3 downto 2) = "00"
		else "01000" when cmpr_res(3 downto 1) = "010"
		else "00100" when cmpr_res(3 downto 1) = "011"
		else "00010" when cmpr_res(3) = '1' and cmpr_res(0) = '0'
		else "00001";

	--	--resi kolizni stav, kdy je nulova shoda vsech bitu se zapisovanym bitem a 6. bit jiz byl zapsan
	not_collision <= (mem_bcm(4) and next_bcm_h(4)) or (mem_bcm(3) and next_bcm_h(3)) or (mem_bcm(2) and next_bcm_h(2)) or (mem_bcm(1) and next_bcm_h(1)) or (mem_bcm(0) and next_bcm_h(0));
	mem_res       <= mem_bcm(4) & (not (mem_bcm(4)) and mem_bcm(3)) & (not (mem_bcm(4) or mem_bcm(3)) and mem_bcm(2)) & (not (mem_bcm(4) or mem_bcm(3) or mem_bcm(2)) and mem_bcm(1)) & (not (mem_bcm(4) or mem_bcm(3) or mem_bcm(2) or mem_bcm(1)) and mem_bcm(0));
	mem_res_rev   <= (not (mem_bcm(0) or mem_bcm(1) or mem_bcm(2) or mem_bcm(3)) and mem_bcm(4)) & (not (mem_bcm(0) or mem_bcm(1) or mem_bcm(2)) and mem_bcm(3)) & (not (mem_bcm(0) or mem_bcm(1)) and mem_bcm(2)) & (not (mem_bcm(0)) and mem_bcm(1)) & mem_bcm(0);

	--vystupni logika
	bcm_res <= "000001" when mem_bcm = "00000"
		else next_bcm_h & '0' when FIRST = '1' and not_collision = '1'
		else mem_res & '0' when FIRST = '1' and not_collision = '0'
		else mem_res_rev & '0';

	-- pamet neprectenych BCM bloku
	process(CLK, ARST) is
	begin
		if ARST = '1' then
			mem_bcm <= (others => '1');
		elsif rising_edge(CLK) then
			if NEW_TEST = '1' then
				if mem_bcm = "00000" then
					mem_bcm <= (others => '1');
				else
					mem_bcm <= (mem_bcm(4) and (not bcm_res(5))) & (mem_bcm(3) and (not bcm_res(4))) & (mem_bcm(2) and (not bcm_res(3))) & (mem_bcm(1) and (not bcm_res(2))) & (mem_bcm(0) and (not bcm_res(1)));
				end if;
			end if;
		end if;
	end process;

	-- pameti stavajiciho a nasledujiciho bloku
	process(CLK, ARST) is
	begin
		if ARST = '1' then
			ACTUAL_BCMO <= "100000";
			next_BCM    <= "000001";
		elsif rising_edge(clk) then
			if NEW_TEST = '1' then
				ACTUAL_BCMO <= next_BCM;
				next_BCM    <= bcm_res;
			end if;
		end if;
	end process;

--	process(clk) is
--	begin
--		if rising_edge(clk) then
--			END_ROW <= '0';
--			if NEW_TEST = '1' then
--				if switch = "100000" then
--					switch  <= "000001";
--					END_ROW <= '1';
--				else
--					switch <= switch(4 downto 0) & '0';--

	--			end if;
	--		end if;
	--	end if;
	--end process;

	--ACTUAL_BCMO <= switch;
	--NEXT_BCMO   <= "000001" when switch = "100000" else std_logic_vector(unsigned(switch) + unsigned(switch));

	END_ROW   <= NEW_TEST when mem_bcm = "00000" else '0';
	NEXT_BCMO <= next_BCM;
end Behavioral;

