`define WSIZE 4
`define MEMSIZE 16
`define MEMDELAY 0
`define WARNINGS


// Synchronous Memory module
//---------------------------------------------------------
// Models an asynchronous word-addressible RAM
// works in negative logic.ie, chip is selected if csn is 0.
// rwn = 1 => read
// rwn = 0 => write
//--------------------------------------------------------- 

module Syncram (databus, addr, csn, 
		rwn, clk, reset);

inout [3:0] databus;
wire [3:0] databus;
input [3:0]addr;
input csn;				// chip select; negative logic
input rwn;				// read write bit; neg logic; 1 ==> read
input clk;
input reset;
reg [3:0] dataout;
wire [3:0] datain;

reg[3:0] memarr[0:15];	// the actual memory array

integer i;

task resetmem;
begin
for (i=0; i<16; i=i+1)
	memarr[i] = 4'b0000;
dataout=4'bzzzz;
end
endtask

initial					// on starting life, zero out memory
begin
	resetmem;
end


// make the tristate connections
bufif1 bin0(datain[0], databus[0], ~rwn&~csn&reset);
bufif1 bin1(datain[1], databus[1], ~rwn&~csn&reset);
bufif1 bin2(datain[2], databus[2], ~rwn&~csn&reset);
bufif1 bin3(datain[3], databus[3], ~rwn&~csn&reset);

bufif1 bout0(databus[0], dataout[0], rwn&~csn&reset);
bufif1 bout1(databus[1], dataout[1], rwn&~csn&reset);
bufif1 bout2(databus[2], dataout[2], rwn&~csn&reset);
bufif1 bout3(databus[3], dataout[3], rwn&~csn&reset);

task dumpmem;
for (i=0; i<16; i=i+1)
	$display ("mem[%0d] = %b", i, memarr[i]);
endtask

always @ (negedge reset)
	resetmem;

always @ (negedge clk)
#1
if (reset)
begin
	if (!csn)
	begin
		if (&addr === 1'bx)			// some bit of addr is z
		begin
			`ifdef WARNINGS_ON
			$display ("invalid address passed to memory");
			`endif
		end
		else
		begin
			if (rwn)				// read
				#`MEMDELAY dataout = memarr[addr];
			else if (!rwn)
			begin
				#`MEMDELAY memarr[addr] = datain;
				#`MEMDELAY dataout = 4'bzzzz;
			end
			else		// rwn is 'z'
				#`MEMDELAY dataout = 4'bzzzz;
		end
	//if(addr == 4'b0010)
		$display($time," mem : %b %b %b %b %b %b",
				rwn,csn,reset,databus, addr, memarr[addr]);
	end
	else
		#`MEMDELAY dataout = 4'bzzzz;

//$display($time," Address: %b rwn: %b databus:%b",
//					addr,rwn,databus); 		
//dumpmem;
//$display("");
end
endmodule
// vim: ts=4 sw=4
