-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.

-- Copyright (C) 1991-2010 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions 
-- and other software and tools, and its AMPP partner logic 
-- functions, and any output files from any of the foregoing 
-- (including device programming or simulation files), and any 
-- associated documentation or information are expressly subject 
-- to the terms and conditions of the Altera Program License 
-- Subscription Agreement, Altera MegaCore Function License 
-- Agreement, or other applicable license agreement, including, 
-- without limitation, that your use is for the sole purpose of 
-- programming logic devices manufactured by Altera and sold by 
-- Altera or its authorized distributors.  Please refer to the 
-- applicable agreement for further details.


-- Generated by Quartus II Version 9.1 (Build Build 350 03/24/2010)
-- Created on Sat Jan 15 11:06:17 2011
INCLUDE "lpm_bustri_WORD.inc";
INCLUDE "VIDEO/BLITTER/lpm_clshift384.INC";
INCLUDE "VIDEO/BLITTER/altsyncram0.INC";
INCLUDE "VIDEO/BLITTER/lpm_clshift144.inc";
INCLUDE "VIDEO/BLITTER/lpm_ror128.inc";


--CONSTANT	BL_SKEW_LF = 255;

--  Title Statement (optional)
TITLE "Blitter";


--  Parameters Statement (optional)

-- {{ALTERA_PARAMETERS_BEGIN}} DO NOT REMOVE THIS LINE!
-- {{ALTERA_PARAMETERS_END}} DO NOT REMOVE THIS LINE!


--  Subdesign Section

SUBDESIGN BLITTER
(
	-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
	nRSTO : INPUT;
	MAIN_CLK : INPUT;
	FB_ALE : INPUT;
	nFB_WR : INPUT;
	nFB_OE : INPUT;
	FB_SIZE0 : INPUT;
	FB_SIZE1 : INPUT;
	VIDEO_RAM_CTR[15..0] : INPUT;
	BLITTER_ON : INPUT;
	FB_ADR[31..0] : INPUT;
	nFB_CS1 : INPUT;
	nFB_CS2 : INPUT;
	nFB_CS3 : INPUT;
	DDRCLK0 : INPUT;
	VDP_IN[63..0] : INPUT;
	BLITTER_DACK[4..0] : INPUT;
	SR_BLITTER_DACK : INPUT;
	BLITTER_RUN : OUTPUT;
	BLITTER_INT : OUTPUT;
	BLITTER_DOUT[127..0] : OUTPUT;
	BLITTER_ADR[31..0] : OUTPUT;
	BLITTER_SIG : OUTPUT;
	BLITTER_WR : OUTPUT;
	BLITTER_TA : OUTPUT;
	FB_AD[31..0] : BIDIR;
	-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
)

VARIABLE
	BYT							:NODE;
	FB_16B[1..0]				:NODE;
	BLITTER_CS					:NODE;
	BL_HRAM_CS 					:NODE;
	DP_RAM_CS					:NODE;
	BL_HRAM_BE[1..0]			:NODE;
	BL_HRAM_OUT[15..0]			:NODE;
	BL_DPRAM_OUT[15..0]			:NODE;
	BL_SRC_X_INC_CS				:NODE;
	BL_SRC_X_INC[15..0]			:DFFE;
	SRC_ADR_INC[31..0]			:NODE;
	SRC_XINC32[31..0]			:NODE;
	BL_SRC_Y_INC_CS				:NODE;
	BL_SRC_Y_INC[15..0]			:DFFE;
	SRC_YINC32[31..0]			:NODE;
	BL_ENDMASK1_CS				:NODE;
	BL_ENDMASK1[15..0]			:DFFE;
	BL_ENDMASK2_CS				:NODE;
	BL_ENDMASK2[15..0]			:DFFE;
	BL_ENDMASK3_CS				:NODE;
	BL_ENDMASK3[15..0]			:DFFE;
	BL_ENDMASK0[15..0]			:NODE;
	BL_ENDMASKF[15..0]			:NODE;
	BL_ENDMASKL[15..0]			:NODE;
	BL_ENDMASKR[15..0]			:NODE;
	BL_SRC_ADRH_CS				:NODE;
	BL_SRC_ADRL_CS				:NODE;
	BL_SRC_ADR[31..0]			:DFFE;
	SRC_OLD[27..0]				:DFFE;
	SRC_IADRH_CS				:NODE;
	SRC_IADRL_CS				:NODE;
	SRC_IADR[31..0]				:DFF;
	SRC_IADR_CLR				:DFF;
	SRC_ADR32[31..0]			:NODE;
	BL_DST_X_INC_CS				:NODE;
	BL_DST_X_INC[15..0]			:DFFE;
	DST_ADR_INC[31..0]			:NODE;
	DST_XINC32[31..0]			:NODE;
	BL_DST_Y_INC_CS				:NODE;
	BL_DST_Y_INC[15..0]			:DFFE;
	DST_YINC32[31..0]			:NODE;
	BL_DST_ADRH_CS				:NODE;
	BL_DST_ADRL_CS				:NODE;
	BL_DST_ADR[31..0]			:DFFE;
	DST_IADRH_CS				:NODE;
	DST_IADRL_CS				:NODE;
	DST_IADR[31..0]				:DFF;
	DST_IADR_CLR				:DFF;
	DST_ADR32[31..0]			:NODE;
	BL_X_CNT_CS					:NODE;
	BL_X_CNT[15..0]				:DFFE;
	X_CNT16[15..0]				:NODE;
	BL_Y_CNT_CS					:NODE;
	BL_Y_CNT[15..0]				:DFFE;
	BL_HOP_CS					:NODE;
	BL_HOP[7..0]				:DFFE;
	BL_OP[7..0]					:DFFE;
	BL_LN_CS					:NODE;
	BL_LN_WR					:NODE;
	LN7_CLR						:NODE;
	BL_LN[7..0]					:DFFE;
	BL_SKEW[7..0]				:DFFE;
