module SRAM (BCLK, BRESET, CESRAM, WRITE, AA, BE, DIN, READY, SRAM_Q, SRCO, SRAA, SRDB);

	input			BCLK;
	input			BRESET;
	input			CESRAM;
	input			WRITE;
	input	[18:1]	AA;
	input	 [3:0]	BE;
	input	[31:0]	DIN;
 
	output			READY;
	output	[31:0]	SRAM_Q;

	output	reg	 [4:0]	SRCO;
	output	reg	[17:0]	SRAA; // Word Address
	inout		[15:0]	SRDB;
 
	reg		[15:0]	do_reg;
	reg		 [2:0]	state;
	reg		[17:0]	save_aa;
	reg		 [1:0]	top_be,save_be,muxbe;
	reg		[15:0]	top_do,save_do,muxdo;
	reg		[15:0]	di_reg,pipe_reg;
	reg		[15:0]	oe_reg;
 
	wire			twoa;
	wire	[17:0]	muxadr;
	
	genvar			i;
  
	assign twoa = (BE[3] | BE[2]) & (BE[1] | BE[0]); // two Accesses
 
	always @(posedge BCLK or negedge BRESET)
	  if (!BRESET) state <= 3'd0;
		else
		  casex ({CESRAM,WRITE,twoa,state})
			6'b0x_x_000 : state <= 3'b000; // nothing to do
			6'b10_1_000 : state <= 3'b001;
			6'b10_0_000 : state <= 3'b010;
			6'b11_1_000 : state <= 3'b100;
			6'b11_0_000 : state <= 3'b110;
			// Read
			6'bxx_x_001 : state <= 3'b010;
			6'bxx_x_010 : state <= 3'b011;
			6'bxx_x_011 : state <= 3'b000; // Send READY
			// Write
			6'bxx_x_100 : state <= 3'b101;
			6'bxx_x_101 : state <= 3'b110;
			6'bxx_x_110 : state <= 3'b000; // State 7 at WRITE overlaps with State 0
			default		: state <= 3'b000;
		  endcase

	always @(posedge BCLK) save_aa <= muxadr;
  
	assign muxadr[17:1] = (CESRAM & (state == 3'd0)) ? AA[18:2] : save_aa[17:1];
	assign muxadr[0]   = (CESRAM & (state == 3'd0)) ? AA[1] : ( ((state == 3'd1) | (state == 3'd5)) ? 1'b1 : save_aa[0] );

	always @(posedge BCLK) SRAA <= muxadr;
 
	always @(posedge BCLK) if (!state[2]) top_be = ~BE[3:2];
	always @(posedge BCLK) save_be <= muxbe;
 
	always @(*)
	  casex ({CESRAM,state})
		4'b0_000 : muxbe = 2'b11;
		4'b1_000 : muxbe = AA[1] ? ~BE[3:2] : ~BE[1:0]; // READ has valid BE's
		4'bx_001 : muxbe = ~BE[3:2]; // READ is still active
		4'bx_101 : muxbe = top_be;
		4'bx_010 : muxbe = 2'b11; // State = 2 is End for READ !
		default  : muxbe = save_be;
	  endcase
  
	always @(posedge BCLK) SRCO[1:0] <= muxbe;
 
	always @(posedge BCLK) if (!state[2]) top_do <= DIN[31:16];
	always @(posedge BCLK) save_do <= muxdo;

	always @(*)
	  casex ({CESRAM,state})
		4'b1_000 : muxdo = AA[1] ? DIN[31:16] : DIN[15:0]; // READ has valid BE's
		4'bx_101 : muxdo = top_do;
		default  : muxdo = save_do;
	  endcase

	always @(posedge BCLK) do_reg <= muxdo;

	// Control Signals
	always @(posedge BCLK) SRCO[4] <= ~((CESRAM & (state == 3'd0)) | (state == 3'd1) | (state == 3'd4) | (state == 3'd5) | (state == 3'd6)); // CE
	always @(posedge BCLK) SRCO[3] <= ~((CESRAM & ~WRITE & (state == 3'd0)) | (state == 3'd1)); // OE
	always @(negedge BCLK) SRCO[2] <= ~((state == 3'd4) | (state == 3'd6)); // WE
 
	always @(posedge BCLK) oe_reg <= {16{(CESRAM & WRITE & (state == 3'd0)) | (state == 3'd4) | (state == 3'd5) | (state == 3'd6)}};
 
	generate
		for (i=0;i<=15;i=i+1)
			begin: oectrl
				assign SRDB[i] = oe_reg[i] ? do_reg[i] : 1'bz;
			end
	endgenerate
	
	always @(posedge BCLK) di_reg <= SRDB; // Fast Input Register
	always @(posedge BCLK) pipe_reg <= di_reg;
 
	assign SRAM_Q = {di_reg,(twoa ? pipe_reg : di_reg)};
	assign READY  = CESRAM & (WRITE ? (state == 3'd0) : (state == 3'd3));
 
endmodule