-- file Memtrack.vhd
-- Memtrack gptrack_Easy_v1_0 easy model debug controller implementation
-- copyright: (C) 2023 MPSI Technologies GmbH
-- author: Alexander Wirthmueller (auto-generation)
-- date created: 28 Jun 2025
-- IP header --- ABOVE

-- module parameters:
-- trkclk (clock): memclk
-- ratioTrkclk (track clock ratio wrt. master clock): 1.2
-- capts (signals to be captured): reqHdrengToDdrifRd;ackHdrengToDdrifRd;reqHdrengToDdrifWr;ackHdrengToDdrifWr;ddrAXI_rvalid;ddrAXI_rready_sig;ddrAXI_wready;ddrAXI_bvalid;ddrAXI_wvalid_sig
-- trigs (triggers): vsync.mclk;rgbVideoinToManyAXIS_tlast.mclk
-- sizeSeqbuf (sequence buffer size [kB]): 4

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

use work.Dbecore.all;
use work.Tivsp.all;

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

		resetMemclk: in std_logic;
		memclk: in std_logic;

		vsync: in std_logic;
		rgbVideoinToManyAXIS_tlast: in std_logic;

		reqInvClearMask: in std_logic;
		ackInvClearMask: out std_logic;

		getInfoTixVState: out std_logic_vector(7 downto 0);
		getInfoTCapt: out std_logic_vector(31 downto 0);
		getInfoPtr0Seqbuf: out std_logic_vector(15 downto 0);

		reqInvSelect: in std_logic;
		ackInvSelect: out std_logic;

		selectStaTixVTrigger: in std_logic_vector(7 downto 0);
		selectStaFallingNotRising: in std_logic_vector(7 downto 0);
		selectStoTixVTrigger: in std_logic_vector(7 downto 0);
		selectStoFallingNotRising: in std_logic_vector(7 downto 0);

		reqInvSet: in std_logic;
		ackInvSet: out std_logic;

		setRng: in std_logic_vector(7 downto 0);
		setTCaptMax: in std_logic_vector(31 downto 0);

		reqInvSetMask: in std_logic;
		ackInvSetMask: out std_logic;

		setMaskTixVCapture: in std_logic_vector(7 downto 0);

		reqSeqbufToHostif: in std_logic;
		ackSeqbufToHostif: out std_logic;
		dneSeqbufToHostif: in std_logic;
		avllenSeqbufToHostif: out std_logic_vector(31 downto 0);

		seqbufToHostifAXIS_tready: in std_logic;
		seqbufToHostifAXIS_tvalid: out std_logic;
		seqbufToHostifAXIS_tdata: out std_logic_vector(31 downto 0);
		seqbufToHostifAXIS_tlast: out std_logic;

		reqHdrengToDdrifRd: in std_logic;
		ackHdrengToDdrifRd: in std_logic;
		reqHdrengToDdrifWr: in std_logic;
		ackHdrengToDdrifWr: in std_logic;
		ddrAXI_rvalid: in std_logic;
		ddrAXI_rready_sig: in std_logic;
		ddrAXI_wready: in std_logic;
		ddrAXI_bvalid: in std_logic;
		ddrAXI_wvalid_sig: in std_logic
	);
end Memtrack;