-- barell shifter
	DIST_RIGHT[8..0]			:NODE;
	BS_SKEW[7..0]				:NODE;
	BL_BSIN[383..0]				:NODE;
	BL_BSOUT[383..0]			:NODE;
	SHIFT_DIR					:NODE;
	BL_SRC_BUF1[127..0]			:DFFE;
	BL_SRC_BUF2[127..0]			:DFFE;
	BL_SRC_BUF3[127..0]			:DFFE;
	BL_DST_BUFRD[127..0]		:DFFE;	
	BL_READ_DST					:NODE;				-- LATCH SIGNAL DST BUF RD
	BL_READ_SRC					:NODE;				-- LATCH SIGNAL SRC BUF
	SRC_READ					:NODE;				-- FREIGABE LATCH SIGNAL
	NOT_DST_READ				:NODE;
	WREN_B						:NODE;				-- WR ENA HALFTONE RAM
	X_INDEX_CS					:NODE;
	X_INDEX[15..0]				:DFF;				-- LAUFZEIGER X COUNT
	X_INDEX_CLR					:DFF;				-- X INDEX LÖSCHEN CPU WRITE
	X_INDEX_CLR_DIR				:NODE;				-- X INDEX LÖSCHEN STATE MACHINE
	DST_X_INC[15..0]			:NODE;				-- ANZAHL WORTE PRO DURCHLAUF
	X_CNT_T[15..0]				:NODE;
	Y_INDEX_CS					:NODE;
	Y_INDEX[15..0]				:DFF;				-- LAUFZEIGER Y COUNT
	Y_INDEX_CLR					:DFF;
	LINE_NR[3..0]				:NODE;
	SDXINC						:DFF;				-- INC INDEX SPALTE
	YIINC						:NODE;				-- INC INDEX ZEILE
	ZAINC						:NODE;				-- INC ADRESSEN ZEILENUMBRUCH
	HOP_OUT[127..0]				:NODE;
	OP_OUT[127..0]				:NODE;
	ENDMASK1_SHIFT[7..0]		:NODE;
	ENDMASK2_SHIFT[7..0]		:NODE;
	ENDMASK12_IN[143..0]		:NODE;
	ENDMASK12_OUT[143..0]		:NODE;
	ENDMASK23_IN[143..0]		:NODE;
	ENDMASK23_OUT[143..0]		:NODE;
	ENDMASKM_IN[127..0]			:NODE;
	ENDMASKM_OUT[127..0]		:NODE;
	ROR_CNT[8..0]				:NODE;
	ENDMASK123[127..0]			:DFF;
	ENDMASKEND[31..0]			:NODE;
	BLITTER_SIG					:DFF;
	BLITTER_REQ					:NODE;
	BL_START					:DFF;
	BL_NOTRUN					:NODE;
	
-- MAIN STATE MACHINE
	BL_SM						:MACHINE WITH STATES(START,NEW_LINE,RDSRC3,RDSRC2,RDSRC1,RDDST,WRDSTW,WRDST,TESTZEILENENDE,TESTFERTIG,FERTIG);	
	
BEGIN
-- BYT UND WORD SELECT 16 BIT
	BYT      = !FB_SIZE1 &  FB_SIZE0;
	FB_16B0 = FB_ADR[0]==0;										-- wenn ADR==0
	FB_16B1 = FB_ADR[0]==1 # !BYT;								-- wenn ADR==1 or NOT BYT
-- BLITTER CS
	BLITTER_CS = !nFB_CS1 & FB_ADR[19..7]==H"1F14";				-- FFFF8A00-7F  
	BLITTER_TA = BLITTER_CS;
