//--------------------------------------------------------------------------------------------------
//
// Title       : Interface
// Design      : U4
// Author      : mbari###
// Company     : MBARI
//
//-------------------------------------------------------------------------------------------------
//
// File        : C:\Projects\genosensor\2g\CPLDs\Core\U4\src\Interface.v
// Generated   : Tue Dec 16 13:43:36 2003
// From        : interface description file
// By          : Itf2Vhdl ver. 1.20
//
//-------------------------------------------------------------------------------------------------
//
// Description : 
//
//-------------------------------------------------------------------------------------------------
`timescale 1ps / 1ps

//{{ Section below this comment is automatically maintained
//   and may be overwritten
//{module {Interface}}
module Interface ( inDATA ,outDATA ,Reset ,AS ,AD ,RD ,Mclk ,ASleading ,WR ,ADDR );

input WR ;
wire WR ;
input [7:0] outDATA ;
wire [7:0] outDATA ;
input Reset ;
wire Reset ;
input AS ;
wire AS ;
input RD ;
wire RD ;
input Mclk ;
wire Mclk ;

output ASleading ;
wire ASleading ;
output [7:0] inDATA ;
wire [7:0] inDATA ;
output [7:0] ADDR ;
wire [7:0] ADDR ;

inout [7:0] AD ;
wire [7:0] AD ;

//}} End of automatically maintained section

// -- Enter your statements here -- //

//The core PLD currently uses address range 0 - F
`define CORE_PLD_RANGE 8'h0F   

//This is the register which lathces the address off the bus
reg [7:0] ADDR_reg;					
//this register is used to deterine if at the end of a RD or WR 
//should the address register begin incermented
//to preform an auto incement leave 
//output the AS strobe low while strobing read and write.
//This line is sampled at the leading edge of rd or wr.
//if this line is active then on the trailing edge 
//of rd or wr the address register will begin incremented.
reg AutoInc;									
//this register is used to locate the rising edge of AS
reg ASedge;	 
//this is used to find the falling and rising edge of RD or WR
reg WRRDedge;

//this iskept to reduce system usage
//synthesis attribute keep of Enable_AD is true;
wire Enable_AD;	 
wire ADDR_in_Range;	  

//wire Enable_DATA;

assign ADDR = ADDR_reg;

 //drive the AD bus only if within this pld's range
assign Enable_AD = ((WR) & (!RD) & ADDR_in_Range);
assign ADDR_in_Range = (ADDR_reg <= `CORE_PLD_RANGE );
assign ASleading = !AS & ASedge;  //True when the AS is falling, which is the leading edge
//this is old stuff
//assign Enable_AD = ((!AS) & (!WR) & (RD) & (ADDR <= `CORE_PLD_RANGE));
//assign Enable_DATA = ((WR) & (ADDR <= `CORE_PLD_RANGE));
//assign AD = Enable_AD ? DATA : 8'bz;  
//assign DATA = Enable_DATA ? AD : 8'bz;

assign inDATA = AD;
assign AD = (Enable_AD) ? outDATA : 8'bz;

always @ (negedge Mclk)
	begin
		ASedge <= AS;
		WRRDedge <= WR & RD; //because they are active low!
		if (Reset) ADDR_reg <= 8'b0;
		else if (ASleading & RD & WR) ADDR_reg <= AD; //Latch the Address off the bus 
			//this is the auto inc.  On falling edge of RD or WR and the auto inc bit is set then add one to the address
		else if (((RD & WR) & !WRRDedge & AutoInc & ADDR_in_Range)) ADDR_reg <= (ADDR_reg < `CORE_PLD_RANGE) ? ADDR_reg + 8'd1 : ADDR_reg <= 8'b0;
			//leading edge of RD or WR, sample AS to determine if a Autoinc cycle
	    if (!(RD & WR) & WRRDedge)  AutoInc <= !AS;
		
	end
endmodule