architecture Rtl of Memtrack is

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

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

			enA: in std_logic;
			weA: in std_logic;

			aA: in std_logic_vector(9 downto 0);
			drdA: out std_logic_vector(31 downto 0);
			dwrA: in std_logic_vector(31 downto 0);

			rstB: in std_logic;
			clkB: in std_logic;

			enB: in std_logic;
			weB: in std_logic;

			aB: in std_logic_vector(9 downto 0);
			drdB: out std_logic_vector(31 downto 0);
			dwrB: in std_logic_vector(31 downto 0)
		);
	end component;

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

	constant wD: natural := 32;
	constant logWD: natural := 2;

	constant sizeSeqbuf: natural := 4096;
	constant logSizeSeqbuf: natural := 12;

	constant tixVCaptureReqHdrengToDdrifRd: std_logic_vector(7 downto 0) := x"00";
	constant tixVCaptureAckHdrengToDdrifRd: std_logic_vector(7 downto 0) := x"01";
	constant tixVCaptureReqHdrengToDdrifWr: std_logic_vector(7 downto 0) := x"02";
	constant tixVCaptureAckHdrengToDdrifWr: std_logic_vector(7 downto 0) := x"03";
	constant tixVCaptureDdrAXI_rvalid: std_logic_vector(7 downto 0) := x"04";
	constant tixVCaptureDdrAXI_rready_sig: std_logic_vector(7 downto 0) := x"05";
	constant tixVCaptureDdrAXI_wready: std_logic_vector(7 downto 0) := x"06";
	constant tixVCaptureDdrAXI_bvalid: std_logic_vector(7 downto 0) := x"07";
	constant tixVCaptureDdrAXI_wvalid_sig: std_logic_vector(7 downto 0) := x"08";

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

	constant tixVTriggerVoid: std_logic_vector(7 downto 0) := x"00";
	constant tixVTriggerVsync: std_logic_vector(7 downto 0) := x"01";
	constant tixVTriggerRgbVideoinToManyAXIS_tlast: std_logic_vector(7 downto 0) := x"02";

	---- main operation (op)
	type stateOp_t is (
		stateOpInit,
		stateOpInv,
		stateOpIdle,
		stateOpStart,
		stateOpRun,
		stateOpStop,
		stateOpClear
	);
	signal stateOp: stateOp_t;

	signal ackInvClearMask_sig: std_logic;
	signal ackInvSelect_sig: std_logic;
	signal ackInvSet_sig: std_logic;
	signal ackInvSetMask_sig: std_logic;

	signal staTixVTrigger: std_logic_vector(7 downto 0);
	signal staFallingNotRising: boolean;

	signal stoTixVTrigger: std_logic_vector(7 downto 0);
	signal stoFallingNotRising: boolean;

	signal mask: std_logic_vector(14 downto 0);

	signal strbStart: std_logic;
	signal strbStop: std_logic;

	---- sequence operation (seq)
	type stateSeq_t is (
		stateSeqInit,
		stateSeqIdle,
		stateSeqRun,
		stateSeqDone,
		stateSeqClear,
		stateSeqAckClear
	);
	signal stateSeq: stateSeq_t;

	signal rdySeq: std_logic;
	signal dneSeq: std_logic;

	signal TCapt: std_logic_vector(31 downto 0);

	signal ptr0SeqbufTrackNotFixed: std_logic;
	signal ptr0Seqbuf: natural range 0 to sizeSeqbuf/4-1;

	signal enSeqbuf: std_logic;

	signal aSeqbuf: natural range 0 to sizeSeqbuf/4-1;
	signal aSeqbuf_vec: std_logic_vector(logSizeSeqbuf-2-1 downto 0);

	signal dwrSeqbuf: std_logic_vector(31 downto 0);

	---- sequence buffer B/hostif-facing operation (seqbufB)
	type stateSeqbufB_t is (
		stateSeqbufBInit,
		stateSeqbufBIdle,
		stateSeqbufBXferA, stateSeqbufBXferB,
		stateSeqbufBDone,
		stateSeqbufBClear
	);
	signal stateSeqbufB: stateSeqbufB_t;

	signal enSeqbufB: std_logic;

	signal aSeqbufB: natural range 0 to sizeSeqbuf/(wD/8)-1;
	signal aSeqbufB_vec: std_logic_vector(logSizeSeqbuf-logWD-1 downto 0);

	---- sampling operation (sample)
	signal capt: std_logic_vector(14 downto 0);

	signal start: std_logic;
	signal stop: std_logic;

	---- mclk to memclk CDC sampling (mclkToMemclkSample)

	signal capt_memclk: std_logic_vector(14 downto 0);
	signal capt_to_memclkm1: std_logic_vector(14 downto 0);
	signal capt_to_memclkm2: std_logic_vector(14 downto 0);
	signal staTixVTrigger_memclk: std_logic_vector(7 downto 0);
	signal staTixVTrigger_to_memclkm1: std_logic_vector(7 downto 0);
	signal staTixVTrigger_to_memclkm2: std_logic_vector(7 downto 0);
	signal stoTixVTrigger_memclk: std_logic_vector(7 downto 0);
	signal stoTixVTrigger_to_memclkm1: std_logic_vector(7 downto 0);
	signal stoTixVTrigger_to_memclkm2: std_logic_vector(7 downto 0);
	signal strbStart_memclk: std_logic;
	signal strbStart_to_memclkm1: std_logic;
	signal strbStart_to_memclkm2: std_logic;
	signal strbStop_memclk: std_logic;
	signal strbStop_to_memclkm1: std_logic;
	signal strbStop_to_memclkm2: std_logic;
	signal reqOpToSeqClear_memclk: std_logic;
	signal reqOpToSeqClear_to_memclkm1: std_logic;
	signal reqOpToSeqClear_to_memclkm2: std_logic;
	signal reqSeqbufBToSeqClear_memclk: std_logic;
	signal reqSeqbufBToSeqClear_to_memclkm1: std_logic;
	signal reqSeqbufBToSeqClear_to_memclkm2: std_logic;

	---- mclk to memclk CDC stretching (mclkToMemclkStretch)

	signal capt_to_memclk: std_logic_vector(14 downto 0);
	signal staTixVTrigger_to_memclk: std_logic_vector(7 downto 0);
	signal stoTixVTrigger_to_memclk: std_logic_vector(7 downto 0);
	signal strbStart_to_memclk: std_logic;
	signal strbStop_to_memclk: std_logic;
	signal reqOpToSeqClear_to_memclk: std_logic;
	signal reqSeqbufBToSeqClear_to_memclk: std_logic;

	---- memclk to mclk CDC sampling (memclkToMclkSample)

	signal rdySeq_mclk: std_logic;
	signal rdySeq_to_mclkm1: std_logic;
	signal rdySeq_to_mclkm2: std_logic;
	signal dneSeq_mclk: std_logic;
	signal dneSeq_to_mclkm1: std_logic;
	signal dneSeq_to_mclkm2: std_logic;
	signal TCapt_mclk: std_logic_vector(31 downto 0);
	signal TCapt_to_mclkm1: std_logic_vector(31 downto 0);
	signal TCapt_to_mclkm2: std_logic_vector(31 downto 0);
	signal ptr0Seqbuf_mclk: natural range 0 to sizeSeqbuf/4-1;
	signal ptr0Seqbuf_to_mclkm1: natural range 0 to sizeSeqbuf/4-1;
	signal ptr0Seqbuf_to_mclkm2: natural range 0 to sizeSeqbuf/4-1;
	signal start_mclk: std_logic;
	signal start_to_mclkm1: std_logic;
	signal start_to_mclkm2: std_logic;
	signal stop_mclk: std_logic;
	signal stop_to_mclkm1: std_logic;
	signal stop_to_mclkm2: std_logic;
	signal ackSeqbufBToSeqClear_mclk: std_logic;
	signal ackSeqbufBToSeqClear_to_mclkm1: std_logic;
	signal ackSeqbufBToSeqClear_to_mclkm2: std_logic;

	---- memclk to mclk CDC stretching (memclkToMclkStretch)

	signal rdySeq_to_mclk: std_logic;
	signal dneSeq_to_mclk: std_logic;
	signal TCapt_to_mclk: std_logic_vector(31 downto 0);
	signal ptr0Seqbuf_to_mclk: natural range 0 to sizeSeqbuf/4-1;
	signal start_to_mclk: std_logic;
	signal stop_to_mclk: std_logic;
	signal ackSeqbufBToSeqClear_to_mclk: std_logic;

	---- handshake

	-- op to seq
	signal reqOpToSeqClear: std_logic;

	-- seqbufB to seq
	signal reqSeqbufBToSeqClear: std_logic;
	signal ackSeqbufBToSeqClear: std_logic;

