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

// 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 Ram (dataout, addr, datain,csn,rwn);

output dataout;
reg [3:0]dataout;
input [3:0]addr;
input [3:0]datain;
input csn;				// chip select; negative logic
input rwn;

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

integer i;

initial					// on starting life, zero out memory
begin
	for (i=0; i<16; i=i+1)
		memarr[i] = 4'b0000;
	dataout = 4'bzzzz;
end

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

always @ (rwn or addr or csn)		// what should be the trigger?
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
	end
	else
		#`MEMDELAY dataout = 4'bzzzz;
end

endmodule
