-- file Trace.vhd
-- Trace easy model controller implementation
-- copyright: (C) 2016-2020 MPSI Technologies GmbH
-- author: Alexander Wirthmueller (auto-generation)
-- date created: 10 May 2025
-- IP header --- ABOVE

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.Dbecore.all;
use work.Zuvsp.all;

entity Trace is
	port (
		reset: in std_logic;
		mclk: in std_logic;

		vsync: in std_logic;
		ixTExp: in std_logic_vector(3 downto 0);

		NRow: in std_logic_vector(10 downto 0);
		NCol: in std_logic_vector(10 downto 0);

		rgbFromVideoinAXIS_tready: out std_logic;
		rgbFromVideoinAXIS_tvalid: in std_logic;
		rgbFromVideoinAXIS_tdata: in std_logic_vector(35 downto 0);
		rgbFromVideoinAXIS_tlast: in std_logic;

		tkclksrcGetTkstTkst: in std_logic_vector(31 downto 0);

		reqInvAcquire: in std_logic;
		ackInvAcquire: out std_logic;

		reqInvConfig: in std_logic;
		ackInvConfig: out std_logic;

		configTixVOrient: in std_logic_vector(7 downto 0);
		configRow0: in std_logic_vector(15 downto 0);
		configCol0: in std_logic_vector(15 downto 0);

		getInfoTixVState: out std_logic_vector(7 downto 0);
		getInfoTkst: out std_logic_vector(31 downto 0);

		reqInvUnlock: in std_logic;
		ackInvUnlock: out std_logic;

		reqFlgbufToHostif: in std_logic;
		ackFlgbufToHostif: out std_logic;
		dneFlgbufToHostif: in std_logic;
		avllenFlgbufToHostif: out std_logic_vector(31 downto 0);

		flgbufToHostifAXIS_tready: in std_logic;
		flgbufToHostifAXIS_tvalid: out std_logic;
		flgbufToHostifAXIS_tdata: out std_logic_vector(63 downto 0);
		flgbufToHostifAXIS_tlast: out std_logic
	);
end Trace;

