module ICACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, PTE_ACC,
				   USE_CA, PTB_WR, PTB_SEL, USER, PROT_ERROR,
				   DRAM_ACC, IO_RD, IO_ACC, IC_PREQ, ACC_OK, HIT_ALL, CUPDATE, AUX_DAT, NEW_PTB, PTB_ONE );

	input			BCLK;
	input			BRESET;
	input			IO_SPACE;
	input			MDONE;		// Memory Done : Feedback from DRAM Controller, BCLK aligned
	input			IO_READY;
	input			MMU_HIT,CA_HIT;
	input			READ;
	input			PTE_ACC;
	input			USE_CA;
	input			PTB_WR,PTB_SEL;
	input			USER;
	input			PROT_ERROR;
	
	output	reg		DRAM_ACC,IO_RD;
	output			IO_ACC;
	output			IC_PREQ;
	output			ACC_OK;
	output			HIT_ALL;
	output			CUPDATE;
	output			AUX_DAT;
	output	reg		NEW_PTB,PTB_ONE;
	
	reg		 [3:0]	new_state;
	reg				rd_done;
	reg				card_flag;
	reg				rd_rdy;

	wire			io_busy;
	wire			dram_go;
	wire			rd_ende;
	wire			do_ca_rd;
	
// Cycle :			/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_
// Access :			_/-----------------------------------\__
// State Machine :  ____/----------------------------\______
//							Busy status ...

	assign rd_ende = CA_HIT | rd_rdy;	// CA_HIT only if Cache activ !

	always @(	 READ	 	// only READ , global control
			  or PROT_ERROR	// is not allowed !
			//
			  or IO_SPACE	// indicates access in the IO_WELT
			  or io_busy	// is already active ?
			//
			  or MMU_HIT	// Hit in the MMU , now only a READ can be active
			  or rd_ende	// Cache Hit
			  or DRAM_ACC	// DRAM Access running
			//
			  or PTE_ACC )	// PTE Access running
			//				  #_#			   #_#						#_#
		casex ({READ,PROT_ERROR,IO_SPACE,io_busy,MMU_HIT,rd_ende,DRAM_ACC,PTE_ACC})
		// MMU Miss : PTE load from memory 
		  8'b10_xx_0xx_0 : new_state = 4'b0100;	// start PTE access
	  	// IO-Address selected : external access starts if not already BUSY
		  8'b10_10_1xx_x : new_state = 4'b0001;
		// DRAM Access : Cache Miss at READ
		  8'b10_0x_100_x : new_state = 4'b1010;	// can start directly
		  default 		 : new_state = 4'b0;
		endcase
		
	assign IO_ACC   = new_state[0];	// to load the Register for Data and Addr
	assign dram_go  = new_state[1];
	assign IC_PREQ  = new_state[2];	// MMU to DCACHE !
	assign do_ca_rd = new_state[3];
	
	assign HIT_ALL = MMU_HIT & CA_HIT;	// for Update "Last-Set" , MMU_HIT contains ZUGRIFF
	
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) card_flag <= 1'b0;
			else card_flag <= (do_ca_rd & ~rd_rdy) | (card_flag & ~MDONE);
	
	assign CUPDATE = card_flag & USE_CA & MDONE;	// USE_CA = ~CI & ~LDC;
	
	always @(posedge BCLK) rd_rdy <= card_flag & MDONE;	
	
	// The cache RAM can not provide fast enough the data after an Update. In this case a secondary data path is activated
	assign AUX_DAT = rd_rdy;
	
	// DRAM Interface :

	always @(posedge BCLK) if (dram_go) DRAM_ACC <= 1'b1;
							 else
								DRAM_ACC <= DRAM_ACC & ~MDONE & BRESET;
	// IO Interface :
	
	always @(posedge BCLK)
	  begin
		if (IO_ACC) IO_RD <= READ;  else IO_RD <= IO_RD & ~IO_READY & BRESET;
	  end
	  
	assign io_busy = IO_RD | rd_done;	// access is gone in next clock cycle, therefore blocked with "rd_done"
	
	always @(posedge BCLK) rd_done <= READ & IO_READY;	// For READ one clock later for data to come through
	
	// global feedback to opcode fetch unit : you can continue
	
	assign ACC_OK = IO_SPACE ? rd_done : (READ & MMU_HIT & rd_ende);
	
	// PTB1 und PTB0
	
	always @(posedge BCLK) NEW_PTB <= PTB_WR;			// to MMU Update Block
	always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
	
endmodule