-- REGISTER
	-- HALFTON RAM 
	BL_HRAM_CS = !nFB_CS1 & FB_ADR[19..5]==H"7C50";						-- $F8A00-1F.w
	BL_HRAM_BE1 = BL_HRAM_CS & FB_16B0;
	BL_HRAM_BE0 = BL_HRAM_CS & FB_16B1;
	WREN_B = B"0";
	LINE_NR[] = BL_LN[3..0] + ((Y_INDEX[3..0] & !BL_DST_X_INC15) - (Y_INDEX[3..0] & BL_DST_X_INC15));
	(BL_DPRAM_OUT[],BL_HRAM_OUT[]) = altsyncram0(FB_ADR[4..1],LINE_NR[],BL_HRAM_BE[],MAIN_CLK,DDRCLK0,FB_AD[31..16],FB_AD[31..16],BL_HRAM_CS & !nFB_WR,WREN_B);
	DP_RAM_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C528";							-- $F8A50.w
	-- SRC X INC
	BL_SRC_X_INC[].CLK = MAIN_CLK;
	BL_SRC_X_INC[15..1] = FB_AD[31..17];
	BL_SRC_X_INC0 = GND;
	BL_SRC_X_INC_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C510");						-- $F8A20.w
	BL_SRC_X_INC[15..8].ENA = BL_SRC_X_INC_CS & !nFB_WR & FB_16B0;
	BL_SRC_X_INC[7..0].ENA  = BL_SRC_X_INC_CS & !nFB_WR & FB_16B1;
	SRC_XINC32[15..0]  = BL_SRC_X_INC[];											-- ERWEITERN AUF 32 BIT
	SRC_XINC32[31..16] = H"FFFF" & BL_SRC_X_INC15;									-- ERWEITERN AUF 32 BIT
	-- SRC Y INC
	BL_SRC_Y_INC[].CLK = MAIN_CLK;
	BL_SRC_Y_INC[15..1] = FB_AD[31..17];
	BL_SRC_Y_INC0 = GND;
	BL_SRC_Y_INC_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C511");						-- $F8A22.w
	BL_SRC_Y_INC[15..8].ENA = BL_SRC_Y_INC_CS & !nFB_WR & FB_16B0;
	BL_SRC_Y_INC[7..0].ENA  = BL_SRC_Y_INC_CS & !nFB_WR & FB_16B1;
	SRC_YINC32[15..0]  = BL_SRC_Y_INC[];											-- ERWEITERN AUF 32 BIT
	SRC_YINC32[31..16] = H"FFFF" & BL_SRC_Y_INC15;									-- ERWEITERN AUF 32 BIT
	-- SRC ADR HIGH
	BL_SRC_ADR[].CLK = MAIN_CLK;
	BL_SRC_ADR[31..16] = FB_AD[31..16];
	BL_SRC_ADRH_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C512");						-- $F8A24.w
	BL_SRC_ADR[31..24].ENA = BL_SRC_ADRH_CS & !nFB_WR & FB_16B0;
	BL_SRC_ADR[23..16].ENA = BL_SRC_ADRH_CS & !nFB_WR & FB_16B1;
	-- SRC ADR LOW
	BL_SRC_ADR[].CLK = MAIN_CLK;
	BL_SRC_ADR[15..1] = FB_AD[31..17];
	BL_SRC_ADR0 = GND;
	BL_SRC_ADRL_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C513");						-- $F8A26.w
	BL_SRC_ADR[15..8].ENA = BL_SRC_ADRL_CS & !nFB_WR & FB_16B0;
	BL_SRC_ADR[7..0].ENA  = BL_SRC_ADRL_CS & !nFB_WR & FB_16B1;
	SRC_IADR[].CLK = DDRCLK0;
	SRC_IADRH_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C520");							-- $F8A40.w
	SRC_IADRL_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C521");							-- $F8A42.w
	SRC_IADR_CLR.CLK = MAIN_CLK;
	SRC_IADR_CLR = (BL_SRC_ADRL_CS # BL_SRC_ADRH_CS) & !nFB_WR;				-- LÖSCHEN BEI WRITE
	SRC_IADR[] = (((SRC_IADR[] + (SRC_ADR_INC[] & SDXINC)) & !ZAINC) + ((((((0,BL_X_CNT[]) - 1) * SRC_XINC32[]) + SRC_YINC32[]) * (0,Y_INDEX[])) & ZAINC)) & SRC_READ & !SRC_IADR_CLR;
	SRC_ADR32[] = BL_SRC_ADR[] + SRC_IADR[];							-- ZUGRIFFSADRESSE THEORETISCH 
	-- ENDMASK 1
	BL_ENDMASK1[].CLK = MAIN_CLK;
	BL_ENDMASK1[] = FB_AD[31..16];
	BL_ENDMASK1_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C514");						-- $F8A28.w
	BL_ENDMASK1[15..8].ENA = BL_ENDMASK1_CS & !nFB_WR & FB_16B0;
	BL_ENDMASK1[7..0].ENA  = BL_ENDMASK1_CS & !nFB_WR & FB_16B1;
	-- ENDMASK 2
	BL_ENDMASK2[].CLK = MAIN_CLK;
	BL_ENDMASK2[] = FB_AD[31..16];
	BL_ENDMASK2_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C515");						-- $F8A2A.w
	BL_ENDMASK2[15..8].ENA = BL_ENDMASK2_CS & !nFB_WR & FB_16B0;
	BL_ENDMASK2[7..0].ENA  = BL_ENDMASK2_CS & !nFB_WR & FB_16B1;
	-- ENDMASK 3
	BL_ENDMASK3[].CLK = MAIN_CLK;
	BL_ENDMASK3[] = FB_AD[31..16];
	BL_ENDMASK3_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C516");						-- $F8A2C.w
	BL_ENDMASK3[15..8].ENA = BL_ENDMASK3_CS & !nFB_WR & FB_16B0;
	BL_ENDMASK3[7..0].ENA  = BL_ENDMASK3_CS & !nFB_WR & FB_16B1;
	-- DST X INC
	BL_DST_X_INC[].CLK = MAIN_CLK;
	BL_DST_X_INC[15..1] = FB_AD[31..17];
	BL_DST_X_INC0 = GND;
	BL_DST_X_INC_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C517");						-- $F8A2E.w
	BL_DST_X_INC[15..8].ENA = BL_DST_X_INC_CS & !nFB_WR & FB_16B0;
	BL_DST_X_INC[7..0].ENA  = BL_DST_X_INC_CS & !nFB_WR & FB_16B1;
	DST_XINC32[15..0]  = BL_DST_X_INC[];											-- ERWEITERN AUF 32 BIT
	DST_XINC32[31..16] = H"FFFF" & BL_DST_X_INC15;									-- ERWEITERN AUF 32 BIT
	-- DST Y INC
	BL_DST_Y_INC[].CLK = MAIN_CLK;
	BL_DST_Y_INC[15..1] = FB_AD[31..17];
	BL_DST_Y_INC0 = GND;
	BL_DST_Y_INC_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C518");						-- $F8A30.w
	BL_DST_Y_INC[15..8].ENA = BL_DST_Y_INC_CS & !nFB_WR & FB_16B0;
	BL_DST_Y_INC[7..0].ENA  = BL_DST_Y_INC_CS & !nFB_WR & FB_16B1;
	DST_YINC32[15..0]  = BL_DST_Y_INC[];											-- ERWEITERN AUF 32 BIT
	DST_YINC32[31..16] = H"FFFF" & BL_DST_Y_INC15;									-- ERWEITERN AUF 32 BIT
	-- DST ADR HIGH
	BL_DST_ADR[].CLK = MAIN_CLK;
	BL_DST_ADR[31..16] = FB_AD[31..16];
	BL_DST_ADRH_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C519");						-- $F8A32.w
	BL_DST_ADR[31..24].ENA = BL_DST_ADRH_CS & !nFB_WR & FB_16B0;
	BL_DST_ADR[23..16].ENA = BL_DST_ADRH_CS & !nFB_WR & FB_16B1;
	-- DST ADR LOW
	BL_DST_ADR[].CLK = MAIN_CLK;
	BL_DST_ADR[15..1] = FB_AD[31..17];
	BL_DST_ADR0 = GND;
	BL_DST_ADRL_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C51A");						-- $F8A34.w
	BL_DST_ADR[15..8].ENA = BL_DST_ADRL_CS & !nFB_WR & FB_16B0;
	BL_DST_ADR[7..0].ENA  = BL_DST_ADRL_CS & !nFB_WR & FB_16B1;
	DST_IADR[].CLK = DDRCLK0;
	DST_IADRH_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C522");							-- $F8A44.w
	DST_IADRL_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C523");							-- $F8A46.w
	DST_IADR_CLR.CLK = MAIN_CLK;					
	DST_IADR_CLR = (BL_DST_ADRL_CS # BL_DST_ADRH_CS) & !nFB_WR;					-- LÖSCHEN BEI WRITE
	DST_IADR[] = (((DST_IADR[] + (DST_ADR_INC[] & SDXINC)) & !ZAINC) + ((((((0,BL_X_CNT[]) - 1) * DST_XINC32[]) + DST_YINC32[]) * (0,Y_INDEX[])) & ZAINC)) & !DST_IADR_CLR;
	DST_ADR32[] = BL_DST_ADR[] + DST_IADR[];									-- ZUGRIFFSADRESSE THEORETISCH
	-- X COUNT
	BL_X_CNT[].CLK = MAIN_CLK;
	BL_X_CNT[] = FB_AD[31..16];
	BL_X_CNT_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C51B");							-- $F8A36.w
	BL_X_CNT[15..8].ENA = BL_X_CNT_CS & !nFB_WR & FB_16B0;
	BL_X_CNT[7..0].ENA  = BL_X_CNT_CS & !nFB_WR & FB_16B1;
	X_INDEX[].CLK = DDRCLK0;
	X_INDEX_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C524");							-- $F8A48.w
	X_INDEX_CLR.CLK = MAIN_CLK;
	X_INDEX_CLR = BL_X_CNT_CS & !nFB_WR;										-- LÖSCHEN BEI WRITE
	X_INDEX[] = ((X_INDEX[] & !ZAINC) + (DST_X_INC[] & SDXINC) + (BL_X_CNT[] & ZAINC)) & !X_INDEX_CLR & !X_INDEX_CLR_DIR;
	X_CNT16[] = X_INDEX[] - (X_CNT_T[] & (X_INDEX[]!=0));		-- EFFEKTIV geschrieben
-- SCHRITTWEITEN BEI PALLETTENMOD
	IF (BL_SRC_X_INC[] != BL_DST_X_INC[]) # (BL_X_CNT[] < 4) THEN 
		DST_X_INC[] = 1;
		X_CNT_T[] = 0;
		SRC_ADR_INC[] = SRC_XINC32[];		-- SRC X INC
		DST_ADR_INC[] = DST_XINC32[];		-- DST X INC
	ELSE		
		IF BL_SRC_X_INC[] == H"0002" THEN 
			DST_X_INC[] = 8;
			X_CNT_T[] = (0,DST_ADR32[3..1]);
			SRC_ADR_INC[] = 16;						-- SRC X INC
			DST_ADR_INC[] = 16;						-- DST X INC
		ELSE
			IF BL_SRC_X_INC[] == H"FFFE" THEN 
				DST_X_INC[] = 8;
				X_CNT_T[] = 7 - (0,DST_ADR32[3..1]);
				SRC_ADR_INC[] = -16;				-- SRC X INC
				DST_ADR_INC[] = -16;				-- DST X INC
			ELSE							
				IF BL_SRC_X_INC[] == H"0004" THEN 
					DST_X_INC[] = 4;
					X_CNT_T[] = (0,DST_ADR32[3..2]);
					SRC_ADR_INC[] = 16;						-- SRC X INC
					DST_ADR_INC[] = 16;						-- DST X INC
				ELSE
					IF BL_SRC_X_INC[] == H"FFFC" THEN 
						DST_X_INC[] = 4;
						X_CNT_T[] = 3 - (0,DST_ADR32[3..2]);
						SRC_ADR_INC[] = -16;				-- SRC X INC
						DST_ADR_INC[] = -16;				-- DST X INC
					ELSE							
						IF BL_SRC_X_INC[] == H"0008" THEN 
							DST_X_INC[] = 2;
							X_CNT_T[] = (0,DST_ADR32[3]);
							SRC_ADR_INC[] = 16;						-- SRC X INC
							DST_ADR_INC[] = 16;						-- DST X INC
						ELSE
							IF BL_SRC_X_INC[] == H"FFF8" THEN 
								DST_X_INC[] = 2;
								X_CNT_T[] = 1 - (0,DST_ADR32[3]);
								SRC_ADR_INC[] = -16;				-- SRC X INC
								DST_ADR_INC[] = -16;				-- DST X INC
							ELSE							
								DST_X_INC[] = 1;
								X_CNT_T[] = 0;
								SRC_ADR_INC[] = SRC_XINC32[];		-- SRC X INC
								DST_ADR_INC[] = DST_XINC32[];		-- DST X INC
							END IF;
						END IF;
					END IF;
				END IF;
			END IF;
		END IF;
	END IF;
	-- Y COUNT
	BL_Y_CNT[].CLK = MAIN_CLK;
	BL_Y_CNT[] = FB_AD[31..16];
	BL_Y_CNT_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C51C";							-- $F8A38.w
	BL_Y_CNT[15..8].ENA = BL_Y_CNT_CS & !nFB_WR & FB_16B0;
	BL_Y_CNT[7..0].ENA  = BL_Y_CNT_CS & !nFB_WR & FB_16B1;
	Y_INDEX[].CLK = DDRCLK0;
	Y_INDEX_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C525";							-- $F8A4A.w
	Y_INDEX_CLR.CLK = MAIN_CLK;
	Y_INDEX_CLR = BL_Y_CNT_CS & !nFB_WR;										-- LÖSCHEN BEI WRITE
	Y_INDEX[] = (Y_INDEX[] + (1 & YIINC)) & !Y_INDEX_CLR;
	-- HOP LOGIC
	BL_HOP[].CLK = MAIN_CLK;
	BL_HOP[] = FB_AD[31..24];
	BL_HOP_CS = !nFB_CS1 & FB_ADR[19..1]==H"7C51D";								-- $F8A3A.w
	BL_HOP[7..0].ENA  = BL_HOP_CS & !nFB_WR & FB_16B0;							-- $F8A3A
	-- OP LOGIC
	BL_OP[].CLK = MAIN_CLK;
	BL_OP[] = FB_AD[23..16];
	BL_OP[7..0].ENA  = BL_HOP_CS & !nFB_WR & FB_16B1;							-- $F8A3B
	-- LINE NUMBER BYT
	BL_LN[].CLK = MAIN_CLK;
	BL_LN_CS = !nFB_CS1 & (FB_ADR[19..1] == H"7C51E");							-- $F8A3C.w
	BL_LN_WR = BL_LN_CS & !nFB_WR & FB_16B0;									-- $F8A3C WRITE SIGNAL
	BL_LN[6..0] = FB_AD[30..24];												-- HOG UND SMUDGE
	BL_LN[6..0].ENA  = BL_LN_WR;													-- $F8A3C
	BL_LN7.ENA  = BL_LN_WR # LN7_CLR;													-- $F8A3C
	BL_LN7 = FB_AD31 & BLITTER_ON & (BL_X_CNT[] > X_CNT16[]) & (BL_Y_CNT[] > Y_INDEX[]) & !LN7_CLR; -- BUSY 
	BL_START.CLK = MAIN_CLK;
	BL_START = BL_LN7 & !BL_LN_CS & BLITTER_ON & (BL_X_CNT[] > X_CNT16[]) & (BL_Y_CNT[] > Y_INDEX[]) & !LN7_CLR; 
	-- SKEW BYT
	BL_SKEW[].CLK = MAIN_CLK;
	BL_SKEW[] = FB_AD[23..16];
	BL_SKEW[].ENA  = BL_LN_CS & !nFB_WR & FB_16B1;								-- $F8A3D
--- REGISTER OUT
	FB_AD[31..16] = lpm_bustri_WORD(
						BL_HRAM_CS	    & BL_DPRAM_OUT[]
					  # BL_SRC_X_INC_CS & BL_SRC_X_INC[]
					  # BL_SRC_Y_INC_CS & BL_SRC_Y_INC[]
					  # BL_SRC_ADRH_CS  & SRC_ADR32[31..16]
					  # BL_SRC_ADRL_CS  & SRC_ADR32[15..0]
					  # BL_ENDMASK1_CS  & BL_ENDMASK1[]
					  # BL_ENDMASK2_CS  & BL_ENDMASK2[]
					  # BL_ENDMASK3_CS  & BL_ENDMASK3[]
					  # BL_DST_X_INC_CS & BL_DST_X_INC[]
					  # BL_DST_Y_INC_CS & BL_DST_Y_INC[]
					  # BL_DST_ADRH_CS  & DST_ADR32[31..16]
					  # BL_DST_ADRL_CS  & DST_ADR32[15..0]
					  # BL_X_CNT_CS 	& (BL_X_CNT[]-X_INDEX[])
					  # BL_Y_CNT_CS 	& (BL_Y_CNT[]-Y_INDEX[])
					  # BL_HOP_CS 		& (BL_HOP[],BL_OP[])
					  # BL_LN_CS 		& (BL_LN7 # !BL_NOTRUN,BL_LN[6..0],BL_SKEW[])		
					  # SRC_IADRH_CS	& SRC_IADR[31..16]
					  # SRC_IADRL_CS	& SRC_IADR[15..0]
					  # DST_IADRH_CS	& DST_IADR[31..16]
					  # DST_IADRL_CS	& DST_IADR[15..0]
					  # X_INDEX_CS		& X_INDEX[]
					  # Y_INDEX_CS		& Y_INDEX[]
					  # DP_RAM_CS		& BL_HRAM_OUT[]
					  ,BLITTER_CS & !nFB_OE); 									-- FFFF8A00-7F
--------------------------------------------------------------------------------------
-- SRC BUFFER LADEN
	BL_SRC_BUF1[].CLK = DDRCLK0;
	BL_SRC_BUF1[127..64].ENA = BLITTER_DACK1 & BL_READ_SRC;
	BL_SRC_BUF1[63..0].ENA   = BLITTER_DACK0 & BL_READ_SRC;
	BL_SRC_BUF1[] = (VDP_IN[],VDP_IN[]);
	BL_SRC_BUF2[].CLK = DDRCLK0;
	BL_SRC_BUF2[127..64].ENA = BLITTER_DACK1 & BL_READ_SRC;
	BL_SRC_BUF2[63..0].ENA   = BLITTER_DACK0 & BL_READ_SRC;
	BL_SRC_BUF2[] = BL_SRC_BUF1[];
	BL_SRC_BUF3[].CLK = DDRCLK0;
	BL_SRC_BUF3[127..64].ENA = BLITTER_DACK1 & BL_READ_SRC;
	BL_SRC_BUF3[63..0].ENA   = BLITTER_DACK0 & BL_READ_SRC;
	BL_SRC_BUF3[] = BL_SRC_BUF2[];
	-- ZUORDNUNG ---------------------------------------------------
	IF BL_SRC_X_INC15 THEN		-- WENN NEGATIV -> REIHENFOLGE KEHREN
		BL_BSIN[127..0]   = BL_SRC_BUF3[];
		BL_BSIN[255..128] = BL_SRC_BUF2[];
		BL_BSIN[383..256] = BL_SRC_BUF1[];
	ELSE						-- SONST NORMAL BEI VORWÄRTS
		BL_BSIN[127..0]   = BL_SRC_BUF1[];
		BL_BSIN[255..128] = BL_SRC_BUF2[];
		BL_BSIN[383..256] = BL_SRC_BUF3[];
	END IF;
-- DST BUFFER READ	
	BL_DST_BUFRD[].CLK = DDRCLK0;
	BL_DST_BUFRD[127..64].ENA = BLITTER_DACK1 & BL_READ_DST;
	BL_DST_BUFRD[63..0].ENA   = BLITTER_DACK0 & BL_READ_DST;
	BL_DST_BUFRD[] = (VDP_IN[],VDP_IN[]);
-- barell shift *****************************************************************************
-- SOURCE SHIFT RIGHT = LPM_CSHIFT RIGTH ;SKEW SHIFT: IF FXRS==0 THEN RIGHT ELSE LEFT
	DIST_RIGHT[] = (16 * ((0,DST_ADR32[3..1]) - (0,SRC_ADR32[3..1]))) + (!BL_SKEW7 &  (0,BL_SKEW[3..0])) - (BL_SKEW7 & (0,BL_SKEW[3..0]));
	IF DIST_RIGHT8 THEN 		
		BS_SKEW[] = 0 - DIST_RIGHT[7..0]; 					-- LPM SHIFT LEFT
		SHIFT_DIR = GND;									-- DIR = LEFT
	else													
		BS_SKEW[] = DIST_RIGHT[7..0]; 						-- LPM SHIFT RIGHT
		SHIFT_DIR = VCC;									-- DIR = RIGHT
	end if;
-- barell shifter: direction 0=links 1=rechts IN BEZUG AUF ausgabewert!
	BL_BSOUT[] = lpm_clshift384(BL_BSIN[], SHIFT_DIR , BS_SKEW[]);	-- wir brauchen 128bit
-- HOP ***************************************************************************************
	CASE BL_HOP[1..0] IS
		WHEN H"0" =>
					--    12345678901234567890123456789012
			HOP_OUT[] = H"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
		WHEN H"1" =>
			HOP_OUT[] = (BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[]);
		WHEN H"2" =>
			HOP_OUT[] = BL_BSOUT[255..128];
		WHEN OTHERS =>
			HOP_OUT[] = (BL_BSOUT[255..128] & (BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[],BL_HRAM_OUT[]));
	END CASE;
-- OP *****************************************************************************************
	CASE BL_OP[3..0] IS
		WHEN H"0" =>
			OP_OUT[] = H"0";
			SRC_READ = B"0";
		WHEN H"1" =>
			OP_OUT[] = HOP_OUT[] AND BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"2" =>
			OP_OUT[] = HOP_OUT[] AND !BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"3" =>
			OP_OUT[] = HOP_OUT[];
			SRC_READ = BL_HOP1;
		WHEN H"4" =>
			OP_OUT[] = !HOP_OUT[] AND BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"5" =>
			OP_OUT[] = BL_DST_BUFRD[];
			SRC_READ = B"0";
		WHEN H"6" =>
			OP_OUT[] = HOP_OUT[] XOR BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"7" =>
			OP_OUT[] = HOP_OUT[] OR BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"8" =>
			OP_OUT[] = !HOP_OUT[] AND !BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"9" =>
			OP_OUT[] = !HOP_OUT[] XOR BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"A" =>
			OP_OUT[] = !BL_DST_BUFRD[];
			SRC_READ = B"0";
		WHEN H"B" =>
			OP_OUT[] = HOP_OUT[] OR !BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"C" =>
			OP_OUT[] = !HOP_OUT[];
			SRC_READ = BL_HOP1;
		WHEN H"D" =>
			OP_OUT[] = !HOP_OUT[] OR BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN H"E" =>
			OP_OUT[] = !HOP_OUT[] OR !BL_DST_BUFRD[];
			SRC_READ = BL_HOP1;
		WHEN OTHERS =>
					--   12345678901234567890123456789012
			OP_OUT[] = H"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
			SRC_READ = B"0";
	END CASE;
------------ ENDMASKEN SETZEN ******************************************************************************																							 
			ENDMASK1_SHIFT[3..0] = 0; 						
			ENDMASK2_SHIFT[3..0] = 0; 
			ENDMASKEND[] =  DST_ADR32[] + (0,(BL_X_CNT[] - X_INDEX[]) - 1) * DST_XINC32[];					
			IF BL_DST_X_INC15 THEN ---------------------------- RÜCKWÄRTS X_INC NEGATIV
				IF X_INDEX[] == 0 THEN															-- ENDE?	
					ENDMASK2_SHIFT[7..4] = 8 - (0,(DST_ADR32[3..1]));							-- JA ENDMASK 3 SETZEN 
				ELSE					
					ENDMASK2_SHIFT[7..4] = 0;													-- NEIN -> ENDMASK 3 AUF ENDMASK2 SETZEN 
				END IF;	 
				IF (X_CNT16[] + DST_X_INC[]) >= BL_X_CNT[] THEN									-- SCHON ZEILENENDE?	
					ENDMASK1_SHIFT[7..4] = 1 + (0,(ENDMASKEND[3..1]));							-- JA -> ENDMASK 1 SETZEN 
				ELSE					
					ENDMASK1_SHIFT[7..4] = 0;													-- NEIN -> ENDMASK 3 AUF ENDMASK2 SETZEN 
				END IF;
			ELSE	------------------------------------------- VORWÄRTS X_INC POSITIV (immer bei memcopy)
				IF X_INDEX[] == 0 THEN															-- ANFANG?	
					ENDMASK1_SHIFT[7..4] = 1 + (0,(DST_ADR32[3..1])); 							-- JA -> ENDMASK 1 SETZEN 
				ELSE		
					ENDMASK1_SHIFT[7..4] = 0;													-- NEIN->ENDMASK1  AUF ENDMASK2 SETZEN 
				END IF;		
				IF (X_CNT16[] + DST_X_INC[]) >= BL_X_CNT[] THEN									-- SCHON ZEILENENDE?	
					ENDMASK2_SHIFT[7..4] = 8 - (0,(ENDMASKEND[3..1]));							-- JA: ENDMASK 3 SETZEN
				ELSE					
					ENDMASK2_SHIFT[7..4] = 0;													-- NOCH NICHT AKTIV->ENDMASK 3 AUF ENDMASK2 SETZEN 
				END IF;	 
			END IF;
-- ENDMASKEN -- barell shifter 144 bit, direction 0 = links 1 = rechts
		BL_ENDMASK0[] = 0;
		BL_ENDMASKF[] = -1;
		BL_ENDMASKL[] = BL_ENDMASK1[] & !BL_DST_X_INC15 # BL_ENDMASK3[] & BL_DST_X_INC15;
		BL_ENDMASKR[] = BL_ENDMASK3[] & !BL_DST_X_INC15 # BL_ENDMASK1[] & BL_DST_X_INC15;
	CASE DST_X_INC[] IS
		WHEN 8 => 	-- INC 2
			ENDMASK12_IN[] = (BL_ENDMASKL[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[]);
			ENDMASKM_IN[]  =               (BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[],BL_ENDMASKF[]);
			ENDMASK23_IN[] =               (BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASKR[]);
		WHEN 4 =>	-- INC 4
			ENDMASK12_IN[] = (BL_ENDMASKL[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[]);
			ENDMASKM_IN[]  =               (BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASKF[],BL_ENDMASK0[]);
			ENDMASK23_IN[] =               (BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASKR[]);
		WHEN 2 =>	-- INC 8
			ENDMASK12_IN[] = (BL_ENDMASKL[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[]);
			ENDMASKM_IN[]  =               (BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[]);
			ENDMASK23_IN[] =               (BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASKR[]);
		WHEN OTHERS =>
			ENDMASK12_IN[] = (BL_ENDMASKL[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[]);
			ENDMASKM_IN[]  =               (BL_ENDMASKF[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[],BL_ENDMASK0[]);
			ENDMASK23_IN[] =               (BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASK2[],BL_ENDMASKR[]);
	END CASE;
	ENDMASK12_OUT[] = lpm_clshift144(ENDMASK12_IN[],1,ENDMASK1_SHIFT[]);			-- IMMER rechts SCHIEBEN
	ENDMASK23_OUT[] = lpm_clshift144(ENDMASK23_IN[],0,ENDMASK2_SHIFT[]);			-- IMMER LINKS SCHIEBEN	
	ROR_CNT[] = 16 * (0,DST_ADR32[3..1]);
	ENDMASKM_OUT[] = lpm_ror128(ENDMASKM_IN[],ROR_CNT[6..0]);
	ENDMASK123[].CLK = DDRCLK0;
	ENDMASK123[] = ENDMASK12_OUT[127..0] & ENDMASK23_OUT[143..16] & ENDMASKM_OUT[];
	BLITTER_DOUT[] = ((ENDMASK123[] & OP_OUT[]) # (!ENDMASK123[] & BL_DST_BUFRD[]));
	NOT_DST_READ = ((BL_OP[3..0] == H"0") # (BL_OP[3..0] == H"3") # (BL_OP[3..0] == H"C") # (BL_OP[3..0] == H"F")) & (ENDMASK123[] == H"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
-- STATE MACHINE **********************************************************************************---------------------------12345678901234567890123456789012 	
	BLITTER_RUN = BLITTER_ON;										-- BLITTER IST DA!
	BLITTER_ADR[3..0] = H"0";										-- IMMER LINE
	BLITTER_SIG.CLK = DDRCLK0;
	BLITTER_SIG = BLITTER_REQ & !BLITTER_DACK0 & !BLITTER_DACK1;
-- BLITTER MAIN STATE MACHINE  -----------------------------------------------
	BL_SM.CLK = DDRCLK0;
	SRC_OLD[].CLK = DDRCLK0;
	SRC_OLD[] = SRC_ADR32[31..4];
	SDXINC.CLK = DDRCLK0;
	CASE BL_SM IS
		WHEN START =>   ------------------------- START
			BL_NOTRUN = VCC;			-- BLITTER NOT RUN
			IF BLITTER_ON & BL_START & (BL_X_CNT[] > X_CNT16[]) & (BL_Y_CNT[] > Y_INDEX[]) THEN	-- STARTEN?
				BL_SM = NEW_LINE;									-- JA START
			ELSE
				BL_SM = START;										-- NICHT STARTEN
			END IF;
		WHEN NEW_LINE => ----------------------- NEU LINIE
			X_INDEX_CLR_DIR = VCC;									-- JA -> X INDEX LÖSCHEN FÜR START LINE 			
			IF SRC_READ THEN										-- SOURCE READ NÖTIG?
				BL_SM = RDSRC3;										-- JA							
			ELSE
				BL_SM = RDDST;										-- NEIN -> DIREKT ZU READ DEST
			END IF;
		WHEN RDSRC3 =>  ------------------------ READ SRC3
			BLITTER_ADR[31..4] = SRC_ADR32[31..4] - 1 + (2 & BL_SRC_X_INC15);
			BLITTER_REQ = VCC;
			BL_READ_SRC = VCC;								-- LATCH UND SB1->SB2
			IF BLITTER_DACK0 THEN
				BL_SM = RDSRC2;
			ELSE	
				BL_SM = RDSRC3;
			END IF;
		WHEN RDSRC2 =>  ------------------------- READ SRC2
			BLITTER_ADR[31..4] = SRC_ADR32[31..4];
			BLITTER_REQ = VCC;
			BL_READ_SRC = VCC;									-- LATCH UND SB1->SB2
			IF BLITTER_DACK0 THEN
				BL_SM = RDSRC1;
			ELSE	
				BL_SM = RDSRC2;
			END IF;
		WHEN RDSRC1 =>	------------------------ READ SRC1
			BLITTER_ADR[31..4] = SRC_ADR32[31..4] + 1 - (2 & BL_SRC_X_INC15);
			BLITTER_REQ = VCC;
			BL_READ_SRC = VCC;								-- LATCH UND SB1->SB2
			SRC_OLD[].ENA = VCC;
			IF BLITTER_DACK0 THEN
				BL_SM = RDDST;
			ELSE	
				BL_SM = RDSRC1;
			END IF;
		WHEN RDDST =>	------------------------ READ DEST
			BLITTER_ADR[31..4] = DST_ADR32[31..4];
			IF NOT_DST_READ THEN
				BL_SM = WRDSTW;
			ELSE
				BLITTER_REQ = VCC;
				BL_READ_DST = VCC;
				IF BLITTER_DACK0 THEN
					BL_SM = WRDSTW;
				ELSE	
					BL_SM = RDDST;
				END IF;
			END IF;
		WHEN WRDSTW =>	 ------------------------ KURZ WARTEN AUF ERGEBNIS
			BLITTER_ADR[31..4] = DST_ADR32[31..4];
			BL_SM = WRDST;
		WHEN WRDST =>	------------------------- WRITE DEST
			BLITTER_ADR[31..4] = DST_ADR32[31..4];
			BLITTER_WR = VCC;
			BLITTER_REQ = VCC;
			SDXINC = BLITTER_DACK2;									-- INCCREMENT SRC, DST, X_INDEX
			IF BLITTER_DACK0 THEN
				BL_SM = TESTZEILENENDE;
			ELSE	
				BL_SM = WRDST;
			END IF;
		WHEN TESTZEILENENDE =>	----------------- ZEILENDE?
			IF X_CNT16[] >= BL_X_CNT[] THEN							-- SCHON ZEILENENDE? 	
				YIINC = VCC;										-- JA -> INC Y-INDEX
				BL_SM = TESTFERTIG;									-- => TEST OB FERTIG
			ELSE
				IF !SRC_READ THEN									-- KEIN SOURCE READ?
					BL_SM = RDDST;									-- JA => LESEN UNNÖTIG ->
				ELSE
					IF SRC_ADR32[31..4] == SRC_OLD[] THEN			-- ADRESSE IMMER NOCH IN DER LINE?
						BL_SM = RDDST;								-- DATEN SIND GÜLTIG -> READ DEST
					ELSE
						BL_SM = RDSRC1;								-- SONST NEXT SRC
					END IF;
				END IF;
			END IF;	
		WHEN TESTFERTIG =>	--------------------- TEST AUF FERTIG
			ZAINC = VCC;											-- ZEILENENDE: INC SRC UND DST ADRESSEN 
			IF Y_INDEX[] >= BL_Y_CNT[] THEN							-- LETZTE ZEILE?
				BL_SM = FERTIG;										-- JA => FERTIG
			ELSE
				BL_SM = NEW_LINE;									-- NEIN => NEXT LINE
			END IF;
		WHEN FERTIG => -------------------------- FERTIG
			BL_NOTRUN = VCC;										-- BLITTER NOT RUN
			BLITTER_INT = VCC;										-- BLITTER INTERRUPT
			LN7_CLR = VCC;											-- BUSY BIT LÖSCHEN
			IF (BL_LN7 == 0) & (BL_START == 0) THEN			-- WARTEN BIS GELÖSCHT (SYNC MIT 33MHz)
				BL_SM = START;	
			ELSE
				BL_SM = FERTIG;
			END IF;
		WHEN OTHERS =>
			BL_SM = FERTIG;
	END CASE;
END;