architecture Rtl of Trace is

	------------------------------------------------------------------------
	-- component declarations
	------------------------------------------------------------------------

	component Dpbram_size188kB_a8b8 is
		port (
			rstA: in std_logic;
			clkA: in std_logic;

			enA: in std_logic;
			weA: in std_logic;

			aA: in std_logic_vector(17 downto 0);
			drdA: out std_logic_vector(7 downto 0);
			dwrA: in std_logic_vector(7 downto 0);

			rstB: in std_logic;
			clkB: in std_logic;

			enB: in std_logic;
			weB: in std_logic;

			aB: in std_logic_vector(17 downto 0);
			drdB: out std_logic_vector(7 downto 0);
			dwrB: in std_logic_vector(7 downto 0)
		);
	end component;

	component Dpbram_size38kB_a8b64 is
		port (
			rstA: in std_logic;
			clkA: in std_logic;

			enA: in std_logic;
			weA: in std_logic;

			aA: in std_logic_vector(15 downto 0);
			drdA: out std_logic_vector(7 downto 0);
			dwrA: in std_logic_vector(7 downto 0);

			rstB: in std_logic;
			clkB: in std_logic;

			enB: in std_logic;
			weB: in std_logic;

			aB: in std_logic_vector(12 downto 0);
			drdB: out std_logic_vector(63 downto 0);
			dwrB: in std_logic_vector(63 downto 0)
		);
	end component;

	------------------------------------------------------------------------
	-- signal declarations
	------------------------------------------------------------------------

	constant tixVOrientSqr: std_logic_vector(7 downto 0) := x"00";
	constant tixVOrientLand: std_logic_vector(7 downto 0) := x"01";
	constant tixVOrientPort: std_logic_vector(7 downto 0) := x"02";

	constant tixVStateIdle: std_logic_vector(7 downto 0) := x"00";
	constant tixVStateAcq: std_logic_vector(7 downto 0) := x"01";
	constant tixVStateLock: std_logic_vector(7 downto 0) := x"02";

	---- flag buffer B/hostif-facing operation (flgbufB)
	type stateFlgbufB_t is (
		stateFlgbufBInit,
		stateFlgbufBIdle,
		stateFlgbufBXferA, stateFlgbufBXferB,
		stateFlgbufBDone
	);
	signal stateFlgbufB: stateFlgbufB_t;

	signal enFlgbufB: std_logic;
	signal aFlgbufB: natural range 0 to 38*1024/8-1;
	signal aFlgbufB_vec: std_logic_vector(12 downto 0);

	-- IP sigs.flgbufB.cust --- INSERT

	---- main operation (op)
	type stateOp_t is (
		stateOpInit,
		stateOpInv
	);
	signal stateOp: stateOp_t;

	signal ackInvAcquire_sig: std_logic;
	signal ackInvConfig_sig: std_logic;
	signal ackInvUnlock_sig: std_logic;

	signal tixVState: std_logic_vector(7 downto 0);
	signal tkst: std_logic_vector(31 downto 0);

	signal tixVOrient: std_logic_vector(7 downto 0);

	signal row0: natural range 0 to 3000/2-1;
	signal col0: natural range 0 to 4000/2-1;

	signal enAccbuf: std_logic;
	signal aAccbuf: natural;
	signal aAccbuf_vec: std_logic_vector(17 downto 0);
	signal dwrAccbuf: std_logic_vector(7 downto 0);

	signal enAccbufB: std_logic;
	signal aAccbufB: natural;
	signal aAccbufB_vec: std_logic_vector(17 downto 0);

	signal enFlgbuf: std_logic;
	signal aFlgbuf: natural;
	signal aFlgbuf_vec: std_logic_vector(15 downto 0);
	signal dwrFlgbuf: std_logic_vector(7 downto 0);

	-- IP sigs.op.cust --- INSERT

	---- myAccbuf
	signal drdAccbufB: std_logic_vector(7 downto 0);

	---- other
	-- IP sigs.oth.cust --- IBEGIN

	------------------------------------------------------------------------
	-- functional description
	------------------------------------------------------------------------

	-- perform log2 5-bit red-only HDR of "on" image first, then flag if log2 of "off" image is -2 or more
	-- accbuf is sufficient for 640x480 pixels, allow arbitrary row0/col0, 640x480/480x640/554x554 (up to 307200 pixels)

--	if abc=0 then
--		val <= drdAccbufB(4 downto 0);
--	elsif abc=1 then
--		val <= drdAccbufB(1 downto 0) & drdAccbufBm1(7 downto 5);
--	elsif abc=2 then
--		val <= drdAccbufB(6 downto 2);
--	elsif abc=3 then
--		val <= drdAccbufB(3 downto 0) & drdAccbufBm1(7 downto 7);
--	elsif abc=4 then
--		val <= drdAccbufB(0 downto 0) & drdAccbufBm1(7 downto 4);
--	elsif abc=5 then
--		val <= drdAccbufB(5 downto 1);
--	elsif abc=6 then
--		val <= drdAccbufB(2 downto 0) & drdAccbufBm1(7 downto 6);
--	elsif abc=7 then
--		val <= drdAccbufB(7 downto 3);
--	end if;

	-- IP sigs.oth.cust --- IEND