begin

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

	mySeqbuf : Dpbram_size4kB_a32b32
		port map (
			rstA => resetMemclk,
			clkA => memclk,

			enA => enSeqbuf,
			weA => '1',

			aA => aSeqbuf_vec,
			drdA => open,
			dwrA => dwrSeqbuf,

			rstB => reset,
			clkB => mclk,

			enB => enSeqbufB,
			weB => '0',

			aB => aSeqbufB_vec,
			drdB => seqbufToHostifAXIS_tdata,
			dwrB => (others => '0')
		);

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

	ackInvClearMask <= ackInvClearMask_sig;
	ackInvSelect <= ackInvSelect_sig;
	ackInvSet <= ackInvSet_sig;
	ackInvSetMask <= ackInvSetMask_sig;

	getInfoTixVState <= tixVStateArm when stateOp=stateOpIdle
				else tixVStateAcq when stateOp=stateOpRun
				else tixVStateDone when stateOp=stateOpStop
				else tixVStateIdle;
	getInfoTCapt <= TCapt_mclk;
	getInfoPtr0Seqbuf <= std_logic_vector(to_unsigned(ptr0Seqbuf_mclk, 16));

	strbStart <= '1' when stateOp=stateOpStart else '0';

	reqOpToSeqClear <= '1' when stateOp=stateOpClear else '0';

	process (reset, mclk, stateOp)
		variable rng: boolean;
		variable restart: boolean;

		variable TCaptMax: std_logic_vector(31 downto 0);

		variable ixMask: natural range 0 to 14;

		variable strb_last: std_logic;

	begin
		if reset='1' then
			stateOp <= stateOpInit;
			ackInvClearMask_sig <= '0';
			ackInvSelect_sig <= '0';
			ackInvSet_sig <= '0';
			ackInvSetMask_sig <= '0';
			staTixVTrigger <= tixVTriggerVoid;
			staFallingNotRising <= false;
			stoTixVTrigger <= tixVTriggerVoid;
			stoFallingNotRising <= false;
			mask <= (others => '0');
			strbStop <= '0';

			rng := false;
			restart := false;
			TCaptMax := (others => '0');
			strb_last := '0';

		elsif rising_edge(mclk) then
			if stateOp=stateOpInit or (stateOp/=stateOpInv and (reqInvClearMask='1' or reqInvSelect='1' or reqInvSet='1' or reqInvSetMask='1'))  then
				strbStop <= '0';

				if reqInvClearMask='1' then
					mask <= (others => '0');

					ackInvClearMask_sig <= '1';
					stateOp <= stateOpInv;

				elsif reqInvSelect='1' then
					staTixVTrigger <= selectStaTixVTrigger;
					staFallingNotRising <= (selectStaFallingNotRising=tru8);
					stoTixVTrigger <= selectStoTixVTrigger;
					stoFallingNotRising <= (selectStoFallingNotRising=tru8);

					ackInvSelect_sig <= '1';
					stateOp <= stateOpInv;

				elsif reqInvSet='1' then
					if setRng=tru8 then
						rng := true;
					else
						rng := false;
					end if;
					TCaptMax := setTCaptMax;

					ackInvSet_sig <= '1';
					stateOp <= stateOpInv;

				elsif reqInvSetMask='1' then
					ixMask := to_integer(unsigned(setMaskTixVCapture));
					mask(ixMask) <= '1';

					ackInvSetMask_sig <= '1';
					stateOp <= stateOpInv;

				else
					restart := false;

					if rng then
						strb_last := start_mclk;

						stateOp <= stateOpIdle;

					else
						stateOp <= stateOpInit;
					end if;
				end if;

			elsif stateOp=stateOpInv then
				if (reqInvClearMask='0' and ackInvClearMask_sig='1') or (reqInvSet='0' and ackInvSet_sig='1') or (reqInvSelect='0' and ackInvSelect_sig='1') or (reqInvSetMask='0' and ackInvSetMask_sig='1') then
					ackInvClearMask_sig <= '0';
					ackInvSet_sig <= '0';
					ackInvSelect_sig <= '0';
					ackInvSetMask_sig <= '0';

					strbStop <= '1';

					restart := true;

					stateOp <= stateOpStop;
				end if;

			elsif stateOp=stateOpIdle then
				if staTixVTrigger=tixVTriggerVoid or (not staFallingNotRising and strb_last='0' and start_mclk='1') or (staFallingNotRising and strb_last='1' and start_mclk='0') then
					stateOp <= stateOpStart;
				else
					strb_last := start_mclk;
				end if;

			elsif stateOp=stateOpStart then -- strbStart='1'
				strb_last := stop_mclk;

				stateOp <= stateOpRun;

			elsif stateOp=stateOpRun then
				if (stoTixVTrigger=tixVTriggerVoid and unsigned(TCaptMax)/=0 and (unsigned(TCapt_mclk)>=unsigned(TCaptMax) or dneSeq_mclk='1')) or unsigned(TCapt_mclk)>=x"FFFFFF00" or (not stoFallingNotRising and strb_last='0' and stop_mclk='1') or (stoFallingNotRising and strb_last='1' and stop_mclk='0') then
					strbStop <= '1';

					stateOp <= stateOpStop;

				else
					strb_last := stop_mclk;
				end if;

			elsif stateOp=stateOpStop then
				strbStop <= '0';

				if restart then
					stateOp <= stateOpClear;

				else
					if rdySeq_mclk='1' then
						stateOp <= stateOpInit;
					end if;
				end if;

			elsif stateOp=stateOpClear then -- reqOpToSeqClear='1'
				if rdySeq_mclk='1' then
					stateOp <= stateOpInit;
				end if;
			end if;
		end if;
	end process;

	------------------------------------------------------------------------
	-- implementation: sampling operation (sample)
	------------------------------------------------------------------------

	process (resetMemclk, memclk)

	begin
		if resetMemclk='1' then
			capt <= (others => '0');
			start <= '0';
			stop <= '0';

		elsif rising_edge(memclk) then
			capt <= ("000000" & ddrAXI_wvalid_sig & ddrAXI_bvalid & ddrAXI_wready & ddrAXI_rready_sig & ddrAXI_rvalid & ackHdrengToDdrifWr & reqHdrengToDdrifWr & ackHdrengToDdrifRd & reqHdrengToDdrifRd) and not mask;

			case staTixVTrigger_memclk is
				when tixVTriggerVsync =>
					start <= vsync;
				when tixVTriggerRgbVideoinToManyAXIS_tlast =>
					start <= rgbVideoinToManyAXIS_tlast;
				when others =>
					start <= '0';
			end case;

			case stoTixVTrigger_memclk is
				when tixVTriggerVsync =>
					stop <= vsync;
				when tixVTriggerRgbVideoinToManyAXIS_tlast =>
					stop <= rgbVideoinToManyAXIS_tlast;
				when others =>
					stop <= '0';
			end case;
		end if;
	end process;

	------------------------------------------------------------------------
	-- implementation: sequence operation (seq)
	------------------------------------------------------------------------

	rdySeq <= '1' when stateSeq=stateSeqIdle else '0';
	dneSeq <= '1' when stateSeq=stateSeqDone else '0';

	ptr0Seqbuf <= aSeqbuf when ptr0SeqbufTrackNotFixed='1' else 0;

	aSeqbuf_vec <= std_logic_vector(to_unsigned(aSeqbuf, logSizeSeqbuf-2));

	ackSeqbufBToSeqClear <= '1' when stateSeq=stateSeqAckClear else '0';

	process (resetMemclk, memclk, stateSeq)
		variable quad: std_logic_vector(31 downto 0);

		variable i: natural range 0 to 3;

		variable first: boolean;
		variable stop_lcl: boolean;

		variable burstCapt: std_logic_vector(14 downto 0);
		variable burstCnt: natural range 0 to 65535;

	begin
		if resetMemclk='1' then
			stateSeq <= stateSeqInit;
			TCapt <= (others => '0');
			ptr0SeqbufTrackNotFixed <= '0';
			enSeqbuf <= '0';
			aSeqbuf <= 0;
			dwrSeqbuf <= (others => '0');

			quad := (others => '0');
			i := 0;
			first := true;
			stop_lcl := false;
			burstCapt := (others => '0');
			burstCnt := 0;

		elsif rising_edge(memclk) then
			if stateSeq=stateSeqInit then
				TCapt <= (others => '0');
				ptr0SeqbufTrackNotFixed <= '0';
				enSeqbuf <= '0';
				aSeqbuf <= 0;
				dwrSeqbuf <= (others => '0');

				quad := (others => '0');
				i := 0;
				first := true;
				stop_lcl := false;
				burstCapt := (others => '0');
				burstCnt := 0;

				stateSeq <= stateSeqIdle;

			elsif stateSeq=stateSeqIdle then -- rdySeq='1'
				if strbStart_memclk='1' then
					stateSeq <= stateSeqRun;
				end if;

			elsif stateSeq=stateSeqRun then
				TCapt <= std_logic_vector(unsigned(TCapt) + 1);

				if strbStop_memclk='1' or (stoTixVTrigger=tixVTriggerVoid and (i=0 and aSeqbuf=sizeSeqbuf/4-1)) then
					stop_lcl := true;
				end if;

				quad((i+1)*16-1) := '0';
				quad((i+1)*16-2 downto i*16) := capt;

				if i=1 then
					if quad(14 downto 0)=capt then
						if capt/=burstCapt or burstCnt=65535 then
							if not first then
								if aSeqbuf=sizeSeqbuf/4-1 then
									ptr0SeqbufTrackNotFixed <= '1';
									aSeqbuf <= 0;
								else
									aSeqbuf <= aSeqbuf + 1;
								end if;
							end if;

							burstCnt := 0;
						end if;

						burstCapt := capt;
						burstCnt := burstCnt + 1;

						dwrSeqbuf <= "1" & burstCapt & std_logic_vector(to_unsigned(burstCnt, 16));

					else
						burstCapt := (others => '0');
						burstCnt := 0;

						if not first then
							if aSeqbuf=sizeSeqbuf/4-1 then
								ptr0SeqbufTrackNotFixed <= '1';
								aSeqbuf <= 0;
							else
								aSeqbuf <= aSeqbuf + 1;
							end if;
						end if;

						dwrSeqbuf <= quad;
					end if;

					enSeqbuf <= '1';

					i := 0;
					first := false;

					stateSeq <= stateSeqRun;

				else
					enSeqbuf <= '0';

					if stop_lcl then
						stateSeq <= stateSeqDone;

					else
						i := i + 1;

						stateSeq <= stateSeqRun;
					end if;
				end if;

			elsif stateSeq=stateSeqDone then -- dneSeq='1'
				if reqOpToSeqClear_memclk='1' or reqSeqbufBToSeqClear_memclk='1' then
					aSeqbuf <= 0;
					dwrSeqbuf <= (others => '1');

					stateSeq <= stateSeqClear;
				end if;

			elsif stateSeq=stateSeqClear then
				if aSeqbuf=sizeSeqbuf/4-1 then
					if reqSeqbufBToSeqClear_memclk='1' then
						stateSeq <= stateSeqAckClear;
					else
						stateSeq <= stateSeqInit;
					end if;

				else
					aSeqbuf <= aSeqbuf + 1;
				end if;

			elsif stateSeq=stateSeqAckClear then -- ackSeqbufBToSeqClear='1'
				if reqSeqbufBToSeqClear_memclk='0' then
					stateSeq <= stateSeqInit;
				end if;
			end if;
		end if;
	end process;

	------------------------------------------------------------------------
	-- implementation: sequence buffer B/hostif-facing operation (seqbufB)
	------------------------------------------------------------------------

	ackSeqbufToHostif <= '1' when stateSeqbufB=stateSeqbufBXferA or stateSeqbufB=stateSeqbufBXferB or stateSeqbufB=stateSeqbufBDone else '0';

	avllenSeqbufToHostif <= std_logic_vector(to_unsigned(sizeSeqbuf, 32)) when dneSeq_mclk='1'
				else (others => '0');

	seqbufToHostifAXIS_tvalid <= '1' when stateSeqbufB=stateSeqbufBXferB else '0';

	seqbufToHostifAXIS_tlast <= '1' when stateSeqbufB=stateSeqbufBXferB and aSeqbufB=(sizeSeqbuf/(wD/8))-1 else '0';

	enSeqbufB <= '1' when stateSeqbufB=stateSeqbufBXferA else '0';

	aSeqbufB_vec <= std_logic_vector(to_unsigned(aSeqbufB, logSizeSeqbuf-logWD));

	reqSeqbufBToSeqClear <= '1' when stateSeqbufB=stateSeqbufBClear else '0';

	process (reset, mclk, stateSeqbufB)

	begin
		if reset='1' then
			stateSeqbufB <= stateSeqbufBInit;
			aSeqbufB <= 0;

		elsif rising_edge(mclk) then
			if stateSeqbufB=stateSeqbufBInit then
				aSeqbufB <= 0;

				stateSeqbufB <= stateSeqbufBIdle;

			elsif stateSeqbufB=stateSeqbufBIdle then
				if reqSeqbufToHostif='1' then
					stateSeqbufB <= stateSeqbufBXferA;
				end if;

			elsif stateSeqbufB=stateSeqbufBXferA then -- enSeqbufB='1'
				stateSeqbufB <= stateSeqbufBXferB;
				
			elsif stateSeqbufB=stateSeqbufBXferB then -- seqbufToHostifAXIS_tvalid='1'
				if seqbufToHostifAXIS_tready='1' then
					if aSeqbufB=(sizeSeqbuf/(wD/8))-1 then
						stateSeqbufB <= stateSeqbufBDone;

					else
						aSeqbufB <= aSeqbufB + 1;

						stateSeqbufB <= stateSeqbufBXferA;
					end if;

				elsif reqSeqbufToHostif='0' then
					stateSeqbufB <= stateSeqbufBInit;
				end if;

			elsif stateSeqbufB=stateSeqbufBDone then
				if dneSeqbufToHostif='1' then
					stateSeqbufB <= stateSeqbufBClear;

				elsif reqSeqbufToHostif='0' then
					stateSeqbufB <= stateSeqbufBInit;
				end if ;

			elsif stateSeqbufB=stateSeqbufBClear then -- reqSeqbufBToSeqClear='1'
				if reqSeqbufToHostif='0' and ackSeqbufBToSeqClear='1' then
					stateSeqbufB <= stateSeqbufBInit;
				end if;
			end if;
		end if;
	end process;

	------------------------------------------------------------------------
	-- implementation: mclk to memclk CDC sampling (mclkToMemclkSample)
	------------------------------------------------------------------------

	-- IP impl.mclkToMemclkSample.wiring --- BEGIN
	-- IP impl.mclkToMemclkSample.wiring --- END

	-- IP impl.mclkToMemclkSample.rising --- BEGIN
	process (resetMemclk, memclk)
		-- IP impl.mclkToMemclkSample.vars --- BEGIN
		variable strbStart_wait: boolean;
		variable strbStop_wait: boolean;
		-- IP impl.mclkToMemclkSample.vars --- END

	begin
		if resetMemclk='1' then
			-- IP impl.mclkToMemclkSample.asyncrst --- BEGIN
			capt_memclk <= (others => '0');
			capt_to_memclkm1 <= (others => '0');
			capt_to_memclkm2 <= (others => '0');
			staTixVTrigger_memclk <= (others => '0');
			staTixVTrigger_to_memclkm1 <= (others => '0');
			staTixVTrigger_to_memclkm2 <= (others => '0');
			stoTixVTrigger_memclk <= (others => '0');
			stoTixVTrigger_to_memclkm1 <= (others => '0');
			stoTixVTrigger_to_memclkm2 <= (others => '0');
			strbStart_memclk <= '0';
			strbStart_to_memclkm1 <= '0';
			strbStart_to_memclkm2 <= '0';
			strbStop_memclk <= '0';
			strbStop_to_memclkm1 <= '0';
			strbStop_to_memclkm2 <= '0';
			reqOpToSeqClear_memclk <= '0';
			reqOpToSeqClear_to_memclkm1 <= '0';
			reqOpToSeqClear_to_memclkm2 <= '0';
			reqSeqbufBToSeqClear_memclk <= '0';
			reqSeqbufBToSeqClear_to_memclkm1 <= '0';
			reqSeqbufBToSeqClear_to_memclkm2 <= '0';

			strbStart_wait := false;
			strbStop_wait := false;
			-- IP impl.mclkToMemclkSample.asyncrst --- END
			-- IP impl.mclkToMemclkSample.asyncrst.cust --- INSERT

		elsif rising_edge(memclk) then
			if capt_to_memclkm1=capt_to_memclkm2 then
				capt_memclk <= capt_to_memclkm2;
			end if;
			capt_to_memclkm1 <= capt_to_memclk;
			capt_to_memclkm2 <= capt_to_memclkm1;

			if staTixVTrigger_to_memclkm1=staTixVTrigger_to_memclkm2 then
				staTixVTrigger_memclk <= staTixVTrigger_to_memclkm2;
			end if;
			staTixVTrigger_to_memclkm1 <= staTixVTrigger_to_memclk;
			staTixVTrigger_to_memclkm2 <= staTixVTrigger_to_memclkm1;

			if stoTixVTrigger_to_memclkm1=stoTixVTrigger_to_memclkm2 then
				stoTixVTrigger_memclk <= stoTixVTrigger_to_memclkm2;
			end if;
			stoTixVTrigger_to_memclkm1 <= stoTixVTrigger_to_memclk;
			stoTixVTrigger_to_memclkm2 <= stoTixVTrigger_to_memclkm1;

			if strbStart_memclk='1' then
				strbStart_memclk <= '0';
			elsif strbStart_to_memclkm1='1' and strbStart_to_memclkm2='1' and not strbStart_wait then
				strbStart_memclk <= '1';
				strbStart_wait := true;
			end if;
			if strbStart_to_memclkm1='0' and strbStart_to_memclkm2='0' and strbStart_wait then
				strbStart_wait := false;
			end if;
			strbStart_to_memclkm1 <= strbStart_to_memclk;
			strbStart_to_memclkm2 <= strbStart_to_memclkm1;

			if strbStop_memclk='1' then
				strbStop_memclk <= '0';
			elsif strbStop_to_memclkm1='1' and strbStop_to_memclkm2='1' and not strbStop_wait then
				strbStop_memclk <= '1';
				strbStop_wait := true;
			end if;
			if strbStop_to_memclkm1='0' and strbStop_to_memclkm2='0' and strbStop_wait then
				strbStop_wait := false;
			end if;
			strbStop_to_memclkm1 <= strbStop_to_memclk;
			strbStop_to_memclkm2 <= strbStop_to_memclkm1;

			if reqOpToSeqClear_to_memclkm1=reqOpToSeqClear_to_memclkm2 then
				reqOpToSeqClear_memclk <= reqOpToSeqClear_to_memclkm2;
			end if;
			reqOpToSeqClear_to_memclkm1 <= reqOpToSeqClear_to_memclk;
			reqOpToSeqClear_to_memclkm2 <= reqOpToSeqClear_to_memclkm1;

			if reqSeqbufBToSeqClear_to_memclkm1=reqSeqbufBToSeqClear_to_memclkm2 then
				reqSeqbufBToSeqClear_memclk <= reqSeqbufBToSeqClear_to_memclkm2;
			end if;
			reqSeqbufBToSeqClear_to_memclkm1 <= reqSeqbufBToSeqClear_to_memclk;
			reqSeqbufBToSeqClear_to_memclkm2 <= reqSeqbufBToSeqClear_to_memclkm1;

		end if;
	end process;
	-- IP impl.mclkToMemclkSample.rising --- END

	------------------------------------------------------------------------
	-- implementation: mclk to memclk CDC stretching (mclkToMemclkStretch)
	------------------------------------------------------------------------

	-- IP impl.mclkToMemclkStretch.wiring --- BEGIN
	-- IP impl.mclkToMemclkStretch.wiring --- END

	-- IP impl.mclkToMemclkStretch.rising --- BEGIN
	process (reset, mclk)
		-- IP impl.mclkToMemclkStretch.vars --- BEGIN
		constant imax: natural := 1;

		variable capt_i: natural range 0 to imax;
		variable staTixVTrigger_i: natural range 0 to imax;
		variable stoTixVTrigger_i: natural range 0 to imax;
		variable strbStart_i: natural range 0 to imax;
		variable strbStop_i: natural range 0 to imax;
		variable reqOpToSeqClear_i: natural range 0 to imax;
		variable reqSeqbufBToSeqClear_i: natural range 0 to imax;
		-- IP impl.mclkToMemclkStretch.vars --- END

	begin
		if reset='1' then
			-- IP impl.mclkToMemclkStretch.asyncrst --- BEGIN
			capt_to_memclk <= (others => '0');
			staTixVTrigger_to_memclk <= (others => '0');
			stoTixVTrigger_to_memclk <= (others => '0');
			strbStart_to_memclk <= '0';
			strbStop_to_memclk <= '0';
			reqOpToSeqClear_to_memclk <= '0';
			reqSeqbufBToSeqClear_to_memclk <= '0';

			capt_i := 0;
			staTixVTrigger_i := 0;
			stoTixVTrigger_i := 0;
			strbStart_i := 0;
			strbStop_i := 0;
			reqOpToSeqClear_i := 0;
			reqSeqbufBToSeqClear_i := 0;
			-- IP impl.mclkToMemclkStretch.asyncrst --- END
			-- IP impl.mclkToMemclkStretch.asyncrst.cust --- INSERT

		elsif rising_edge(mclk) then
			if capt_i=imax then
				if capt/=capt_to_memclk then
					capt_to_memclk <= capt;
					capt_i := 0;
				end if;
			else
				capt_i := capt_i + 1;
			end if;

			if staTixVTrigger_i=imax then
				if staTixVTrigger/=staTixVTrigger_to_memclk then
					staTixVTrigger_to_memclk <= staTixVTrigger;
					staTixVTrigger_i := 0;
				end if;
			else
				staTixVTrigger_i := staTixVTrigger_i + 1;
			end if;

			if stoTixVTrigger_i=imax then
				if stoTixVTrigger/=stoTixVTrigger_to_memclk then
					stoTixVTrigger_to_memclk <= stoTixVTrigger;
					stoTixVTrigger_i := 0;
				end if;
			else
				stoTixVTrigger_i := stoTixVTrigger_i + 1;
			end if;

			if strbStart='1' then
				strbStart_to_memclk <= '1';
				strbStart_i := 0;
			elsif strbStart_i=imax then
				strbStart_to_memclk <= '0';
			else
				strbStart_i := strbStart_i + 1;
			end if;

			if strbStop='1' then
				strbStop_to_memclk <= '1';
				strbStop_i := 0;
			elsif strbStop_i=imax then
				strbStop_to_memclk <= '0';
			else
				strbStop_i := strbStop_i + 1;
			end if;

			if reqOpToSeqClear_i=imax then
				if reqOpToSeqClear/=reqOpToSeqClear_to_memclk then
					reqOpToSeqClear_to_memclk <= reqOpToSeqClear;
					reqOpToSeqClear_i := 0;
				end if;
			else
				reqOpToSeqClear_i := reqOpToSeqClear_i + 1;
			end if;

			if reqSeqbufBToSeqClear_i=imax then
				if reqSeqbufBToSeqClear/=reqSeqbufBToSeqClear_to_memclk then
					reqSeqbufBToSeqClear_to_memclk <= reqSeqbufBToSeqClear;
					reqSeqbufBToSeqClear_i := 0;
				end if;
			else
				reqSeqbufBToSeqClear_i := reqSeqbufBToSeqClear_i + 1;
			end if;

		end if;
	end process;
	-- IP impl.mclkToMemclkStretch.rising --- END

	------------------------------------------------------------------------
	-- implementation: memclk to mclk CDC sampling (memclkToMclkSample)
	------------------------------------------------------------------------

	-- IP impl.memclkToMclkSample.wiring --- BEGIN
	-- IP impl.memclkToMclkSample.wiring --- END

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

	begin
		if reset='1' then
			-- IP impl.memclkToMclkSample.asyncrst --- BEGIN
			rdySeq_mclk <= '0';
			rdySeq_to_mclkm1 <= '0';
			rdySeq_to_mclkm2 <= '0';
			dneSeq_mclk <= '0';
			dneSeq_to_mclkm1 <= '0';
			dneSeq_to_mclkm2 <= '0';
			TCapt_mclk <= (others => '0');
			TCapt_to_mclkm1 <= (others => '0');
			TCapt_to_mclkm2 <= (others => '0');
			ptr0Seqbuf_mclk <= 0;
			ptr0Seqbuf_to_mclkm1 <= 0;
			ptr0Seqbuf_to_mclkm2 <= 0;
			start_mclk <= '0';
			start_to_mclkm1 <= '0';
			start_to_mclkm2 <= '0';
			stop_mclk <= '0';
			stop_to_mclkm1 <= '0';
			stop_to_mclkm2 <= '0';
			ackSeqbufBToSeqClear_mclk <= '0';
			ackSeqbufBToSeqClear_to_mclkm1 <= '0';
			ackSeqbufBToSeqClear_to_mclkm2 <= '0';

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

		elsif rising_edge(mclk) then
			if rdySeq_to_mclkm1=rdySeq_to_mclkm2 then
				rdySeq_mclk <= rdySeq_to_mclkm2;
			end if;
			rdySeq_to_mclkm1 <= rdySeq_to_mclk;
			rdySeq_to_mclkm2 <= rdySeq_to_mclkm1;

			if dneSeq_to_mclkm1=dneSeq_to_mclkm2 then
				dneSeq_mclk <= dneSeq_to_mclkm2;
			end if;
			dneSeq_to_mclkm1 <= dneSeq_to_mclk;
			dneSeq_to_mclkm2 <= dneSeq_to_mclkm1;

			if TCapt_to_mclkm1=TCapt_to_mclkm2 then
				TCapt_mclk <= TCapt_to_mclkm2;
			end if;
			TCapt_to_mclkm1 <= TCapt_to_mclk;
			TCapt_to_mclkm2 <= TCapt_to_mclkm1;

			if ptr0Seqbuf_to_mclkm1=ptr0Seqbuf_to_mclkm2 then
				ptr0Seqbuf_mclk <= ptr0Seqbuf_to_mclkm2;
			end if;
			ptr0Seqbuf_to_mclkm1 <= ptr0Seqbuf_to_mclk;
			ptr0Seqbuf_to_mclkm2 <= ptr0Seqbuf_to_mclkm1;

			if start_to_mclkm1=start_to_mclkm2 then
				start_mclk <= start_to_mclkm2;
			end if;
			start_to_mclkm1 <= start_to_mclk;
			start_to_mclkm2 <= start_to_mclkm1;

			if stop_to_mclkm1=stop_to_mclkm2 then
				stop_mclk <= stop_to_mclkm2;
			end if;
			stop_to_mclkm1 <= stop_to_mclk;
			stop_to_mclkm2 <= stop_to_mclkm1;

			if ackSeqbufBToSeqClear_to_mclkm1=ackSeqbufBToSeqClear_to_mclkm2 then
				ackSeqbufBToSeqClear_mclk <= ackSeqbufBToSeqClear_to_mclkm2;
			end if;
			ackSeqbufBToSeqClear_to_mclkm1 <= ackSeqbufBToSeqClear_to_mclk;
			ackSeqbufBToSeqClear_to_mclkm2 <= ackSeqbufBToSeqClear_to_mclkm1;

		end if;
	end process;
	-- IP impl.memclkToMclkSample.rising --- END

	------------------------------------------------------------------------
	-- implementation: memclk to mclk CDC stretching (memclkToMclkStretch)
	------------------------------------------------------------------------

	-- IP impl.memclkToMclkStretch.wiring --- BEGIN
	-- IP impl.memclkToMclkStretch.wiring --- END

	-- IP impl.memclkToMclkStretch.rising --- BEGIN
	process (resetMemclk, memclk)
		-- IP impl.memclkToMclkStretch.vars --- BEGIN
		constant imax: natural := 2;

		variable rdySeq_i: natural range 0 to imax;
		variable dneSeq_i: natural range 0 to imax;
		variable TCapt_i: natural range 0 to imax;
		variable ptr0Seqbuf_i: natural range 0 to imax;
		variable start_i: natural range 0 to imax;
		variable stop_i: natural range 0 to imax;
		variable ackSeqbufBToSeqClear_i: natural range 0 to imax;
		-- IP impl.memclkToMclkStretch.vars --- END

	begin
		if resetMemclk='1' then
			-- IP impl.memclkToMclkStretch.asyncrst --- BEGIN
			rdySeq_to_mclk <= '0';
			dneSeq_to_mclk <= '0';
			TCapt_to_mclk <= (others => '0');
			ptr0Seqbuf_to_mclk <= 0;
			start_to_mclk <= '0';
			stop_to_mclk <= '0';
			ackSeqbufBToSeqClear_to_mclk <= '0';

			rdySeq_i := 0;
			dneSeq_i := 0;
			TCapt_i := 0;
			ptr0Seqbuf_i := 0;
			start_i := 0;
			stop_i := 0;
			ackSeqbufBToSeqClear_i := 0;
			-- IP impl.memclkToMclkStretch.asyncrst --- END
			-- IP impl.memclkToMclkStretch.asyncrst.cust --- INSERT

		elsif rising_edge(memclk) then
			if rdySeq_i=imax then
				if rdySeq/=rdySeq_to_mclk then
					rdySeq_to_mclk <= rdySeq;
					rdySeq_i := 0;
				end if;
			else
				rdySeq_i := rdySeq_i + 1;
			end if;

			if dneSeq_i=imax then
				if dneSeq/=dneSeq_to_mclk then
					dneSeq_to_mclk <= dneSeq;
					dneSeq_i := 0;
				end if;
			else
				dneSeq_i := dneSeq_i + 1;
			end if;

			if TCapt_i=imax then
				if TCapt/=TCapt_to_mclk then
					TCapt_to_mclk <= TCapt;
					TCapt_i := 0;
				end if;
			else
				TCapt_i := TCapt_i + 1;
			end if;

			if ptr0Seqbuf_i=imax then
				if ptr0Seqbuf/=ptr0Seqbuf_to_mclk then
					ptr0Seqbuf_to_mclk <= ptr0Seqbuf;
					ptr0Seqbuf_i := 0;
				end if;
			else
				ptr0Seqbuf_i := ptr0Seqbuf_i + 1;
			end if;

			if start_i=imax then
				if start/=start_to_mclk then
					start_to_mclk <= start;
					start_i := 0;
				end if;
			else
				start_i := start_i + 1;
			end if;

			if stop_i=imax then
				if stop/=stop_to_mclk then
					stop_to_mclk <= stop;
					stop_i := 0;
				end if;
			else
				stop_i := stop_i + 1;
			end if;

			if ackSeqbufBToSeqClear_i=imax then
				if ackSeqbufBToSeqClear/=ackSeqbufBToSeqClear_to_mclk then
					ackSeqbufBToSeqClear_to_mclk <= ackSeqbufBToSeqClear;
					ackSeqbufBToSeqClear_i := 0;
				end if;
			else
				ackSeqbufBToSeqClear_i := ackSeqbufBToSeqClear_i + 1;
			end if;

		end if;
	end process;
	-- IP impl.memclkToMclkStretch.rising --- END

end Rtl;