begin

	------------------------------------------------------------------------
	-- sub-module instantiation
	------------------------------------------------------------------------

	myAccbuf : Dpbram_size188kB_a8b8
		port map (
			rstA => reset,
			clkA => mclk,

			enA => enAccbuf,
			weA => '1',

			aA => aAccbuf_vec,
			drdA => open,
			dwrA => dwrAccbuf,

			rstB => reset,
			clkB => mclk,

			enB => enAccbufB,
			weB => '0',

			aB => aAccbufB_vec,
			drdB => drdAccbufB,
			dwrB => (others => '0')
		);

	myFlgbuf : Dpbram_size38kB_a8b64
		port map (
			rstA => reset,
			clkA => mclk,

			enA => enFlgbuf,
			weA => '1',

			aA => aFlgbuf_vec,
			drdA => open,
			dwrA => dwrFlgbuf,

			rstB => reset,
			clkB => mclk,

			enB => enFlgbufB,
			weB => '0',

			aB => aFlgbufB_vec,
			drdB => flgbufToHostifAXIS_tdata,
			dwrB => (others => '0')
		);

	------------------------------------------------------------------------
	-- implementation: flag buffer B/hostif-facing operation (flgbufB)
	------------------------------------------------------------------------

	-- IP impl.flgbufB.wiring --- BEGIN
	ackFlgbufToHostif <= '1' when (stateFlgbufB=stateFlgbufBXferA or stateFlgbufB=stateFlgbufBXferB or stateFlgbufB=stateFlgbufBDone) else '0';

	flgbufToHostifAXIS_tvalid <= '1' when stateFlgbufB=stateFlgbufBXferB else '0';
	flgbufToHostifAXIS_tlast <= '0' when (stateFlgbufB=stateFlgbufBXferA or (stateFlgbufB=stateFlgbufBXferB and aFlgbufB/=38*1024/8-1)) else '1';

	enFlgbufB <= '1' when stateFlgbufB=stateFlgbufBXferA else '0';
	aFlgbufB_vec <= std_logic_vector(to_unsigned(aFlgbufB, 13));
	-- IP impl.flgbufB.wiring --- END

	-- IP impl.flgbufB.wiring.cust --- RBEGIN
	avllenFlgbufToHostif <= std_logic_vector(to_unsigned(38*1024, 32)) when stateFlgbufB=stateFlgbufBIdle else (others => '0');
	-- IP impl.flgbufB.wiring.cust --- REND

	-- IP impl.flgbufB.rising --- BEGIN
	process (reset, mclk)
		-- IP impl.flgbufB.vars --- BEGIN
		-- IP impl.flgbufB.vars --- END

	begin
		if reset='1' then
			-- IP impl.flgbufB.asyncrst --- BEGIN
			stateFlgbufB <= stateFlgbufBInit;
			aFlgbufB <= 0;

			-- IP impl.flgbufB.asyncrst --- END
			-- IP impl.flgbufB.asyncrst.cust --- INSERT

		elsif rising_edge(mclk) then
			if stateFlgbufB=stateFlgbufBInit then
				-- IP impl.flgbufB.syncrst --- BEGIN
				aFlgbufB <= 0;

				-- IP impl.flgbufB.syncrst --- END
				-- IP impl.flgbufB.syncrst.cust --- INSERT

				if reqFlgbufToHostif='0' then
					stateFlgbufB <= stateFlgbufBIdle;
				end if;

			elsif stateFlgbufB=stateFlgbufBIdle then
				if reqFlgbufToHostif='1' then
					stateFlgbufB <= stateFlgbufBXferA;
				end if;

			elsif stateFlgbufB=stateFlgbufBXferA then
				stateFlgbufB <= stateFlgbufBXferB;

			elsif stateFlgbufB=stateFlgbufBXferB then
				if flgbufToHostifAXIS_tready='1' then
					if aFlgbufB=38*1024/8-1 then
						stateFlgbufB <= stateFlgbufBDone;

					else
						aFlgbufB <= aFlgbufB + 1; -- IP impl.flgbufB.xferB.inc --- ILINE

						stateFlgbufB <= stateFlgbufBXferA;
					end if;

				elsif reqFlgbufToHostif='0' then
					stateFlgbufB <= stateFlgbufBInit;
				end if;

			elsif stateFlgbufB=stateFlgbufBDone then
				if dneFlgbufToHostif='1' then
					stateFlgbufB <= stateFlgbufBInit;
				end if;
			end if;
		end if;
	end process;
	-- IP impl.flgbufB.rising --- END

	------------------------------------------------------------------------
	-- implementation: main operation (op)
	------------------------------------------------------------------------

	-- IP impl.op.wiring --- BEGIN
	ackInvAcquire <= ackInvAcquire_sig;
	ackInvConfig <= ackInvConfig_sig;
	ackInvUnlock <= ackInvUnlock_sig;

	getInfoTixVState <= tixVState;
	getInfoTkst <= tkst;
	-- IP impl.op.wiring --- END

	-- IP impl.op.wiring.cust --- LINE

	-- IP impl.op.rising --- BEGIN
	process (reset, mclk)
		-- IP impl.op.vars --- BEGIN
		-- IP impl.op.vars --- END

	begin
		if reset='1' then
			-- IP impl.op.asyncrst --- BEGIN
			stateOp <= stateOpInit;
			ackInvAcquire_sig <= '0';
			ackInvConfig_sig <= '0';
			ackInvUnlock_sig <= '0';
			tixVState <= (others => '0');
			tkst <= (others => '0');
			tixVOrient <= (others => '0');
			row0 <= 0;
			col0 <= 0;
			enAccbuf <= '0';
			aAccbuf <= 0;
			aAccbuf_vec <= (others => '0');
			dwrAccbuf <= (others => '0');
			enAccbufB <= '0';
			aAccbufB <= 0;
			aAccbufB_vec <= (others => '0');
			enFlgbuf <= '0';
			aFlgbuf <= 0;
			aFlgbuf_vec <= (others => '0');
			dwrFlgbuf <= (others => '0');

			-- IP impl.op.asyncrst --- END
			-- IP impl.op.asyncrst.cust --- INSERT

		elsif rising_edge(mclk) then
			if (stateOp=stateOpInit or (stateOp/=stateOpInv and (reqInvAcquire='1' or reqInvConfig='1' or reqInvUnlock='1'))) then
				if reqInvAcquire='1' then
					-- IP impl.op.init.invAcquire --- IBEGIN
					if tixVState=tixVStateIdle then
						tixVState <= tixVStateAcq;
					end if;

					ackInvAcquire_sig <= '1';
					ackInvConfig_sig <= '0';
					ackInvUnlock_sig <= '0';
					-- IP impl.op.init.invAcquire --- IEND

					stateOp <= stateOpInv;

				elsif reqInvConfig='1' then
					-- IP impl.op.init.invConfig --- IBEGIN
					tixVOrient <= configTixVOrient;
					row0 <= to_integer(unsigned(configRow0));
					col0 <= to_integer(unsigned(configCol0));

					ackInvAcquire_sig <= '0';
					ackInvConfig_sig <= '1';
					ackInvUnlock_sig <= '0';
					-- IP impl.op.init.invConfig --- IEND

					stateOp <= stateOpInv;

				elsif reqInvUnlock='1' then
					-- IP impl.op.init.invUnlock --- IBEGIN
					if tixVState=tixVStateLock then
						tixVState <= tixVStateIdle;
					end if;

					ackInvAcquire_sig <= '1';
					ackInvConfig_sig <= '0';
					ackInvUnlock_sig <= '0';
					-- IP impl.op.init.invUnlock --- IEND

					stateOp <= stateOpInv;

				else
					-- IP impl.op.syncrst --- RBEGIN
					ackInvAcquire_sig <= '0';
					ackInvConfig_sig <= '0';
					ackInvUnlock_sig <= '0';
					enAccbuf <= '0';
					aAccbuf <= 0;
					aAccbuf_vec <= (others => '0');
					dwrAccbuf <= (others => '0');
					enAccbufB <= '0';
					aAccbufB <= 0;
					aAccbufB_vec <= (others => '0');
					enFlgbuf <= '0';
					aFlgbuf <= 0;
					aFlgbuf_vec <= (others => '0');
					dwrFlgbuf <= (others => '0');

					-- IP impl.op.syncrst --- REND
					-- IP impl.op.syncrst.cust --- INSERT

					stateOp <= stateOpInit;
				end if;

			elsif stateOp=stateOpInv then
				if ((reqInvAcquire='0' and ackInvAcquire_sig='1') or (reqInvConfig='0' and ackInvConfig_sig='1') or (reqInvUnlock='0' and ackInvUnlock_sig='1')) then
					-- IP impl.op.inv.reset --- IBEGIN
					ackInvAcquire_sig <= '0';
					ackInvConfig_sig <= '0';
					ackInvUnlock_sig <= '0';
					-- IP impl.op.inv.reset --- IEND

					stateOp <= stateOpInit;
				end if;
			end if;
		end if;
	end process;
	-- IP impl.op.rising --- END

	------------------------------------------------------------------------
	-- implementation: other 
	------------------------------------------------------------------------

	
	-- IP impl.oth.cust --- INSERT

end Rtl;
